Xamarin Forms: Issue with MediaElement audio playing - xamarin.forms

I am using MediaElement for playing audio. I have a list of items and I need to play audio one after another. When playing audio I will change the background color of that list item. Also If I tap an item, the audio of that selected item starts playing, also the color of that item is modifying. These features are working fine in android. I have added a video of the android here.
Because of Native Crash Reporting of MediaElement, I have added a custom renderer in the ios platform. After adding the custom renderer, there are some issues while playing audio in ios. After playing the first audio, the second and third items background color is modifying. After that, the next 2 items color is modifying. I need to play items one by one.
My code:
//Xaml
<MediaElement
x:Name="audio_mediaelement"
MediaEnded="AudioEnded"
ShowsPlaybackControls="True">
<MediaElement.HeightRequest>
<OnIdiom x:TypeArguments="x:Double">
<OnIdiom.Phone>80</OnIdiom.Phone>
<OnIdiom.Tablet>120</OnIdiom.Tablet>
<OnIdiom.Desktop>80</OnIdiom.Desktop>
</OnIdiom>
</MediaElement.HeightRequest>
</MediaElement>
//Initial audio source set up
audio_mediaelement.Source = aduiourl
//When audio end
public void AudioEnded(object sender, EventArgs args)
{
audioOrder = audioOrder + 1;
if(audioOrder < listVerses.Count)
{
audio_mediaelement.Source = aduioFormat + listVerses[audioOrder].audioUrl;
ChapterList.ItemsSource = listVerses;
listVerses[audioOrder].BGColor = Color.FromHex("#f2ee71");
ChapterList.ScrollTo(((IList)ChapterList.ItemsSource)[audioOrder-1], ScrollToPosition.Start, true);
}
}
I have uploaded a sample project here for reference since it is very difficult to understand the issue without a sample. If I didn't add the MediaElement custom renderer, the app will hang after playing audio.

You could set the AutoPlay as False in default and play the video manually .
<MediaElement
HeightRequest="400"
AutoPlay="False"
x:Name="media"
MediaEnded="AudioEnded"
ShowsPlaybackControls="True">
</MediaElement>
in Code behind
Play the video after setting the url
media.Source = xxx;
media.Play();
And when want to play the next video
public void AudioEnded(object sender, EventArgs args)
{
media.Stop();
media.Source = new url;
media.Play();
}

Related

CefSharp WpfControl and rendering to image

We want to show a webpage in a chromium based browser within a wpf application.
The website that is displayed within the browser should also be shown on another screen but without interaction.
I want to combine the cefsharp wpf browser control and the cefsharp offscreen rendering.
Can I use one chromium instance for displaying the page with interactions in wpf and export the current visible website as an image?
Thank you and best regards,
Simon
Thank you amatiland, it indeed works with the OnPaint Method or Event.
public MainWindow()
{
InitializeComponent();
Browser.Paint += Browser_Paint;
}
void Browser_Paint(object sender, CefSharp.Wpf.PaintEventArgs e)
{
Bitmap newBitmap = new Bitmap(e.Width, e.Height, 4 * e.Width, System.Drawing.Imaging.PixelFormat.Format32bppRgb, e.Buffer);
var aPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "TestImageCefSharpQuant.png");
newBitmap.Save(aPath);
}
XAML
<wpf:ChromiumWebBrowser x:Name="Browser" Address="www.google.com"></wpf:ChromiumWebBrowser>

Image tint Button Android Xamarin Forms

I try to create a CustomRenderer for Android inherit to ButtonRenderer with an Image. I want change color of Image programmatically like TintColor on iOS.
For example, my CustomRenderer iOS :
public class IconButtonRenderer : ButtonRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Button> e)
{
base.OnElementChanged(e);
var button = e.NewElement;
}
public override void Draw(CoreGraphics.CGRect rect)
{
base.Draw(rect);
// Here I change color of Image in Red.
Control.ImageView.Image = Control.ImageView.Image.ImageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate);
Control.ImageView.TintColor = UIColor.Red;
}
}
On Android:
Control is an Android.Widget.Button and not have Image property but Xamarin.Forms.Button has property Image and use Android.Widget.Button for Android.
How I can access image with format Android for change color?
Image tint Button Android Xamarin Forms
Orignal Image
Solution 1 :
As #Mathias Kirkegaard said, in your ButtonRenderer you could use SetColorFilter to change color :
Control.Background.SetColorFilter(Android.Graphics.Color.Blue, PorterDuff.Mode.SrcIn);
It did work in native Android, but has some problem in Xamarin.Forms, it only changes the Button background color like this: effect. Hope someone could find a solution, and if I find a solution to solve this issue I will come back and update my answer.
Solution 2 :
You could use the plugin : Tinted Image and add a click event to implement the same feature.
Install the Plugin.CrossPlatformTintedImage nuget package
Initialize the renderer in your iOS, Android, and UWP projects as shown below:
Xamarin.Forms.Init();
TintedImageRenderer.Init();
In Xaml:
<ContentPage
...
xmlns:controls="clr-namespace:Plugin.CrossPlatformTintedImage.Abstractions;assembly=Plugin.CrossPlatformTintedImage.Abstractions"
...>
...
<controls:TintedImage x:Name="buttonImage" TintColor="Blue" Source="redDis.png"/>
...
</ContentPage>
In code, Adding a Tap Gesture Gesture Recognizer :
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += (s, e) =>
{
// handle the tap
};
buttonImage.GestureRecognizers.Add(tapGestureRecognizer);
Effect after adding a click event on Tinted Image
Solution 3 :
If you need to use ImageButton, you could refer to this solution. I didn't test it but you could use the ImageButton from XLab.
XLab ImageButton Source code
XLab ImageButtonRenderer Source code
On a button you can use "SetColorFilter(color)"
You might be able to get the color using the ContextCompat:
var color = new Color(ContextCompat.GetColor(Context, Resource.Color.Green));
and then apply it:
yourButton.SetColorFilter(color)
Not sure whether you need to use an ImageButton rather than a simple Button.

How to migrate a clickable Frame with ripple touch to Xamarin.Forms 2.5?

I have implemented a clickable Frame in Xamarin.Forms 2.3.4 with a custom FrameRenderer that set Clickable (and LongPressable FWIW) to true, subscribed the respective events and set the FrameRenderers foreground
TypedValue typedValue = new TypedValue();
this.Context.Theme.ResolveAttribute(Android.Resource.Attribute.SelectableItemBackground, typedValue, true);
this.Foreground = this.Resources.GetDrawable(typedValue.ResourceId, this.Context.Theme);
to achieve Material motion (ripple touch).
After updating to XF 2.5 (most likely as of 2.3.5, since fast renderers have been introduced with that release) my touch events have ceased to work. My custom renderer is assigned correctly, so are the Clickable and LongPressable properties, but nothing happens. Partially I have been able to work around the issue - at least for the moment - by subscribing to FrameRenderer.Touch and call OnClick from that event handler. This renders the app usable, but unfortunately lacks the visual feedback in form of the ripple touch effect.
Is there any way I can restore the original behavior? Is there any way to implement a clickable frame with ripple touch in XF 2.5?
With the help of this answer I have figured out a solution. Here's a draft of it:
First of all I store a local reference to my RippleDrawable (see documentation)
private void SetMaterialMotion()
{
TypedValue typedValue = new TypedValue();
this.Context.Theme.ResolveAttribute(Android.Resource.Attribute.SelectableItemBackground, typedValue, true);
this.Foreground = this.Resources.GetDrawable(typedValue.ResourceId, this.Context.Theme);
this._layerDrawable = this.Foreground as RippleDrawable;
}
then I have to subscribe to the Touch event
private void SubscribeClickEvent()
{
if (this.ClickableFrame.IsClickable)
{
this.Touch += ClickableFrameRenderer_Touch;
}
}
In my ClickableFrameRenderer_Touch I set the Pressed property and the hotspot of the RippleDrawable
private void ClickableFrameRenderer_Touch(object sender, TouchEventArgs e)
{
if(e.Event.Action == Android.Views.MotionEventActions.Down)
{
this.Pressed = true;
}
if(e.Event.Action == Android.Views.MotionEventActions.Up)
{
this._layerDrawable.SetHotspot(e.Event.GetX(), e.Event.GetY());
this.Pressed = false;
}
}
This will show the ripple touch motion (more or less) as expected. Of course this does not handle long presses, yet, but I'm on a way.
Anyway, this is not a solution I like very much. I still think that there has to be a supported way on making FastRenderers.FrameRenderer clickable. If anyone knows it: Please share your knowledge.

Dynamic Button Icon Windows app

I'm trying to do a pause/play button windows 10 app.
So far I know 3 ways to set the button using
button.context = "some segoe code" - works fine when I initialize it with the button but on the code to change the context the button appears as a bunch of squares
Button symbolicon - works fine initializing but no idea how to alter the symbolicon value outside of button declaration
button uri - only thing I could find online about button changing, but I don't have the button libraries that come in windows phone...
what is your recommendations so on clickrelease the button changes to either the pause or the play
I have used SymbolIcon to achieve the toggle play/pause.
XAML:
<Button Click="play_Click">
<SymbolIcon x:Name="play" Symbol="Play"/>
</Button>
C# code behind:
private void play_Click(object sender, RoutedEventArgs e)
{
if (play.Symbol.Equals(Symbol.Play))
{
play.Symbol = Symbol.Pause;
}
else if (play.Symbol.Equals(Symbol.Pause))
{
play.Symbol = Symbol.Play;
}
}
Comment if you encounter any issues.

How to configure ExpressionTextBox bindings / OwnerActivity when used in a dialog?

Our group is working on a Custom Activity Designer around our Email activity. It's a pretty straight forward designer, allow the user to enter settings / creds, but instead of cluttering the activity designer with all the settable options, we thought about putting some settings in a dialog window. (Which opens when you click the button beside the server address box).
Some of our email activity properties are InArguments so we are trying to make use of the ExpressionTextBox to display these values without much luck. The main problem is we aren't sure how to properly set up the binding and the OwnerActivity on the ExpressionTextBox. In the Activity Designer's xaml this is simply done by setting Expression=ModelItem.Property using a converter for the InArgument and setting the OwnerActivity=ModelItem, like this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="{Binding ModelItem.ServerAddress, ConverterParameter=In, Converter={StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="{x:Type system:String}" OwnerActivity="{Binding ModelItem}" Margin="2" MaxLines="1" />
If anyone has any ideas on how we could accomplish this in a dialog, please advise.
Well, this is more a WPF\MVVM question than WF4, really.
When developing custom activities designers you just have to keep one thing in mind: any change made on designer\dialog should be reflected on ModelItem. Either through XAML binding expressions or through code on ModelItem.Properties property.
Now, when and how you do it, there are several answers to that but that's really an implementation detail and depends on how you want to do it.
Lets assume you're showing the dialog on button-beside-the-server-address-box click. And lets also assume you've access to dialog textboxes through their name. At that point, you've access to ModelItem so just set its properties as needed:
private void ButtonNextToServerAddressBox_OnClick(object sender, RoutedEventArgs e)
{
var dialog = new ServerAddressEditor();
var result = dialog.ShowDialog();
if (result ?? false)
{
ModelItem.Properties["Server"].SetValue(new InArgument<string>(dialog.ServerTextBox.Text));
ModelItem.Properties["Port"].SetValue(new InArgument<string>(dialog.PortTextBox.Text));
// ... set all other properties
}
}
Now, if you are using any other pattern, or you want pure MVVM, it can be a little more tricky because of how ModelItem works. But this is a totally fine approach.
I resolved this by creating a property in the dialog's ViewModel to hold the Activity Designer's ModelItem.
public ModelItem OwnerActivity {
get { return _OwnerActivity; }
set { _OwnerActivity = value; }
}
vm.OwnerActivity = this.DataContext.ModelItem;
I then set the Xaml for the Expression Text Box in my dialog to binding to this:
<view:ExpressionTextBox HintText="Enter a VB Expression" Expression="
{Binding Path=OwnerActivity.ServerAddress, ConverterParameter=In, Converter=
{StaticResource ArgumentToExpressionConverter}, Mode=TwoWay}" ExpressionType="
{x:Type system:String}" OwnerActivity="{Binding OwnerActivity}" Margin="2"
MaxLines="1" />
Because I'm now binding directly to the ModelItem from the Activity Designer, any change made to the ModelItem property from the dialog is ALWAYS committed, even if you choose to Cancel from the dialog. To wire up the Ok/Cancel buttons so they work accordingly, I did the following in the dialog:
// declare a ModelEditingScope to make changes transactional
private ModelEditingScope _editScope;
// add this to the constructor of the dialog to begin transactional edits on the ModelItem
_editScope = editorViewModel.OwnerActivity.BeginEdit();
// ok & cancel button click event to commit or revert the changes.
private void OK_Click(object sender, RoutedEventArgs e)
{
_editScope.Complete();
this.DialogResult = DialogResult.OK;
this.Close();
}
private void Cancel_Click(object sender, RoutedEventArgs e)
{
_editScope.Revert();
this.DialogResult = DialogResult.Cancel;
this.Close()
}

Resources