I've developed a Xamarin.Forms.Shell app containing 4 tabs.
I would like to add a basic audio player allowing to play music from a streaming source.
But I'm looking to the best way to manage it:
I don't want to display it in a dedicated page, as I don't get the metadata of the audio (no album photo, no title, no author, ...) and there are no "Play Next" or "Play Previous" features
I would like to display a basic view appearing at the bottom and above of the main page, containing 3 buttons (play or pause/stop/close) and the name of the radio
I would like to do something like this:
But I don't know what is the better approach to achieve this:
use a Drawer like SimpleBottomDrawer
use a Slide like SlideOverKit
use a Sheet like BottomSheet
All of these solution seem too complicated for my needs.
Is there another approach?
Here is the solution I've implemented.
By default, I display a Floating Action Button, that will show the radio player control panel.
In this panel, I have the "play"/"stop" controls, the radio title, and a "close" button to hide the panel.
The radio player control panel is hidden by default by applying a TranslationY
The XAML looks like this:
<Grid>
<!-- FloatingActionButton -->
<yummy:PancakeView x:Name="RadioFab"
CornerRadius="28"
Padding="16"
BackgroundColor="{StaticResource AccentColor}"
VerticalOptions="End"
HorizontalOptions="End"
Margin="25">
<yummy:PancakeView.Shadow>
<yummy:DropShadow Offset="1,2"
Color="{StaticResource Gray-Black}"
BlurRadius="2"
Opacity="0.2"/>
</yummy:PancakeView.Shadow>
<Image HeightRequest="24" WidthRequest="24">
<Image.Source ... />
</Image>
<yummy:PancakeView.GestureRecognizers>
<TapGestureRecognizer Tapped="RadioFab_Clicked" />
</yummy:PancakeView.GestureRecognizers>
</yummy:PancakeView>
<!-- Radio player view
<yummy:PancakeView x:Name="RadioPlayerView"
VerticalOptions="End"
HeightRequest="56"
BackgroundColor="{StaticResource Gray-400}"
Opacity="0.9"
TranslationY="56"
IsVisible="True">
<!-- content ... -->
</yummy:PancakeView>
<Grid>
When the Floating Action Button is clicked, I call the TranslateTo() method, allowing me to display the panel, and to get the expected behaviour.
The code-behind looks like this:
private void RadioFab_Clicked(object sender, EventArgs e)
{
this.RadioFab.ScaleTo(0, easing: Easing.Linear);
this.RadioPlayerView.TranslateTo(0, 0, 300);
}
void Player_CloseButton_Clicked(System.Object sender, System.EventArgs e)
{
this.RadioPlayerView.TranslateTo(0, 56, 300);
this.RadioFab.ScaleTo(1, easing: Easing.SpringOut);
}
Related
I've implemented Borderless Editor in my Xamarin.Forms application using Custom EditorRenderer. But I'm facing an issue that the editor text is not selectable at all in both cases, neither in Forms editor control nor in Rendered native editor control. My app has the functionality to let user copy paste the text in the editor while typing, like in any other text editing app. This is a basic feature in most of the apps and is by default there. But it's not working in my app. I've tried enabling it through
Control.SetTextIsSelectable(true);
but still it's not working. I've tried other things too, like:
Control.CustomSelectionActionModeCallback = new
CustomSelectionActionModeCallback();
Control.CustomInsertionActionModeCallback = new CustomInsertionActionModeCallback();
But nothing is working at all and text is not getting selected even a single word. Does anyone has any idea about this issue? How can I make the text selectable and allow default copy paste feature in custom editor?
Here's my code in Xaml:
<renderer:BorderlessEditor
Grid.Row="1"
x:Name="UserTextEditorAndroid"
BackgroundColor="{StaticResource WhiteColor}"
HeightRequest="350"
Margin="20,2"
MaxLength="1024"
IsReadOnly="{Binding Source={x:Reference LongTextTemplate}, Path=Editable, Converter={StaticResource InverseBool}}" />
And the custom render code is:
public class BorderlessEditorRenderer : EditorRenderer
{
public BorderlessEditorRenderer()
{
}
public static void Init() { }
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
Control.Background = null;
var layoutParams = new MarginLayoutParams(Control.LayoutParameters);
layoutParams.SetMargins(0, 0, 0, 0);
LayoutParameters = layoutParams;
Control.LayoutParameters = layoutParams;
Control.SetPadding(0, 0, 0, 0);
SetPadding(0, 0, 0, 0);
Control.SetTextIsSelectable(true);
Control.VerticalScrollBarEnabled = false;
}
}
}
Even if I use Xamarin.Forms own editor in Xaml instead of custom renderer then also it doesn't work at all. The text is still un-selectable.
I am having the same problem - but I'm not using Telerik. I'm running VS 2019 on Win 10. This is easy to repro ...
Create a new "Mobile App (Xamarin Forms)" and simply add an Editor to the MainPage.xaml file. I also put the Editor inside a ScrollView for kicks. The code below only shows a few words of text placed in the Editor, but I actually used a long paragraph from the Microsoft docs. I left that out below so as to simplify code presentation ... and avoid a mess!
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Editor_Test.MainPage">
<StackLayout>
<!-- Place new controls here -->
<ScrollView>
<Editor Text="Visual Studio makes it easier ..."
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand" />
</ScrollView>
</StackLayout>
</ContentPage>
I get normal behavior:
Because of the ScrollView, I can scroll the text with a finger (mouse) drag
A long press (click) selects the word pressed
A double tap (click) selects the word tapped
I get different results if I change 1 line of code in the App ctor, in App.xaml.cs, to instantiate the MainPage with a NavigationPage, like so:
public App()
{
InitializeComponent();
//MainPage = new MainPage();
MainPage = new NavigationPage(new MainPage());
}
Now the behavior changes:
A long press (click) has no effect (no selection)
A double tap (click) has no effect (no selection)
In fact there is no way at all that I can see to select text in the Editor. I don't know why this happens ... but it does. It drove me a bit mad until I realized what was causing it.
I'm using:
Xamarin Forms 4.5.0.495
Xamarin Essentials 1.3.1
Building for Android 9 (Pie)
I'm new to Android/Xamarin ... so my question is, how best to implement my own simple page navigation - ie, without using Xamarin's NavigationPage? I have a simple 3 page app I'd like to make some progress with!
Here is The Code To setting Title and Image butt ..Title Showing button Slider button not Showing
masterPage = new MasterDetailPage()
{
BackgroundColor = Color.Transparent,
Master = BuildMenuPage(),
Title = AppResources.AppNameWithPortal,
IconImageSource =new FileImageSource {File= "slideout.png" }
};
I have also try masterPage.IconImageSource ="slideout.png";
still not working
I want this Result
Try to assign icon to master page:
Xamarin forms MasterDetailPage Menu icon not shown on iOS
var masterDetailpage = new MasterDetailPage {
Master = new Page { Title = "Sample", Icon = "menuIcon.png"},
Detail = new NavigationPage(new Page())
};
I think the screenshot you shared in your question is a screenshot of Universal Windows Platform (UWP). MasterDetailPage has different behaviors in different platform. You can check the document here.
If you want the result in the screenshot, you can customize your masterPage and add event to the slideout button, something like this:
<StackLayout>
<StackLayout>
<ImageButton Source="slideout.png"></ImageButton>
<Label Text="title">
</StackLayout>
<ListView x:Name="listView" x:FieldModifier="public">
...
</ListView>
</StackLayout>
The icon or fileImageSoure you set in the Page will be displayed if supported by the platform under certain circumstances, such as when a NavigationPage is displaying a ContentPage.
Usually, detailPage has a NavigationPage and the icon and title will be displayed there in Android.
You can check the sample here to see the default behavior of MasterDetailPage in Android.
I'm having a problem with showing Dialogs from a View Model. The problem is that the "underlying content is not dimmed and disabled" as the documentation says it should be. If I click on the underlying view the button in the dialog wired to the closed command is sometimes disabled and the user is not able to click it.
I defined the DialogHost in my MainView like this (also tried it in the ShellView):
<materialDesign:DialogHost
HorizontalAlignment="Center"
VerticalAlignment="Center"
CloseOnClickAway="True" />
From my MainViewModel I show the dialog like this:
Dim errView As New ErrorView
Dim res = Await DialogHost.Show(errView)
I wired up the close command on a button in the ErrorView dialog like this:
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
You problem is with the definition of DialogHost; you have it as an empty element.
The DialogHost is a ContentControl. Everything inside is what will become dimmed. So you define it at the root of your main Window/Page XAML, a bit more like:
<materialDesign:DialogHost CloseOnClickAway="True">
<StackPanel>
<TextBlock>Hello World</TextBlock>
<TextBlock>This is the main content of my application</TextBlock>
</StackPanel>
</materialDesign:DialogHost>
I want to create a button that can show a window to show details of elements in listbox when it's clicked. the listbox itsetf was created from a list of JSONObject like this:
<listbox id="userListbox">
<listhead>
<listheader laber="Action"></listheader>
<listheader label="Id"></listheader>
<listheader label="Name"></listheader>
<listheader label="Address"></listheader>
<listheader label="Phone"></listheader>
</listhead>
<listitem forEach="${userController.list}">
<listcell>
<button label="Detail" id="detailButton"></button>
</listcell>
<listcell label="${each.id}" ></listcell>
<listcell label="${each.name}" ></listcell>
<listcell label="${each.address}" ></listcell>
<listcell label="${each.phone}" ></listcell>
</listitem>
</listbox>
for every row (listcell) there is always a button to show the details. but when I load the page, it failed to show the list with error message:
Not unique in ID space < Window cP8Q0#userWindow>: detailButton.
any idea to show a window when the button clicked? here is the code when button is clicked:
#Listen("onClick = #detailButton")
public void showModal(Event event) {
Component comp = Executions.createComponents("/widgets/window/modal_dialog/employee_dialog.zul", null, null);
if(comp instanceof Window) {
((Window)comp).doModal();
}
}
thank you for your help.
The problem is that if you click on different buttons you are running the createComponents again and again. Your employee_dialog.zul is only safe to include into the page once as it has IDs in it; if you do the operation twice you are creating a second set of components with the same ID and the IDs should be unique within a given idSpace (see the ZK developer guide for the theory).
There are other issues here: why create the components twice? Why not keep one and only one set around, showing and hiding them based on button clicks. That is more efficient.
Look at Button to Show a Window from Listbox Row which shows that you can:
<zk>
<!-- hidden -->
<window id="wnd" title="My Modal" visible="false" width="300px">
<button label="close" onClick="wnd.visible = false"/>
</window>
<!-- click button to pop the hidden window! -->
<button label="do it" onClick="wnd.doModal()"/>
</zk>
So you can use a
<include src="/widgets/window/modal_dialog/employee_dialog.zul">
to pull the model dialog into the bottom of the main page once and only once. Then in the code you can set the data into it and do
win1.doModal();
where win1 is the modal window defined in the fragment. You have to tell the model window what to display before you pop it but that is not hard. Use desktopScope.put( "myName", this) to have the controller/view-model of the dialog box register itself in a location where the controller/view-model in the main window can find it and talk to it to pass it the data to render.
Two other tips.
Hide your fragments as /WEB-INF/zul/employee_dialog.zul as anything under WEB-INF cannot be directly accessed by a browser for better security.
Try not to put any zul into your java. That is mixing behaviour with presentation. Sometimes it is unavoidable but always try first to keep the zul in the zul then interact with it via java IDs only (much like my suggestion). It is not always possible but separation of logic from layout is a core design pattern.
Simon
<button label="Detail" />
#Listen("onClick = listbox listitem listcell button")
I have a weird error which I can't figure out.
I am creating a Windows Phone 7 app where I create PivotItems on the fly that contains a ListBox.
Heres the code -
PivotItems = new ObservableCollection<StatusItem>();
DataTemplate itemTemplate = App.Current.Resources["PivotItemTemplate"] as DataTemplate;
ListBox itemBox = new ListBox();
itemBox.ItemsSource = PivotItems;
itemBox.ItemTemplate = itemTemplate;
CorePivotItem = new PivotItem() { Header = header, Content = itemBox };
Now when I ever I add objects to PivotItems, nothing ever shows up in the UI.
Sorry for not being clear the first time - Here is the DataTemplate binding -
<DataTemplate x:Key="PivotItemTemplate">
<StackPanel >
<Image Source="{Binding URL}" ></Image>
<TextBlock Text="{Binding Text}" TextWrapping="Wrap" Margin="12,-6,12,0" Style="{StaticResource PhoneTextSubtleStyle}"/>
</StackPanel>
</DataTemplate>
I am adding the PivotItems to another OC which is binding to a Pivot control. All listings show up fine when I flick across PivotItems. Basically what I am guessing is that the OC is not triggering a refresh on the ListBox. Could I potential use BindingExpressions to force Refresh the list?
Your code doesn't show adding the newly create PivotItem to the Pivot. Is this what you're not doing.
This does of course assume that CorePivotItem is not already defined elsewhere.
Can you show your XAML and other C# code so we get the full picture.