In onViewCreate I set the view behind the screen:
holderMenus.post(new Runnable() {
#Override public void run() {
if (holderMenus != null) {
if (DeviceType.INSTANCE.tablet) {
holderMenus.animate().translationY(-holderMenus.getHeight());
} else {
holderMenus.animate().translationY(holderMenus.getHeight());
}
}
}
});
Then, when I want to move the view in:
holderMenus.animate().translationY(0).setDuration(300);
That works well; the view slides in. Next I want to move the view off the screen:
if (DeviceType.INSTANCE.tablet) {
holderMenus.animate().translationY(-holderMenus.getHeight()).setDuration(300);
} else {
holderMenus.animate().translationY(holderMenus.getHeight()).setDuration(300);
}
But instead of sliding, the view disappears, as if I had set the property to .setVisibility(View.GONE);
How can I make it slide instead?
I have made a custom action button that slides from below the screen and slides back under the screen when listview is scrolled.
Hides:
TranslateAnimation anim = new TranslateAnimation(0, 0, 0, 500);
anim.setDuration(300l);
anim.setFillAfter(true);
layout.startAnimation(anim); //layout is the layout with the button
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
layout.clearAnimation();
layout.setVisibility(View.GONE);
}
}, 300l);
Shows:
Handler h = new Handler();
h.postDelayed(new Runnable() {
#Override
public void run() {
try {
layout.setVisibility(View.VISIBLE);
TranslateAnimation anim = new TranslateAnimation(0, 0, 500, 0);
anim.setDuration(300l);
anim.setFillAfter(true);
layout.startAnimation(anim);
} catch (Exception e) {
e.printStackTrace();
}
}
}, 500l);
I guess that slide out animation is not starting from the point that you think it is. It probably "animates" in the same position off the screen.
You might want to try ObjectAnimator, where you can specify both starting and ending points for your animation using ofFloat method for example.
Related
If the user (in my quizgame) chooses the false answer, the button with the correct answer should blink green.
So far i did it like this:
if(answerTrue)
for (int i = 0; i < 2000; i = i + 250) {
handler.postDelayed(rbl_blinkNormal, i);
i = i + 250;
handler.postDelayed(rbl_blinkGreen, i);
}
And the runnables:
Green:
rbl_blinkGreen= new Runnable() {
#Override
public void run() {
btn_richtig.setBackgroundResource(R.drawable.color_green_btn);
}
};
Normal:
rbl_blinkNormal= new Runnable() {
#Override
public void run() {
btn_richtig.setBackgroundResource(R.drawable.color_black_btn);
}
};
It works fine but like this Im calling the postDelayed() every 250ms. May this impact my application performance and is there any better way to do this?
You can animate your button once you set its color to say GREEN. I mean,
if(answerTrue){
// Set the color of the button to GREEN once.
// Next, animate its visibility with the set color - which is GREEN as follows:
Animation anim = new AlphaAnimation(0.0f, 1.0f);
anim.setDuration(50); //You can manage the blinking time with this parameter
anim.setStartOffset(20);
anim.setRepeatMode(Animation.REVERSE);
anim.setRepeatCount(Animation.INFINITE);
button.startAnimation(anim);
}
Similarly, you can animate the other button and stop animation when you feel like.
Source: Blinking Text in android view
If you want to blink the image only, here is an example.
Button bt_notes = (Button) findViewById(R.id.bt_notes);
int bt_notes_blink = 0;
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
int DrawableImage[] = {R.drawable.picto_keys, R.drawable.picto_blank};
Resources res = getApplicationContext().getResources();
bt_notes.setCompoundDrawablesWithIntrinsicBounds(null, null, null, res.getDrawable(DrawableImage[bt_notes_blink]));
bt_notes_blink++;
if (bt_notes_blink == 2) { bt_notes_blink = 0; }
handler.postDelayed(this, 500);
}
});
}
}, 0);
I know that I can set android:background="?android:attr/selectableItemBackground" to any View to get the nice ripple effect from Android Lollipop.This works well for views which are touched by the user. But what if I want to play the ripple animation without user interaction?
In my application I want to draw attention to a view by playing a ripple animation on this view. How can I do this? I do not found a way to get an Animatior object for the ripple animation. So how can I set a ripple animation to a view from code without user interaction?
Unfortunately no accessible method is available to play ripple animation. But I could think of two possible ways to achieve this
#1 Using reflection
public static void simulateButtonPress(final View view)
{
Drawable drawable = view.getBackground();
if( drawable instanceof RippleDrawable )
{
try
{
final RippleDrawable rd = ((RippleDrawable)drawable);
final Method setRippleActive = rd.getClass().getDeclaredMethod("setRippleActive", boolean.class);
setRippleActive.setAccessible(true);
setRippleActive.invoke(rd, true); //setRippleActive(true)
//exit ripple effect after 250 milliseconds
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
try
{
setRippleActive.invoke(rd, false); //setRippleActive(false)
}
catch (Exception e)
{
e.printStackTrace();
}
}
}, 250);
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
#2 By simulating Motion Events ACTION_DOWN and ACTION_CANCEL
public static void simulateButtonPress(final View view)
{
final long now = SystemClock.uptimeMillis();
final MotionEvent pressEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_DOWN, view.getWidth()/2, view.getHeight()/2, 0);
view.dispatchTouchEvent(pressEvent);
new Handler().postDelayed(new Runnable()
{
#Override
public void run()
{
final long now = SystemClock.uptimeMillis();
final MotionEvent cancelEvent = MotionEvent.obtain(now, now, MotionEvent.ACTION_CANCEL, view.getWidth()/2, view.getHeight()/2, 0);
view.dispatchTouchEvent(cancelEvent);
}
}, 250);
}
Does anyone know how would i do this? And imageView should come from outside of the activity.
Here is the code:
rollingImageView = (ImageView) findViewById(R.id.imageView1);
AnimationSet rollingIn = new AnimationSet(true);
Animation moving = new TranslateAnimation(Animation.RELATIVE_TO_PARENT,-1f,Animation.RELATIVE_TO_PARENT,0,Animation.RELATIVE_TO_PARENT, 0, Animation.RELATIVE_TO_PARENT, 0);
moving.setDuration(5000);
rollingIn.addAnimation(moving);
Animation rotating = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
rotating.setDuration(5000);
rollingIn.addAnimation(rotating);
rollingImageView.startAnimation(rollingIn);
Assuming you have your imageview set to the bottom left down, (this will only help you go from left to right)
In your activity file...
public void callthismethodtostartrolling(){
final Thread myThread = new Thread(new Runnable()
{
#Override
public void run()
{
while (!<imageviewInRightCorner>) {//<<define this yourself
try {
Thread.sleep(4);
runOnUiThread(new Runnable()
{
#Override
public void run() {
rollingImageView.setX((float) (rollingImageView.getX() + 5));
}
});
} catch (InterruptedException e) {
// this should not happen
}
}
}
});
myThread.start
}
PROS
I think it gives the effect you want.
CONS
Ive tried this before, it works, but you cant interrupt the Thread inside the Thread if you ever need to do so. The link to the original problem/con of this is here,if you would like to help Dusan and I ._.
ALTERNATIVE
final Thread myThread = new Thread(new Runnable()
{
#Override
public void run()
{
while (!<imageviewInRightCorner>) {//<<define this yourself
try {
Thread.sleep(4);
runOnUiThread(new Runnable()
{
#Override
public void run() {
rollingImageView.setX((float) (rollingImageView.getX() + 5));
}
});
} catch (InterruptedException e) {
// this should not happen
}
}
}
});
Using myThread.start anywhere in your code to activate your sliding imageview awesomeness.
PROS
Alternative to first option with a different con to suit your need
*able to use myThread.interrupt within Thread
CONS
Cant call the Thread more than once per launch :/ the reason why is all in here
potential while condition explained(as requested by asker)...
How to animate multiple objects one by one after some intervals android
i am using this code for animation
for (int y = 0; y < 10; y++) {
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
but it is animating all in one go but i want one by one animation of my imageview please help
No need to use Threads and Handlers. Instead of that use,
objectAnimator.setStartDelay(delay);
Using that you can stop that animation for the respective 'delay'
Try this code..
int delay = 1000;
for (int y = 0; y < 10; y++) {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.setStartDelay(delay);
oa.start();
delay = delay+1000;
}
You can use for loop to generate AnimatorSet and then play them sequentially using set.playSequentially(yourAnimatorSetListHere);
I haven't used list in below mentioned snippet.
AnimatorSet decSet = new AnimatorSet();
decSet.playTogether(
ObjectAnimator.ofArgb(mTextSlidetoCancel, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mBtnMicActive, "visibility", View.GONE, View.VISIBLE),
ObjectAnimator.ofArgb(mChronometer, "visibility", View.GONE, View.VISIBLE));
decSet.setDuration(125);
AnimatorSet decSet2 = new AnimatorSet();
decSet2.playTogether(
ObjectAnimator.ofArgb(mBtnAttach, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mBtnEmoji, "visibility", View.VISIBLE, View.GONE),
ObjectAnimator.ofArgb(mEditTExt, "visibility", View.VISIBLE, View.GONE)
);
decSet2.setDuration(125);
AnimatorSet set = new AnimatorSet();
set.playSequentially(decSet2,decSet);
set.start();
Try out this way!
public Integer[] Imgid = {R.drawable.anim2, R.drawable.anim3,
R.drawable.anim4, R.drawable.anim5}; // your image array.
Animation anim;
Handler handler;
ImageView iv;
int count;
Runnable galleryAnimRunnable;
Inside onCreate
iv= (ImageView)findViewById(R.id.imagetype);
handler = new Handler();
galleryAnimRunnable = new Runnable() {
public void run() {
if(count==Imgid.length){
//do any action
}
else{
anim = AnimationUtils.loadAnimation(AnimationScreen.this, R.anim.fade_out); // load your desire animation.
iv.setBackgroundResource(Imgid[count]);
iv.setAnimation(anim);
count++;
handler.postDelayed(galleryAnimRunnable, 300); //set your desire delay time.
}
}
};
Your sleep call isn't helping because when one posted UI job goes to sleep, then next one starts and goes to sleep immediately following that, and so on. Then the first job wakes up and runs, followed closely by the second job awakening and running, etc.
If you want the sleep to help you need to wait before posting each job, which could be as simple as something like the following:
for (int y = 0; y < 10; y++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(ProjectFirstActivity.this, y + "",
Toast.LENGTH_SHORT).show();
ObjectAnimator oa = ObjectAnimator.ofFloat(myimageview[y],
"translationY", 0, -200);
oa.setDuration(1000);
oa.start();
}
});
}
EDIT: Although the above explains why you were having problems, I would recommend going with something like the answer posted by Jgdsh Seerm using setStartDelay().
Try this way!
ImageView image1;
public int currentimageindex1=0;
Timer timer;
TimerTask task;
private Animation animation1;
private Animation animation2;
int img[] = {R.drawable.aa, R.drawable.bb,
R.drawable.cc,R.drawable.dd,R.drawable.ee,R.drawable.ff,R.drawable.gg,
R.drawable.hh};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final Handler mHandler = new Handler();
// Create runnable for posting
final Runnable mUpdateResults = new Runnable() {
public void run() {
AnimateandSlideShow();
}
};
int delay = 1000; // delay for 1 sec.
int period = 4000; // repeat every 4 sec.
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
public void run() {
mHandler.post(mUpdateResults);
}
}, delay, period);
}
public void onClick(View v) {
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
/**
* Helper method to start the animation on the splash screen
*/
private void AnimateandSlideShow() {
image1 = (ImageView)findViewById(R.id.imageView1);
image1.setImageResource(img[currentimageindex1%img.length]);
currentimageindex1++;
}
I had used TranslateAnimation and slide up and down a view.
However, I realize, even though after I slide down the view, and use View.GONE in its visibility, the view still able to receive touch event.
You can produce the same problem, by clicking on the button to make the orange color view disappear from the bottom of the screen. Then, when you click on the bottom of the screen, you will realize touch event of the custom view is still being triggered.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int color = getResources().getColor(android.R.color.holo_orange_light);
// construct the RelativeLayout
final RelativeLayout customView = new RelativeLayout(this) {
#Override
public boolean onTouchEvent(MotionEvent event) {
this.setPressed(true);
Log.i("CHEOK", "OH NO! TOUCH!!!!");
return super.onTouchEvent(event);
}
};
customView.setBackgroundColor(color);
final FrameLayout frameLayout = (FrameLayout)this.findViewById(R.id.frameLayout);
frameLayout.addView(customView, new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, 100, Gravity.BOTTOM));
customView.setVisibility(View.GONE);
Button button = (Button)this.findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (customView.getVisibility() != View.VISIBLE) {
// Slide up!
TranslateAnimation anim=new TranslateAnimation(0,0,100,0);
anim.setFillAfter(true);
anim.setDuration(200);
Log.i("CHEOK", "VISIBLE!!!");
customView.setVisibility(View.VISIBLE);
customView.setAnimation(anim);
customView.setEnabled(true);
} else {
// Slide down!
TranslateAnimation anim=new TranslateAnimation(0,0,0,100);
anim.setFillAfter(true);
anim.setDuration(200);
// HELPME : Not sure why, after I hide the view by sliding it down,
// making it View.GONE and setEnabled(false), it still able to
// receive touch event.
Log.i("CHEOK", "GONE!!!");
customView.setVisibility(View.GONE);
customView.setAnimation(anim);
customView.setEnabled(false);
}
}
});
}
}
The complete source code to demonstrate this problem can be found here :
https://www.dropbox.com/s/1101dm885fn5hzq/animator_bug.zip
How can I make my custom view not to receive touch event, after I had slide it down?
It is not clear to me why you are using setAnimation() instead of startAnimation() as it does not appear that you have set a start time on your animations.
On another note, I have found that setting a view to GONE while it has an associated animation does not make it truly "GONE." Instead, you must first get rid of the animation using clearAnimation().
So, something like this instead:
public void onClick(View v) {
if (customView.getVisibility() != View.VISIBLE) {
// Slide up!
TranslateAnimation anim=new TranslateAnimation(0,0,100,0);
anim.setFillAfter(true);
anim.setDuration(200);
customView.setVisibility(View.VISIBLE);
customView.setEnabled(true);
customView.startAnimation(anim);
} else {
// Slide down!
TranslateAnimation anim=new TranslateAnimation(0,0,0,100);
anim.setFillAfter(true);
anim.setDuration(200);
anim.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
customView.clearAnimation();
customView.setVisibility(View.GONE);
customView.setEnabled(false);
}
#Override
public void onAnimationRepeat(Animation animation) {
// nothing to do
}
#Override
public void onAnimationStart(Animation animation) {
// nothing to do
}
}
}
}
I don't recall, but you may have to post() the contents of onAnimationEnd() instead of running the code immediately for it to take effect properly.