Vertical SeekBar behaves strangely when initiated on a thread - android

I'm using a simple Vertical SeekBar that is working fine if I initiate it on the onCreate function. But if I initiate the SeekBar on a different thread the thumb position does not work as expected.
The code I'm using to initiate the SeekBar:
public class MainActivity extends Activity {
AbsoluteLayout mainLayout;
VerticalSeekBar seekBar;
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context=this;
mainLayout=(AbsoluteLayout)findViewById(R.id.main_layout_id);
Thread thread1 =new Thread(runnable1);
thread1.start();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
private Runnable runnable1 = new Runnable(){
#Override
public void run() {
seekBar=new VerticalSeekBar(context);
loadMainScreen.sendEmptyMessage(0);
}
};
Handler loadMainScreen = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
AbsoluteLayout.LayoutParams parameters = new AbsoluteLayout.LayoutParams(40,200,150,30);
mainLayout.addView(seekBar,parameters);
}
};
}
I do not think the problem is on the SeekBar but I will show the code anyway.
public class VerticalSeekBar extends SeekBar implements OnSeekBarChangeListener {
public VerticalSeekBar(Context context) {
super(context);
this.setOnSeekBarChangeListener(this);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
I try changing the Context I'm passing to the variable context to getApplicationContext() and getBaseContext() but it did not work.
If I put the initialization on a runOnUiThread it crashes because the SeekBar is not initialized when I try to add to the layout. If I put both the initialization and the addView on a runOnUiThread it works but that is not what I want.
I was wondering if there is something I could do regarding the Context to make it work. Any different ideas are welcome.
Thanks in advance

Related

Seek Bar Progress is not updating after Activity/Fragment relaunch

I was customized android default seek bar to show in vertically and using in fragments go get some feedback from user.
After first launch it is showing properly. But Once I submitted my first feedback I am relaunching the activity with fragments which contains my customized Vertical Seek Bar.
At that time thumb in Vertical Seekbar is coming to "0" but progress is not coming to "0" and showing some progress. :(
Below i am adding my Vertical Seek bar code please suggest me if i missed any thing .
public class VerticalSeekBar extends SeekBar {
private int mLastProgress = 0;
private OnSeekBarChangeListener mOnChangeListener;
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
public synchronized int getMaximum() {
return getMax();
}
#Override
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (mOnChangeListener != null) {
mOnChangeListener.onStartTrackingTouch(this);
}
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_MOVE:
super.onTouchEvent(event);
int progress = getMax() - (int) (getMax() * event.getY() / getHeight());
// Ensure progress stays within boundaries
if (progress < 0) {
progress = 0;
}
if (progress > getMax()) {
progress = getMax();
}
setProgress(progress); // Draw progress
if (progress != mLastProgress) {
// Only enact listener if the progress has actually changed
mLastProgress = progress;
if (mOnChangeListener != null) {
mOnChangeListener.onProgressChanged(this, progress, true);
}
}
onSizeChanged(getWidth(), getHeight(), 0, 0);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_UP:
if (mOnChangeListener != null) {
mOnChangeListener.onStopTrackingTouch(this);
}
setPressed(false);
setSelected(false);
break;
case MotionEvent.ACTION_CANCEL:
super.onTouchEvent(event);
setPressed(false);
setSelected(false);
break;
}
return true;
}
public synchronized void setMaximum(int maximum) {
setMax(maximum);
}
#Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener) {
this.mOnChangeListener = onChangeListener;
}
public synchronized void setProgressAndThumb(int progress) {
setProgress(progress);
onSizeChanged(getWidth(), getHeight(), 0, 0);
if (progress != mLastProgress) {
mLastProgress = progress;
if (mOnChangeListener != null) {
mOnChangeListener.onProgressChanged(this, progress, true);
}
}
}
public synchronized void setMyProgress(int progress) {
setProgress(progress);
}
}
Finally i got the solution for my problem.
In .xml while creating vertical seekBar I used android:progressDrawable="#drawable/seek" but in seek.xml i forgot to declare titles as
item android:id="#android:id/secondaryProgress",
item android:id="#android:id/background" and
item android:id="#android:id/progress".

Why OnSeekBarChangeListener always returns boolean variable false?

I have one Vertical Seekbar in my android project. Vertical Seekbar is initialized in onCreate Method:
verticalSeekBar1 = (VerticalSeekBar) findViewById(R.id.verticalSeekbar1);
verticalSeekBar1.setOnSeekBarChangeListener(Listener1);
And I have to implement OnSeekBarChangeListener interface as shown below
private SeekBar.OnSeekBarChangeListener Listener1 = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar arg0, int seekBarLevel, boolean changedByUser) {
verticalSeekBar1.setProgress(seekBarLevel);
Log.e(TAG, "onProgressChanged: UserChnagedSeekbar :: "+changedByUser);
if (changedBySpinner){
mSpinner.setSelection(0);
}
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
};
changedByUser is always return false. Whether I changed Seekbar or not. Please help me to get out of this problem. Thank you in advance.
My Custom Vertical Seekbar Class code is
public class VerticalSeekBar extends SeekBar {
private Context mContext;
public VerticalSeekBar(Context context) {
super(context);
init(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context){
mContext=context;
}
protected void onSizeChanged(int w, int h, int oldWidth, int oldHeight) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
Paint paint=new Paint();
paint.setColor(Color.DKGRAY);
paint.setStrokeWidth(2.0f);
Rect rect=new Rect(0,0,getMeasuredWidth(),getMeasuredHeight());
//c.drawRect(rect,paint);
int vWidth=getMeasuredWidth();
int vHeight=getMeasuredHeight();
float startPointY=83;
float middlePointY = (vHeight)/2;
float lastPointY=vHeight-83;
paint.setColor(Color.DKGRAY);
c.drawLine(rect.left,startPointY,rect.centerX(),startPointY,paint);
c.drawLine(rect.left,middlePointY,rect.centerX(),middlePointY,paint);
c.drawLine(rect.left,lastPointY,rect.centerX(),lastPointY,paint);
paint.setColor(Color.DKGRAY);
float x=((vHeight/2)-startPointY)/3;
float f10dbPoint=x+startPointY;
float f5dbPoint=(2*x)+startPointY;
float fm5dbPoint=(vHeight/2)+x;
float fm10dbPoint=(vHeight/2)+(2*x);
float startX=rect.left+32;
c.drawLine(startX,f10dbPoint,rect.centerX(),f10dbPoint,paint);
c.drawLine(startX,f5dbPoint,rect.centerX(),f5dbPoint,paint);
c.drawLine(startX,fm5dbPoint,rect.centerX(),fm5dbPoint,paint);
c.drawLine(startX,fm10dbPoint,rect.centerX(),fm10dbPoint,paint);
c.rotate(-90);
c.translate(-getHeight(),0);
super.onDraw(c);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
int i=0;
i=getMax() - (int) (getMax() * event.getY() / getHeight());
setProgress(i);
Log.i("Progress",getProgress()+"");
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
public void updateThumb(){
onSizeChanged(getWidth(), getHeight(), 0, 0);
}
}
I didn't got the answer that why it's returning value false. But I got the alternate solution to know weather user changed seekbar value or u have changed seekbar value coding. I was changing seekbar value using depending on spinner value. So take variable
boolean changedBySpinner=false;
Inside Spinner ItemClickListener make it true
mSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
changedBySpinner=true;
}
});
set touchClickListener on the seekbar (vertical seekbar)
verticalSeekBar1.setOnTouchListener((View.OnTouchListener) this);
Inside onTouchMethod make that variable true
changedBySpinner=false;
And inside seekbarChangeListener add below code
private SeekBar.OnSeekBarChangeListener Listener1 = new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar arg0, int seekBarLevel, boolean changedByUser) {
if (!changedBySpinner){
mSpinner.setSelection(0);
}
}
#Override
public void onStartTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar arg0) {
// TODO Auto-generated method stub
}
};
Perform your action which wanted to, inside if block. Like I am setting spinner value to 0th element.
Well, this is just an alternate solution. If you are facing the same problem you can use it.

ondraw taking too much ram in custom view repetition

I am designing a customview for the seats in the theater.For x large phones it is working smoothly.But in lower density devices it is hard to work with.
my customview.java
public class SeatView extends ImageView {
float dim;
int status;
Canvas canvas1;
boolean sela=false,ds=false,ua=false;
Bitmap selectedAvailableImage,deselectedAvailableImage,unavailableImage;
Drawable selectedAvailable,deselectedAvailable,unavailable;
SeatView seatView;
public SeatView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs,R.styleable.SeatView,0, 0);
try {
dim = a.getDimension(R.styleable.SeatView_dim, 20f);
status=a.getInt(R.styleable.SeatView_status,1);
selectedAvailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_selected);
deselectedAvailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_available);
unavailableImage=BitmapFactory.decodeResource(getResources(),R.drawable.seat_unavailable);
selectedAvailable=getResources().getDrawable(R.drawable.seat_selected);
deselectedAvailable=getResources().getDrawable(R.drawable.seat_available);
unavailable=getResources().getDrawable(R.drawable.seat_unavailable);
//selectedAvailable.setBounds(100,100,100,100);
//deselectedAvailable.setBounds(10,10,10,10);
//unavailable.setBounds(10,10,10,10);
} finally {
a.recycle();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction()==MotionEvent.ACTION_UP){
if(status==0){
status=1;
invalidate();
}else if(status==1){
status=0;
invalidate();
}
}
return true;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(50,50);
}
public void setAvailable(){
status=1;
invalidate();
}
public void setDisabled(){
status=2;
invalidate();
}
public void setSelected(){
status=0;
invalidate();
}
public int getSeatStatus(){
return status;
}
public void init(Canvas canvas){
switch (status){
case 0:
//sela=true;ds=false;ua=false;
//setImageDrawable(selectedAvailable);
canvas.drawBitmap(selectedAvailableImage,0,0,null);
break;
case 1:
//sela=false;ds=true;ua=false;
//setImageDrawable(deselectedAvailable);
canvas.drawBitmap(deselectedAvailableImage,0,0,null);
break;
case 2:
//sela=false;ds=false;ua=true;
//setImageDrawable(unavailable);
canvas.drawBitmap(unavailableImage,0,0,null);
break;
default: //setImageDrawable(deselectedAvailable);
canvas.drawBitmap(deselectedAvailableImage,0,0,null);
break;
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
init(canvas);
}
}
and my mainactivity.java
public class MainActivity extends AppCompatActivity {
ImageView imageView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//ButterKnife.bind(this);
TableLayout tableLayout=(TableLayout)findViewById(R.id.tblelay);
// Toast.makeText(getApplicationContext(),seatView.getSeatStatus()+"",Toast.LENGTH_LONG).show();
//LinearLayout relativeLayout=(LinearLayout) findViewById(R.id.tblelay);
for (int j=0;j<20;j++){
TableRow tableRow=new TableRow(this);
for (int i=1;i<20;i++){
SeatView seatView=new SeatView(this,null);
seatView.setAvailable();
seatView.setId(i);
if(i%5==0){
seatView.setVisibility(View.INVISIBLE);
}
if(seatView.getParent()!=null)
((ViewGroup)seatView.getParent()).removeView(seatView); // <- fix
if(tableRow.getParent()!=null)
((ViewGroup)tableRow.getParent()).removeView(tableRow);
/* if(i>0){
RelativeLayout.LayoutParams layoutParams=new Rela tiveLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
layoutParams.addRule(RelativeLayout.RIGHT_OF, (i-1));
}*/
tableRow.addView(seatView);
}
tableLayout.addView(tableRow);}
}
}
click here for screenshot

android invalidate function is not called

when findsellectedtBt() called invalidate in the findSellectedBt() don't work.
so onDraw() is not called.
why these codes don't work correctly ?
public class CustomView extends View {
private Typeface t;
private Paint paint;
private Buttons sellectedBt;
public CustomView(Context context) {
... }
public CustomView(Context context, AttributeSet attrs) {
...}
public CustomView(Context context, AttributeSet attrs, int defStyle) {
...}
#Override
protected void onDraw(Canvas canvas) {
if(isInEditMode()) return ;
canvas.drawColor(Color.YELLOW);
switch(sellectedBt) {
case ID:
t = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL);
paint.setTypeface(t);
canvas.drawText("ID: 0000", 50, 100, paint);
case PHOTO:
break;
case LINE:
break;
default:
break;
}
}
public void findSellectedBt(Buttons buttonId ) {
sellectedBt = buttonId;
invalidate();
}
}
public class MainActivity extends Activity {
private CustomView customView;
private Button btId;
private CheckBox btPhoto;
private ToggleButton btLineOff;
private Button btClaer;
private ToggleButton btBlue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
customView = new CustomView(this);
btId = (Button)findViewById(R.id.id);
btPhoto = (CheckBox)findViewById(R.id.photo);
btId.setOnClickListener(new OnClickListener() {
public void onClick(View v){
System.out.println("idOnclick");
customView.findSellectedBt(Buttons.ID);
}
});
btPhoto.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
// TODO Auto-generated method stub
System.out.println("photoChecked");
if(arg1 == true)
customView.findSellectedBt(Buttons.PHOTO);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
package com.example.hw4_200921275;
public enum Buttons {ID, PHOTO, LINE, CLEAR, BLUE}
Double check you're somewhere calling
findSellectedBt(buttonsObject);
By the way, notice the typo in Sellected.

Android Seekbar - only allow change with thumb?

I have a seekbar that I want to only allow changing with the thumb/handle portion. If the user taps anywhere else, I'd like that tap to be ignored.
Is there an inherant property to do this? If not, I already know I can set an onTouch listener and return true to "disable" it, but is there a way to detect when the thumb is tapped so that I can tell onTouch to return false in that case?
I assume you want to change thumb position via code, which is user restricted.so for that try this.may be could help you.
myseekBar.setOnSeekBarChangeListener( new OnSeekBarChangeListener() {
int originalProgress;
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
originalProgress = seekBar.getProgress();
}
#Override
public void onProgressChanged(SeekBar seekBar, int arg1, boolean fromUser) {
if( fromUser == true){
seekBar.setProgress(originalProgress);
}
}
});
I had the same issue , I fixed using a simple logic to compare the new Progress X OldProgress.
This is my code to a VerticalSlider that just allow change value when user click over Thumb.
This is the trick:
int tempProgress = (getMax() - (int) (getMax() * event.getY() / getHeight()));
int diff = Math.abs(tempProgress - progress);
if ( diff > 7 && !isMoving) return true;
isMoving = true;
This is all component source:
package android.widget;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
public class VerticalSeekBar extends SeekBar {
private OnSeekBarChangeListener onChangeListener;
private int progress = 0;
private Drawable mThumb;
private boolean isMoving;
public VerticalSeekBar(Context context) {
super(context);
}
public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public VerticalSeekBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
#Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
#Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
this.onChangeListener = onChangeListener;
}
public void setThumb(Drawable thumb) {
if (thumb != null) {
thumb.setCallback(this);
}
super.setThumb(thumb);
mThumb = thumb;
mThumb.setCallback(this);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if ( onChangeListener!= null)onChangeListener.onStartTrackingTouch(this);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_MOVE:
int tempProgress = (getMax() - (int) (getMax() * event.getY() / getHeight()));
int diff = Math.abs(tempProgress - progress);
if ( diff > 7 && !isMoving) return true;
isMoving = true;
progress = getMax() - (int) (getMax() * event.getY() / getHeight());
if(progress < 18) {progress = 18;}
if(progress > getMax()) {progress = getMax();}
setProgressAndThumb(progress);
setPressed(true);
setSelected(true);
break;
case MotionEvent.ACTION_UP:
isMoving = false;
if ( onChangeListener!= null)onChangeListener.onStopTrackingTouch(this);
setPressed(false);
setSelected(false);
break;
case MotionEvent.ACTION_CANCEL:
isMoving = false;
super.onTouchEvent(event);
setPressed(false);
setSelected(false);
break;
}
return true;
}
public synchronized void setProgressAndThumb(int progress) {
setProgress(progress);
onSizeChanged(getWidth(), getHeight() , 0, 0);
if ( onChangeListener!= null) onChangeListener.onProgressChanged(this, progress, true);
}
#Override
public synchronized void setProgress(int progress) {
this.progress =progress;
super.setProgress(progress);
if ( onChangeListener !=null) onChangeListener.onProgressChanged(this, progress, true);
}
public synchronized void setMaximum(int maximum) {
setMax(maximum);
}
public synchronized int getMaximum() {
return getMax();
}
}
Regards!
// I solved this problem.
private int mOriginProgress;
private boolean mIsDrag;
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
mIsTouched = true;
mOriginProgress = seekBar.getProgress();
}
#Override
public void onProgressChanged(SeekBar seekBar, int p, boolean fromUser) {
if (mOriginProgress == p) {
return;
}
if (mIsDrag) {
// do something
} else {
if (Math.abs(mOriginProgress - p) > 5) {
seekBar.setProgress(mOriginProgress);
} else {
mIsDrag = true;
}
}
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
mIsDrag = false;
}

Categories

Resources