I want to make a button change a seekbar's progress back to a specific value slowly while the button is pressed. It's like, say, the seekbar's curent progress is 150, it's standard value is 100, and I want to decrease the progress back to 100 while a buttons is pressed, and to move 1 unit on the seekbar takes 0.1 sec.
I'm trying to do this using a ValueAnimator
main_seekbar_speed_reset.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
ValueAnimator animator = ValueAnimator.ofInt(main_seekbar_speed.getProgress(), 100);;
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
animator = ValueAnimator.ofInt(main_seekbar_speed.getProgress(), 100);
animator.setDuration(Math.abs(main_seekbar_speed.getProgress() - 100)*100);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
main_seekbar_speed.setProgress((int)valueAnimator.getAnimatedValue());
}
});
case MotionEvent.ACTION_UP:
animator.end();
}
return false;
}
});
But this code resets it immediately.
EDIT
I forgot about adding break; to the end of each case.
It means that switch has gone through every case, thus animator.end() was always called for last, which set the progress of seekbar to the final animated value (100) everytime.
Additionally, animator.end() means that the animator ends immediately; it jumps to the last value it should be at the end of the animation.
MotionEvent.ACTION_DOWN and MotionEvent.ACTION_UP both created a new ValueAnimator, so releasing the button couldn't affect the ValueAnimator which was created when touching the button. It should be declared outside the listener.
So the working code:
`
final ValueAnimator animator = ValueAnimator.ofInt(main_seekbar_speed.getProgress(), 100);
main_seekbar_speed_reset.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
animator.setIntValues(main_seekbar_speed.getProgress(), 100);
animator.setDuration(Math.abs(main_seekbar_speed.getProgress() - 100)*100);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
main_seekbar_speed.setProgress((int)valueAnimator.getAnimatedValue());
}
});
break;
case MotionEvent.ACTION_UP:
animator.pause();
break;
}
return false;
}
});`
Related
I was creating Ontouchlistener But i got 2 error. 1st unexpected token and 2nd Cannot resolve constructor 'Intent(anonymous android.view.View.OnTouchListener, java.lang.Class<com.krish.galaxypdfviewer.Website>)'
And when i tried onclick listener it worked without any error but i want to use Ontouchlistener
Here is the code whats wrong here?
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FloatingActionButton actionButton = findViewById(R.id.action_button);
defineView();
handleIntent();
defineActionBar();
checkPermission();
long start;
actionButton.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(final View v, final MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
start=System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
if(System.currentTimeMillis()-start<500){ //Click is less than 500ms, you can adjust this value later...
//Do what you want on click over here...
}else{
openWebsite(); //It's a long click, do what you want over here...
}
return true;
default:
return false;
}
});
public void openWebsite() {
Intent intent = new Intent(this, Website.class);
startActivity(intent);
}
There's a missing closing curly brace for the onTouch method.
actionButton.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(final View v, final MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
start=System.currentTimeMillis();
return true;
case MotionEvent.ACTION_UP:
if(System.currentTimeMillis()-start<500){ //Click is less than 500ms, you can adjust this value later...
//Do what you want on click over here...
}else{
openWebsite(); //It's a long click, do what you want over here...
}
return true;
default:
return false;
}
} // this one closes onTouch
});
I want to apply some animation whenever user touch on button, like-
on touch/hover = scale down,
move finger out of the view bound = scale up to previous position,
on release/click = scale up to previous position
On touch animation is working perfectly but I am unable to figure out scale up animation to it's previous position when finger is being released. Also I am not too much familiar with Motion touch event, so please tell me which Motion Event will be appropriate to do this. Can anyone please help me. here is my code:
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
imageView.animate().scaleX(0.5f).scaleY(0.5f).start();
break;
case MotionEvent.ACTION_CANCEL:
imageView.animate().scaleX(2.0f).scaleY(2.0f).start();
break;
case MotionEvent.ACTION_UP:
imageView.animate().scaleX(2.0f).scaleY(2.0f).start();
startActivity(new Intent(ActivityOne.this, ActivityTwo.class));
break;
}
return true;
}
});
I have also tried with object animator, something like that:
private void scaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 0.5f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 0.5f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
//scaleDownX.setRepeatMode(ValueAnimator.REVERSE);
//scaleDownY.setRepeatMode(ValueAnimator.REVERSE);
//scaleDownX.setRepeatCount(1);
//scaleDownY.setRepeatCount(1);
animatorSet = new AnimatorSet();
//animatorSet.play(scaleDownX).with(scaleDownY);
animatorSet.playTogether(scaleDownX, scaleDownY);
animatorSet.start();
}
Alright after a long experiment I have discovered the answer by myself. Here it is:
After touch, if user move his finger then we need to cancel button click
boolean isMove;
// initialize
isMove = false;
Set scale down and scale up animation
private void startScaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 0.8f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 0.8f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
scaleDownX.start();
scaleDownY.start();
}
private void cancelScaleAnimation(View view) {
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(view, "scaleX", 1.0f);
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(view, "scaleY", 1.0f);
scaleDownX.setDuration(150);
scaleDownY.setDuration(150);
scaleDownX.start();
scaleDownY.start();
}
Now, apply this animation along with onTouch listener
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
startScaleAnimation(imageView);
break;
case MotionEvent.ACTION_MOVE:
cancelScaleAnimation(imageView);
isMove =true;
break;
case MotionEvent.ACTION_UP:
cancelScaleAnimation(imageView);
if (!isMove){
isMove = false;
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(new Intent(ActivityOne.this, ActivityTwo.class));
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
overridePendingTransition(R.anim.enter_slide_left, R.anim.exit_slide_left);
}
}
},150);
}else {
isMove = false;
}
break;
}
return true;
}
});
Code
private RelativeLayout mToolbar;
mToolbar = (RelativeLayout) myview.findViewById(R.id.toolbar);
mToolbar.setOnTouchListener(new View.OnTouchListener() {
WindowManager.LayoutParams updatedParameters = finalParameters;
double x;
double y;
double pressedX;
double pressedY;
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = updatedParameters.x;
y = updatedParameters.y;
pressedX = event.getRawX();
pressedY = event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
updatedParameters.x = (int) (x + (event.getRawX() - pressedX));
updatedParameters.y = (int) (y + (event.getRawY() - pressedY));
wm.updateViewLayout(myview, updatedParameters);
default:
break;
}
return false;
}
});
I have a service and this above code can move around that service in the screen... It worked before when i had to touch a button and move it around. I switched it to layout now and it does.t work anymore
Why doesn't this work? The same code i used it with a button instead and it worked fine. Does onTouch always have to be button or can it be layouts or textviews as well?
You should return true from onTouch method
If you return false when you get MotionEvent.ACTION_DOWN,
Android assumes that you're not interested in handling touch events and simply doesn't pass any other motion events to you (including MotionEvent.ACTION_MOVE that you're expecting)
You need to update the return part of onTouch Method
public boolean onTouch(View v, MotionEvent event) {
// if return is true means touch enabled
// If return is false means touch is disabled
return true;
}
I am using a videoView to play a video.
bVideoView = (VideoView) findViewById(R.id.bVideoView);
bVideoView.setVideoPath(videoPath);
Now I have a button,
audioToggle = (Button) findViewById(R.id.audioToggle);
Then I have the Button's OnClickListener
private static int aux = 0;
private AudioManager mAudioManager;
audioToggle.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
bVideoView.start();
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
if(aux % 2 == 0){
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 50, 0);
aux++;
} else {
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
aux++;
}
}
});
Now with this OnClickListener I am perfectly able to toggle the audio to mute and unmute when it is clicked each time. However I want something like this,
On the first click the videoView should start.
When I keep pressing the button the audio must mute.
When I release the button the audio must unmute.
I have been trying a lot and failing in some or the other way. Please help.
Do you mean:
The first time I hold the button, the video should play.
While I'm holding the button the audio must be heard.
When I release the button, the audio must be muted.
When I press and hold the button again, the audio must be heard again.
Then what you therefore need is not an OnClickListener but rather an OnTouchListener
What happens under the hood is that your OnClickListener is always called after you release your finger. Using View.OnTouchListener you can dispatch events when you press (you mean touch and hold) and release.
See http://developer.android.com/reference/android/view/View.OnTouchListener.html
Here's a sample snippet:
private static int aux = 0;
private AudioManager mAudioManager;
audioToggle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
bVideoView.start();
mAudioManager = (AudioManager)getSystemService(Context.AUDIO_SERVICE);
switch(e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 50, 0);
break;
case MotionEvent.ACTION_UP:
mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
break;
}
return true;
}
}
Finally, I don't recommend controlling the system's volume. Use a MediaPlayer.OnPreparedListener instead, get the VideoView’s MediaPlayer and then play around with its volume.
Edit:
Here's another sample snippet:
private MediaPlayer bVideoViewMP;
bVideoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
#Override
public void onPrepared(MediaPlayer mp) {
// Fetch a reference
bVideoViewMP = mp;
}
});
audioToggle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
bVideoView.start();
switch(e.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
bVideoViewMP.setVolume(0.75f, 0.75f);
break;
case MotionEvent.ACTION_UP:
bVideoViewMP.setVolume(0, 0);
break;
}
return true;
}
}
These should be placed either on your fragment's onViewCreated() or on your activity's onCreate() method before the VideoView has been fully prepared.
I'd like to have two onTouchEvents on my app. One event would only work on the top half of the screen and the other event would only work on the bottom half of the screen. Is this possible?
//top
public boolean onTouchEvent(MotionEvent event){
this.mDetector.onTouchEvent(event);
// my logic
return super.onTouchEvent(event);
}
//bottom
public boolean onTouchEvent(MotionEvent event){
this.mDetector.onTouchEvent(event);
// my logic
return super.onTouchEvent(event);
}
Since the only provided solutions require you to use multiple Views, I figured I would provide one for a single View that encompasses the entire screen:
public boolean onTouch(View view, MotionEvent event) {
if(event.getY() < activity.getResources().getDisplayMetrics().heightPixels / 2){
//top
}
else{
//bottom
}
return true; //handle the touch
}
This was me just assuming you were only using a single View...
Something like this:
topLayout = (LinearLayout) findViewById(R.id.topLayout);
bottomLayout = (LinearLayout) findViewById(R.id.bottomLayout);
topLayout.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
Log.d(TAG, "top was touched");
return false;
}
});
bottomLayout.setOnTouchListener(new View.OnTouchListener()
{
#Override
public boolean onTouch(View v, MotionEvent event)
{
Log.d(TAG, "bottom was touched");
return false;
}
});
Or you could move those anonymous classes to their own respective classes and use them:
topLayout = (LinearLayout) findViewById(R.id.topLayout);
bottomLayout = (LinearLayout) findViewById(R.id.bottomLayout);
topLayout.setOnTouchListener(new TopOnTouchListener());
bottomLayout.setOnTouchListener(new BottomOnTouchListener());
This is assuming you have some view that spans the top and bottom of your layout. In the above example I'm using two LinearLayouts to do so, but feel free to choose your own.