Discrete seekbar in Android app? - android

I would like to create a seekbar for an Android app that allows the user to select a value between -5 and 5 (which maps to "strongly disagree" and "strongly agree"). How do I make a seekbar with discrete values? or is there a better UI widget I could use for this?
Thanks.

The Seekbar works great for discrete values. We use a Seekbar for discrete data as shown below. To show which item is selected, we just change the font of the selected text view so it is bigger. You could also highlight by changing the background color or something. It works pretty well. You will want to call setMax(11) on the seek bar, and then in your code you need to translate between the range (0 through 11) and (-5 through 5) appropriately.
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<TextView android:text="-5"
android:id="#+id/answerNegative5"
android:textSize="25sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:text="-4"
android:id="#+id/answerNegative4"
android:textSize="25sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:text="-3"
android:id="#+id/answerNegative3"
android:textSize="25sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
.....
</LinearLayout>
<SeekBar android:id="#+id/intensitySlider"
android:layout_weight="0"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>

If you want to implement discrete seekbar with number of gaps without using third party library then use style property of seekbar.
<SeekBar
android:id="#+id/sb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:thumb="#drawable/ic_location"
android:theme="#style/Widget.AppCompat.SeekBar.Discrete" />

I don't know what is the issue here, you add a seekbar having a range of 0-10. Then you can map these values to -5 if you substract -5 from the selected value.
EDIT
add android:max="10" to the xml definiton and you get a fixed size seekbar.
You maybe should consider to add a textview to denote the current selected value's textual representation such as: Strongly Disagree.
To update this view, subscribe to onProgressChanged event and progress parameter will give you the chosen number.
SeekBar s = (SeekBar) findViewById(R.id.SeekBar);
s.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar,
int progress, boolean fromUser) {
}
}

Just use the material components library with something like:
<com.google.android.material.slider.Slider
android:stepSize="1"
android:valueFrom="-5"
android:valueTo="5"
/>

I hope this code surely helpes you.
Try this...
float discrete = 0;
float start = 0;
float end = 100;
float start_pos = 0;
int start_position = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
start = -10; //you need to give starting value of SeekBar
end = 10; //you need to give end value of SeekBar
start_pos = 5; //you need to give starting position value of SeekBar
start_position = (int)(((start_pos - start) / (end - start)) * 100);
discrete = start_pos;
SeekBar seek = (SeekBar) findViewById(R.id.seekBar1);
seek.setProgress(start_position);
seek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
Toast.makeText(getBaseContext(), "discrete = " + String.valueOf(discrete), Toast.LENGTH_SHORT).show();
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// TODO Auto-generated method stub
// To convert it as discrete value
float temp = progress;
float dis = end - start;
discrete = (start + ((temp / 100) * dis));
}
});
}

1-st step : set maxVal to 10;
2-nd step :
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser)
{
switch(seekBar.getId())
{
case R.id.mySeekBar:
int prValue = progress - 5;
editText.setText(String.valueOf(preValue));
break;
}
}

<SeekBar
android:id="#+id/seekbar"
style="#style/SeekBarWithoutSteps"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="22dp"
android:layout_marginRight="22dp"
android:layout_marginTop="#dimen/margin_10"
android:max="4"
android:maxHeight="#dimen/margin_5"
android:minHeight="#dimen/margin_5"
android:paddingLeft="#dimen/margin_10"
android:paddingRight="#dimen/margin_10"
android:progressBackgroundTint="#color/colorGray"
android:progressTint="#color/colorGreen"
android:theme="#style/Widget.AppCompat.SeekBar.Discrete"
android:thumb="#drawable/filled_green"
android:thumbOffset="15dp" />

Related

Prevent Android SeekBar of drawing multiple thumbs on progress change

I'm creating an overlay dialog for my appplication, this is how it looks:
The XML:
<?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="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/ipTv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="0"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white" />
<SeekBar
android:id="#+id/volumeSeekBar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_weight="1"
android:focusable="false"
android:indeterminate="false"
android:max="63"
android:mirrorForRtl="false" />
<TextView
android:id="#+id/portTv"
style="#android:style/Theme.Dialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="63"
android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="#android:color/white" />
</LinearLayout>
The code:
if (alertDialogLayout == null) {
alertDialogLayout = View.inflate(getApplicationContext(), R.layout.volume_dialog, null);
WindowManager wm = (WindowManager) getSystemService(WINDOW_SERVICE);
DisplayMetrics dm = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(dm);
WindowManager.LayoutParams wmlp = new LayoutParams();
wmlp.gravity = Gravity.TOP | Gravity.CENTER_HORIZONTAL;
wmlp.width = dm.widthPixels / 5;
wmlp.height = LayoutParams.WRAP_CONTENT;
wmlp.y += 10;
wmlp.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT;
wmlp.flags = LayoutParams.FLAG_NOT_TOUCH_MODAL;
wm.addView(alertDialogLayout, wmlp);
}
if (volumeBar == null) {
volumeBar = (SeekBar) alertDialogLayout.findViewById(R.id.volumeSeekBar);
volumeBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
//Do some stuff
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) { }
#Override
public void onStopTrackingTouch(SeekBar seekBar) { }
});
}
Why the SeekBar adds more than one thumb? As more I drag it, more thumbs appear, until it's completely full with them. I've checked - OnSeekBarChangeListener is assigned only once. Is there any errors in the code/layout, which I'm missing and causing such strange visual behaviour?
Thanks!
I think your problem is not multiple thumbs, but multiple SeekBars, multiple alertDialogLayout and each one has a SeekBar, or multiple objects created each one creates an alertDialogLayout, So, at first make sure that you initiate the alertDialogLayout only once and also that you initiate the SeekBar only once, also make sure that you are not (some how) initiate an alertDialogLayout or a SeekBar every SeekBar progress change, and to momentarily test all of that, just change the alertDialogLayout and the SeekBar declaration to static and look if that strange behaviour disappears.

How to make double seekbar in android?

I am building an android application where the user select the a maximum value by seekbar.
I need another button on the same seekbar so that user can select maximum and minimum value from a particular unique seekbar.
Here is my code of single seek bar -
package com.ui.yogeshblogspot;
public class CustomSeekBarExActivity extends Activity implements OnSeekBarChangeListener{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
SeekBar bar=(SeekBar)findViewById(R.id.seekBar1);
bar.setOnSeekBarChangeListener(this);
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
TextView tv=(TextView)findViewById(R.id.textView2);
tv.setText(Integer.toString(progress)+"%");
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
Here is my xml code of seek bar -
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#FFFFFF">
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Choose Your Progress"
android:textColor="#000000"
android:textAppearance="?android:attr/textAppearanceMedium" />
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:progressDrawable="#xml/progress"
android:max="100"
android:thumb="#xml/thumb"/>
<TextView
android:id="#+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#000000"
android:gravity="center"
android:layout_gravity="center"
android:paddingTop="10dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>
Fully Customize two way and single way seek bar you can provide thumb color etc
http://codingsignals.com/crystal-range-seekbar-in-android/
Add in your gradle
dependencies {
compile 'com.crystal:crystalrangeseekbar:1.0.0'
}
<com.crystal.crystalrangeseekbar.widgets.BubbleThumbRangeSeekbar
android:id="#+id/rangeSeekbar5"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:corner_radius="10"
app:min_value="0"
app:max_value="100"
app:steps="5"
app:bar_color="#F7BB88"
app:bar_highlight_color="#E07416"
app:left_thumb_image="#drawable/thumb"
app:right_thumb_image="#drawable/thumb"
app:left_thumb_image_pressed="#drawable/thumb_pressed"
app:right_thumb_image_pressed="#drawable/thumb_pressed"
app:data_type="_integer"/>
The Android widget class library has only one slider control, seekbar with only one thumb control. Did some research online and found this cool custom widget, range-seek-bar.
you can followed any one of below
https://github.com/edmodo/range-bar
https://code.google.com/p/range-seek-bar/
https://github.com/Larpon/RangeSeekBar
From Here
<com.appyvet.rangebar.RangeBar
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="#+id/SearchrangeSeekbarAge"
android:layout_width="match_parent"
android:layout_height="72dp"
custom:tickStart="18"
custom:tickInterval="1"
custom:tickEnd="70" />
<com.appyvet.rangebar.RangeBar
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="#+id/SearchrangeSeekbarHeight"
android:layout_width="match_parent"
android:layout_height="72dp"
custom:tickStart="4.5"
custom:tickInterval="0.10"
custom:tickEnd="7.0" />
rangebar.setOnRangeBarChangeListener(new RangeBar.OnRangeBarChangeListener() {
#Override
public void onRangeChangeListener(RangeBar rangeBar, int leftPinIndex,
int rightPinIndex,
String leftPinValue, String rightPinValue) {
}
});
Now that RangeSlider is officially added to Material Components and supports desired options I suggest using that instead of external libraries.
First of all you should add view to your XML layout:
<com.google.android.material.slider.RangeSlider
android:id="#+id/range_seek_bar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:valueFrom="0.0"
android:valueTo="100.0"
app:values="#array/initial_slider_values"/>
then add initial slider values to arrays
<resources>
<array name="initial_slider_values">
<item>20.0</item>
<item>70.0</item>
</array>
</resources>
after that you can access RangeSlider values in code:
binding.rangeSeekBar.addOnChangeListener { slider, value, fromUser ->
Logger.d(slider.values)
}
where values is a List of floats with 2 member
You do not need to use two seekbar , but you can just do the same function of minimum and maximum by using only one seekbar with having two thumbs over it
Here its a library you can use https://code.google.com/p/range-seek-bar/
You can use by using below code
private final Thumb getClosestThumb(float touchX)
{
double xValue = screenToNormalized(touchX);
return (Math.abs(xValue - normalizedMinValue) < Math.abs(xValue - normalizedMaxValue)) ? Thumb.MIN : Thumb.MAX;
}
And in the "public boolean onTouchEvent(MotionEvent event)",
if(pressedThumb == null),
pressedThumb = getClosestThumb(mDownMotionX);
RangeSeekBar https://github.com/RanaRanvijaySingh/RangeSeekBar. Also there are other libraries available which offers a lot of customization. If you want to go for more interactive design then look for Material Range Bar http://android-arsenal.com/details/1/1272.
You can use this libraby of mine. It comes with a lots of cutomizations. It supports seeking progress in both directions.
I think this link also might be helpful .range-seek-bar .
There is an explanation about it at jitpack.io.

How to gradually change colour of a view with seek bar?

I need to change the colour of a layout using the seek bar, from 0xC4DF9B to 0xA2CC61, say & am really struggling. Here is what I have so far:
XML:
<LinearLayout
android:id="#+id/tile1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:background="#C4DF9B">
</LinearLayout>
Java:
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
int seekValue = seekBar.getProgress();
tile1.setBackgroundColor() // ???
}

Seek Bar progress not showing properly

I have set property of seek bar . it reach at one process but its process not reach at 1 as like in image below
sbpassangers.setProgress(1); //set this at onCreate
xml :
<SeekBar
android:id="#+id/sBpassangers"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_toLeftOf="#+id/tvPassengers"
android:layout_toRightOf="#+id/ivPhone"
android:layout_weight="2"
android:paddingBottom="3dp"
android:paddingLeft="2dp"
android:paddingTop="3dp" />
java code :
sbpassangers.setProgress(1);
sbpassangers.setMax(sb1.getProgress());
tvtaxipassangers.setText(Integer.toString(1));
//sb1.setMax(9);
//sb1.setProgress(2); // Set it to zero so it will start at the left-most edge
sbpassangers.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
seekBar.setProgress(progress);
if(progress == 0){
seekBar.setProgress(1);
}
tvtaxipassangers.setText(Integer.toString(seekBar.getProgress()));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {}
});
should be like this :
please help to solve this
Interchange the two lines
From
sbpassangers.setProgress(1);
sbpassangers.setMax(sb1.getProgress());
to
sbpassangers.setMax(sb1.getProgress());
sbpassangers.setProgress(1);
You cannot set the progress of seekbar unless you Defines the maximum value the progress can take.
The seekBar is an essential component which we are using on our application in customized way.
please make a demo project and follow the following code to your MainActivity
SeekbarActivity.java
package com.example.seekbarwidget;
import android.app.Activity;
import android.os.Bundle;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
public class SeekbarActivity extends Activity {
TextView textview;
SeekBar seekbar;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seekbar);
textview = (TextView)findViewById(R.id.textView);
seekbar = (SeekBar)findViewById(R.id.seekBar1);
seekbar.setMax(10);
seekbar.setProgress(5);
//initControls();
seekbar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
//add here your implementation
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
//add here your implementation
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
textview.setText(" value = " +Integer.toString(progress));
}
});
}
}
the activity_seekbar.xml is having following layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical" >
<SeekBar
android:id="#+id/seekBar1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="15dp"
android:layout_marginTop="125dp"
android:indeterminate="false"
android:max="10"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:progress="5"
android:progressDrawable="#drawable/styled_progress"
android:secondaryProgress="5"
android:thumb="#drawable/thumbler_small" />
<TextView
android:id="#+id/textView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Show seekbar value"
android:textColor="#CD2134"
android:textSize="27px"
android:textStyle="bold" />
</LinearLayout>
finally the styled_progress.xml inside drawable folder is having the lines
<?xml version="1.0" encoding="UTF-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:id="#+android:id/SecondaryProgress"
android:drawable="#drawable/progress_cyan"/>
<item
android:id="#+android:id/progress"
android:drawable="#drawable/progress_red"/>
</layer-list>
Custom Seek Bar
For exact answer you will have to provide more information. Taking a wild guess I would say that you need to set also the Max value,
setMax(int)
More information at http://developer.android.com/reference/android/widget/ProgressBar.html

Change Spinner Text Size Programmatically

have a SeekBar and I get the value of it whenever I scroll it. the position should then be the factor, how big the text in my spinner should be.
So I want to change the text size of my spinner items whenever I scroll not the 50sp as in my layout
My custom_list_row.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/textViewRow"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="top|left"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:paddingLeft="?android:attr/listPreferredItemPaddingLeft"
android:paddingRight="?android:attr/listPreferredItemPaddingRight"
android:textAppearance="?android:attr/textAppearanceListItemSmall"
android:textSize="50sp" />
My Adapter
ArrayAdapter<Language> adapter = new ArrayAdapter<Language>(this, R.layout.custom_list_row,
currentLanguages);
spinnerLanguage.setAdapter(adapter);
the Language class is a Object with a toString method.
#Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
resizeViews(progress);
}
private void resizeViews(int progress){
textViewFirstName.setTextSize(20+progress);
//how can I do this for a spinner here?
}
You can use this.
private void resizeViews(int progress){
textViewFirstName.setTextSize(20+progress);
//this might be helpful
for(int i=0;i<spinnerLanguage.getChildCount();i++){
((TextView)spinnerLanguage.getChildAt(i)).setTextSize(20+progress);
}
}

Categories

Resources