Popup AlertDialog with a seekBar to change app volume - android-seekbar

I am new to Android and I need to create an AlertDialog when I press an specific button. AlertDialog has a Seekbar and the seekBar is used to change the volume for my application. But I cannot make it work. Can you please help me? Thank you.
I get this error :
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.SeekBar.setMax(int)' on a null object reference
and my code looks like this:
public class Setting extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_setting);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
public AlertDialog AlarmVolume(View view) {
/*
This part of code creates a dialog which has a seekbar for volume.
*/
AlertDialog.Builder builder = new AlertDialog.Builder(this);
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.volume_dialog, (ViewGroup) findViewById(R.id.settingsItem));
builder.setView(v).setTitle("Adjust Alarm Volume").setPositiveButton("OK", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
//TODO save new volume amount
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
}
});
SeekBar seekbarVolume = (SeekBar)findViewById(R.id.volumeSeekBar);
final AudioManager audioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
seekbarVolume.setMax(audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM));
seekbarVolume.setProgress(audioManager.getStreamVolume(AudioManager.STREAM_ALARM));
seekbarVolume.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, progress, 0);
}
});
return builder.create();
}
}
and this is my volum_dialog.xml file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SeekBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/volumeSeekBar"
android:layout_marginTop="15sp"
android:layout_weight="1" />
</LinearLayout>

You are trying to find your seekbar in your contextView (R.layout.activity_setting):
SeekBar seekbarVolume = (SeekBar)findViewById(R.id.volumeSeekBar);
It returns null because you created your SeekBar dynamically for your AlertDialog:
View v = inflater.inflate(R.layout.volume_dialog, (ViewGroup) findViewById(R.id.settingsItem));
To solve this issue, change this line (SeekBar)findViewById(R.id.volumeSeekBar); to:
(SeekBar) v.findViewById(R.id.volumeSeekBar);
It tries to find your Seekbar in View v instead of ContextView which should work fine.

Related

Customizing the custom picker in Xamarin

I hope everyone is doing great. Can someone help me on how can I remove the 'cancel' and 'Ok' buttons and allow/raise an event selection if I release the mouse on the item on the screen, Secondly I need help with changing the color of the borderlines and background color? I will appreciate your help thanks.
Picker :
public class BorderlessPickerRenderer : PickerRenderer
{
public static void Init() { }
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (e.OldElement == null)
{
Control.Background = Android.Graphics.Color.Rgb();
string fontFamily = e.NewElement?.FontFamily;
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);
}
}
}
You could use Custon Remderer to define a custom Dialog.
how can I remove the 'cancel' and 'Ok' buttons and allow/raise an event selection if I release the mouse on the item on the screen,
The AlertDialog provides SetNegativeButton event to set the cancel and Ok button. Remove both in the view would be okay. The custom view is a listview. You could use the ItemClick of ListView.
Secondly I need help with changing the color of the borderlines and background color?
You could set the background color of the dialog to change. Add the android:divider to set the borderline color. And add the android:dividerHeight to set the borderline height.
Custom Renderer:
[assembly: ExportRenderer(typeof(Picker), typeof(BorderlessPickerRenderer))]
namespace App15.Droid
{
public class BorderlessPickerRenderer : PickerRenderer
{
AlertDialog listDialog;
string[] items;
public BorderlessPickerRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Picker> e)
{
base.OnElementChanged(e);
if (Control != null)
{
Control.Click += Control_Click1; ;
}
}
private void Control_Click1(object sender, EventArgs e)
{
Picker model = Element;
items = model.Items.ToArray();
AlertDialog.Builder builder = new AlertDialog.Builder(this.Context);
builder.SetTitle(model.Title ?? "");
//builder.SetNegativeButton("Cancel", (s, a) =>
//{
// Control?.ClearFocus();
// builder = null;
//});
Android.Views.View view = LayoutInflater.From(this.Context).Inflate(Resource.Layout.listview, null);
Android.Widget.ListView listView = view.FindViewById<Android.Widget.ListView>(Resource.Id.listView1);
MyAdapter myAdapter = new MyAdapter(items, Element.SelectedIndex);
listView.Adapter = myAdapter;
listView.ItemClick += ListView_ItemClick;
builder.SetView(view);
listDialog = builder.Create();
listDialog.Window.DecorView.SetBackgroundColor(Android.Graphics.Color.Pink); // set the dialog background color
listDialog.Show();
//Android.Widget.Button button = listDialog.GetButton((int)DialogButtonType.Negative);
//button.Text = "Cancel";
//button.Click += Button_Click;
//button.SetTextColor(Android.Graphics.Color.Blue); // set the button bottom color
}
//private void Button_Click(object sender, EventArgs e)
//{
// listDialog.Dismiss();
// listDialog = null;
//}
private void ListView_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
Control.Text = items[e.Position];
Element.SelectedIndex = e.Position;
Console.WriteLine(items[e.Position]);
listDialog.Dismiss();
listDialog = null;
}
class MyAdapter : BaseAdapter
{
private string[] items;
private int selectedIndex;
public MyAdapter(string[] items)
{
this.items = items;
}
public MyAdapter(string[] items, int selectedIndex) : this(items)
{
this.selectedIndex = selectedIndex;
}
public override int Count => items.Length;
public override Java.Lang.Object GetItem(int position)
{
return items[position];
}
public override long GetItemId(int position)
{
return position;
}
public override Android.Views.View GetView(int position, Android.Views.View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.listview_item, null);
}
TextView textView = convertView.FindViewById<TextView>(Resource.Id.textView1);
textView.Text = items[position];
return convertView;
}
}
}
}
Xaml:
<Picker x:Name="picker" Title="Title" VerticalOptions="CenterAndExpand" >
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Option 1</x:String>
<x:String>Option 2</x:String>
<x:String>Option 3</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
listview.xml: You could creat in your Resources/layout in android project.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
android:id="#+id/listView1"
android:divider="#android:color/holo_green_light"
android:dividerHeight="2dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
listview_item.xml : You could creat in your Resources/layout in android project.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>

Java wear os Scroll WearableRecyclerView by digital crown

My list is not scrolling when I use digital crown
This is what I do ;
<androidx.wear.widget.WearableRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/wrv_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
/>
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.wrv_demo);
WearableRecyclerView wrv = findViewById(R.id.wrv_container);
wrv.setLayoutManager(new WearableLinearLayoutManager(this));
wrv.setAdapter(new DemoAdapter());
wrv.setHasFixedSize(true);
wrv.setCircularScrollingGestureEnabled(true);
wrv.setEdgeItemsCenteringEnabled(true);
wrv.setOnGenericMotionListener(new View.OnGenericMotionListener() {
#Override
public boolean onGenericMotion(View view, MotionEvent motionEvent) {
return false;
}
});
wrv.setBezelFraction(0.5f);
wrv.setScrollDegreesPerScreen(90);
}
private static class ViewHolder extends RecyclerView.ViewHolder {
TextView mView;
ViewHolder(TextView itemView) {
super(itemView);
mView = itemView;
}
}
private static class DemoAdapter extends WearableRecyclerView.Adapter<ViewHolder> {
private static final int ITEM_COUNT = 100;
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
TextView view = new TextView(parent.getContext());
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.mView.setText("Holder at position " + position);
holder.mView.setTag(position);
}
#Override
public int getItemCount() {
return ITEM_COUNT;
}
}
}
short answer:
wrv.requestFocus();
long answer:
this page outlines how to capture rotary input.
https://developer.android.com/training/wearables/ui/rotary-input
I found that my WearOS app's recyclerview worked automatically in the emulator without any of what it said on that page; however, it did not work on my watch. I implemented every step on that page and then the watch worked. Then I removed every thing on that page. For me, the only thing needed was the recyclerView.requestFocus() line.

How to take longitude and latitude in different locations using marker in maps xamarin.android

I am able to get my current location using marker but unable to set the marker into different locations and get the latitude and longitude values using marker.
public class googlemapsAc : Activity, ILocationListener, IOnMapReadyCallback
{
GoogleMap _map;
LocationManager locManager;
TextView loc1, loc2;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.mapsActivity);
loc1 = FindViewById<TextView>(Resource.Id.btn_loc);
loc1 = FindViewById<TextView>(Resource.Id.btn_loc2);
locManager = (LocationManager)GetSystemService(LocationService);
locManager.RequestLocationUpdates(LocationManager.GpsProvider, 0,0, this);
Location location = locManager.GetLastKnownLocation(LocationManager.GpsProvider);
MapFragment mapFrag = (MapFragment)FragmentManager.FindFragmentById(Resource.Id.map);
mapFrag.GetMapAsync(this);
if (location != null)
{
MarkerOptions options = new MarkerOptions();
LatLng lat = new LatLng(location.Latitude, location.Longitude);
Toast.MakeText(this,"Current location:\nLatitude: " + location.Latitude+ "\n" + "Longitude: " + location.Longitude,ToastLength.Long).Show();
options.SetPosition(lat);
p.AddMarker(options);
}
else
{
Toast.MakeText(this, "Cannot fetch current location!",ToastLength.Short).Show();
}
locManager.RemoveUpdates(this);
}
public void OnLocationChanged(Location location)
{
}
public void OnProviderDisabled(string provider)
{
throw new NotImplementedException();
}
public void OnProviderEnabled(string provider)
{
throw new NotImplementedException();
}
public void OnStatusChanged(string provider, [GeneratedEnum] Availability status, Bundle extras)
{
throw new NotImplementedException();
}
protected override void OnResume()
{
base.OnResume();
locManager.RequestLocationUpdates(LocationManager.GpsProvider, 0,0, this);
}
protected override void OnPause()
{
base.OnPause();
locManager.RemoveUpdates(this);
}
public void OnMapReady(GoogleMap googleMap)
{
_map = googleMap;
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/btn_loc" />
<TextView
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="#+id/btn_loc2" />
<fragment
android:id="#+id/map"
android:layout_height="match_parent"
android:layout_width="match_parent"
class="com.google.android.gms.maps.MapFragment" />
</LinearLayout>
in this code i am able get the current location in toast message,but when i change the location of marker i didn't get the latitude and longitude values into marker to bind that values to text view.
please help me with getting lat lang values using place markers to bind to Textview
in this code i am able get the current location in toast message,but when i change the location of marker i didn't get the latitude and longitude values into marker to bind that values to text view.
I didn't see any code about how you change the location of marker, but you can get the latitude and longitude directly from your marker for example like this:
var latitude = marker.Position.Latitude;
var longitude = marker.Position.Longitude;

SeekBar.IOnSeekBarChangeListener, seekBar can't run

A callback that notifies clients when the progress level has been changed. This includes changes that were initiated by the user through a touch gesture or arrow key/trackball as well as changes that were initiated programmatically.
Inside OnCreate
public class AudioPlayer : Activity,SeekBar.IOnSeekBarChangeListener
seekBar.SetOnSeekBarChangeListener (this);
seekBar.ProgressChanged+= (object sender, SeekBar.ProgressChangedEventArgs e) => {
int progress=(int)(utils.getProgressPercentage(player.CurrentPosition,player.Duration));
seekBar.Progress = progress;
};
public void OnStartTrackingTouch(SeekBar seekBar) {}
public void OnStopTrackingTouch(SeekBar seekBar) {}
public int getProgressPercentage(int currentDuration, int totalDuration)
{
int percentage;
int currentSeconds = (int)(currentDuration / 1000);
int totalSeconds = (int)(totalDuration / 1000);
//calculating percentage
percentage = (((int)currentSeconds) / totalSeconds) * 100;
return percentage;
}
While tracks are playing, seekBar still stops.
Think you want to do is create a timer which will update the seekBar like this:
Activity:
using System;
using Android.App;
using Android.Widget;
using Android.OS;
using Java.Lang;
using Android.Content;
using Android.Graphics.Drawables;
using Java.Util;
namespace PlayVideo
{
[Activity (Label = "PlayVideo", MainLauncher = true)]
public class Activity1 : Activity
{
VideoView videoView;
SeekBar seekBar;
System.Timers.Timer timer;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
videoView = FindViewById<VideoView> (Resource.Id.SampleVideoView);
videoView.SetMediaController(new MediaController(this));
videoView.SetVideoPath ($"android.resource://{PackageName}/{Resource.Raw.output2}");
videoView.Start ();
seekBar = FindViewById<SeekBar> (Resource.Id.seekBar);
seekBar.Max = videoView.Duration;
seekBar.StartTrackingTouch += (object sender, SeekBar.StartTrackingTouchEventArgs e) =>
{
timer.Enabled = false;
};
seekBar.StopTrackingTouch += (object sender, SeekBar.StopTrackingTouchEventArgs e) =>
{
videoView.SeekTo (e.SeekBar.Progress);
timer.Enabled = true;
};
UpdateProgressBar ();
}
private void UpdateProgressBar() {
timer = new System.Timers.Timer();
timer.Interval = 100;
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
seekBar.Progress = videoView.CurrentPosition;
seekBar.Max = videoView.Duration;
}
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<VideoView
android:id="#+id/SampleVideoView"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
<SeekBar
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/seekBar" />
</LinearLayout>
it will look like this:

MVVMCross Custom Control and Binding

I have created a custom control (CustomCard) which is a subclass of the CardView control. I would like to use this control within my project in different places.
For example, I may place the CustomCard within an xml layout manually, or I may want the CustomCard to be an item in an MvxListView. The key is that I would like to re-use the code as much as possible and benefit from having control over the CustomCard class.
When the CustomCard is instantiated, I am inflating it's layout using the standard layout inflater, see code:
using System;
using Android.Animation;
using Android.Content;
using Android.Support.V7.Widget;
using Android.Util;
using Android.Views;
using Android.Widget;
public class Card : CardView
{
private readonly Context _context;
public Card(Context context)
: base(context)
{
_context = context;
Init();
}
public Card(Context context, IAttributeSet attrs)
: base(context, attrs)
{
_context = context;
Init();
}
private void Init()
{
var inflater = (LayoutInflater) _context.GetSystemService(Context.LayoutInflaterService);
CardView = inflater.Inflate(Resource.Layout.base_card, this);
}
}
Within the layout base_card.xml, I have some elements that I would like to bind using MVVMCross, for example,
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white">
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:local="http://schemas.android.com/apk/res-auto"
android:id="#+id/basecard_title"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Title Text-->
<TextView
android:id="#+id/tv_basecard_header_title"
style="#style/card.title"
android:text="title text"
local:MvxBind="Text Title"
/>
<!-- ImageView -->
<MvxImageView
android:id="#+id/ib_basecard_header_button_expand"
style="#style/card.image"
local:MvxBind="Bitmap ImageBytes,Converter=InMemoryImage"/>
</RelativeLayout>
</FrameLayout>
My actual base_card layout is much more complex.
If I try to use my CustomCard within another XML Layout, none of the binding takes place. I think this is because I am using the standard layout inflater to inflate my base_card within my CustomCard rather than BindingInflate() but I can't be sure.
I have searched on SO and through the forums but I can't find any references to anyone using a custom control that inflates it's own view when instantiated with MVVMCross binding.
Has anyone done it, or am I trying to do something that isn't possible?
I ran into similar issue with CardView control. Since CardView directly inherits from FrameLayout I decided to use implementation almost identical to MvxFrameControl (Thanks Stuart for pointing out MvxFrameControl sample):
public class MvxCardView : CardView, IMvxBindingContextOwner
{
private object _cachedDataContext;
private bool _isAttachedToWindow;
private readonly int _templateId;
private readonly IMvxAndroidBindingContext _bindingContext;
public MvxCardView(Context context, IAttributeSet attrs)
: this(MvxAttributeHelpers.ReadTemplateId(context, attrs), context, attrs)
{
}
public MvxCardView(int templateId, Context context, IAttributeSet attrs)
: base(context, attrs)
{
_templateId = templateId;
if (!(context is IMvxLayoutInflater))
{
throw Mvx.Exception("The owning Context for a MvxCardView must implement LayoutInflater");
}
_bindingContext = new MvxAndroidBindingContext(context, (IMvxLayoutInflater)context);
this.DelayBind(() =>
{
if (Content == null && _templateId != 0)
{
Mvx.Trace("DataContext is {0}", DataContext == null ? "Null" : DataContext.ToString());
Content = _bindingContext.BindingInflate(_templateId, this);
}
});
}
protected MvxCardView(IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
protected IMvxAndroidBindingContext AndroidBindingContext
{
get { return _bindingContext; }
}
public IMvxBindingContext BindingContext
{
get { return _bindingContext; }
set { throw new NotImplementedException("BindingContext is readonly in the list item"); }
}
protected View Content { get; set; }
protected override void Dispose(bool disposing)
{
if (disposing)
{
this.ClearAllBindings();
_cachedDataContext = null;
}
base.Dispose(disposing);
}
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
_isAttachedToWindow = true;
if (_cachedDataContext != null
&& DataContext == null)
{
DataContext = _cachedDataContext;
}
}
protected override void OnDetachedFromWindow()
{
_cachedDataContext = DataContext;
DataContext = null;
base.OnDetachedFromWindow();
_isAttachedToWindow = false;
}
[MvxSetToNullAfterBinding]
public object DataContext
{
get { return _bindingContext.DataContext; }
set
{
if (_isAttachedToWindow)
{
_bindingContext.DataContext = value;
}
else
{
_cachedDataContext = value;
if (_bindingContext.DataContext != null)
{
_bindingContext.DataContext = null;
}
}
}
}
}
Usage:
<YourNamespace.MvxCardView
android:layout_width="match_parent"
android:layout_height="match_parent"
local:MvxTemplate="#layout/base_card"
local:MvxBind="DataContext ." />
Note: Using custom implementation also solved my problem with binding click command to CardView control using local:MvxBind="Click MyCommand", which wasn't working until subclassing CardView.

Resources