Im rotating a LinearLayout, using an ObjectAnimator. Clicking the button causes the LinearLayout to rotate 360(degrees) with the bottom part as the Pivot.
After the Layout completes the rotation, it leaves back a 'trail'/black mark and the complete view looks odd. How do I avoid this from happening? After the Layout completes the 360 animation, I want the view to look as it did in the beginning (clean basically).
Is there a view.refresh or update command im suppose to call somewhere?
1)How do I have a clean looking view at the end?
2)When the image is is in the intermediatestate, why does the back-part appear black? How do I get that to look while(ie,color of the relative layout)?
InitialState>IntermediateState>FinalState:
MainActivity
Button bt1;
float pivotX=0f;
float pivotY=0f;
int a=0;
float width,height;
ViewGroup mContainer=null;
Thread t;
private Handler mHandler = new Handler();
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
bt1 = (Button) findViewById(R.id.button1);
mContainer = (ViewGroup) findViewById(R.id.container);
bt1.setOnClickListener(this);
t=new Thread()
{
#Override
public void run()
{
try {
while(true)
{
relativeLayout.postInvalidate();
}
} catch (Exception e) {
// TODO: handle exception
}
}
};
}
#Override
public void onWindowFocusChanged(boolean hasFocus)
{
super.onWindowFocusChanged(hasFocus);
//Here you can get the size!
width = mContainer.getWidth();
height = mContainer.getHeight();
pivotX = mContainer.getPivotX()+width;
pivotY = mContainer.getPivotY()+height;
mContainer.setPivotX(pivotX);
mContainer.setPivotY(pivotY);
}
private void rotate()
{
a -=360;
ObjectAnimator rotate = ObjectAnimator.ofFloat(mContainer, View.ROTATION_X,a);
rotate.setDuration(2000);
AnimatorSet aSet = new AnimatorSet();
aSet.play(rotate);
aSet.start();
mHandler.post(new Runnable()
{
#Override
public void run()
{
b+=1;
relativeLayout.invalidate();
relativeLayout.postInvalidate();
bt1.setText(Integer.toString(b));
}
});
rotate.addListener(new AnimatorListener()
{
#Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
//relativeLayout.invalidate();
t.start();
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
//mContainer.invalidate();
//relativeLayout.invalidate();
try {
t.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
}
#Override
public void onClick(View v)
{
switch(v.getId())
{
case R.id.button1:
rotate();
break;
}
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
tools:context=".MainActivity" >
<LinearLayout
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#140A1F"
android:orientation="horizontal" >
</LinearLayout>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/container"
android:layout_centerHorizontal="true"
android:layout_marginTop="80dp"
android:text="Rotate" />
</RelativeLayout>
Edit: Added a thread.
**Edit2:**** Added a handler and commented out the thread
Adding this to the code fixes the view once the animation is competed, but the intermediate stage still looks the same. Will update this once I figure that out.
rotate.addListener(new AnimatorListener()
{
#Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
relativeLayout.invalidate();
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
//mContainer.invalidate();
relativeLayout.invalidate();
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
Related
I am using this code to animate childViews in a ViewGroup on screen:
zoom_in.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
viewGroup.getChildAt(i).setVisibility(View.VISIBLE);
viewGroup.getChildAt(i).clearAnimation();
if(i<5)
{
i++;
viewGroup.getChildAt(i).startAnimation(animation);
}
else
{
i=0;
}
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
}
});
zoom_out.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// TODO Auto-generated method stub
viewGroup.getChildAt(i).setVisibility(View.INVISIBLE);
viewGroup.getChildAt(i).clearAnimation();
if(i<5)
{
i++;
viewGroup.getChildAt(i).startAnimation(animation);
}
else
{
viewGroup.getChildAt(i).startAnimation(zoom_in);
i=0;
}
}
});
The animation zoom_in and zoom_out are simple zoom in and zoom out animations. When I run this code on Android 4.2 or higher it works perfectly. But on lower then it doesnot work similarly. Can anyone explain me or provide any solution for this problem. I want it to work similar on all devices 4.0 and higher.
I need some information why my animation are making devices to lag. The current problem is seen in Samsung Galaxy Tab Pro 8.4'', but in all devices the are slight lags, kaing writing on keyboard heavy. Thank you for your cooperation !!! :)
PS: Thanks Mikael :). Here is some code. Its complicated animation and it contains several parts very similar to this one with combine animation of several views.
CODE :
mTriangleButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
mLearnMore = (LinearLayout) ((LoginActivity) context)
.findViewById(R.id.learn_more);
if (mAccNameEmail.isShown()) {
// Slider
if (BookshelfApp.isTablet(context)) {
if(getActivity().getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE) {
mDeseretLogo.setVisibility(View.VISIBLE);
mSquigle.setVisibility(View.VISIBLE);
mBorder.setVisibility(View.VISIBLE);
imm.toggleSoftInput(InputMethodManager.RESULT_HIDDEN, 0);
}
view.animate().translationX(0);
view.animate().setDuration(500);
mLearnMore.animate().translationX(0);
mLearnMore.animate().setDuration(500);
mLearnMore.animate().setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
mLearnMore.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
//XXX
} else if (!BookshelfApp.isTablet(context)) {
mCreateAccFragment.animate().translationY(0);
mDeseretLogo.setVisibility(View.VISIBLE);
mSquigle.setVisibility(View.VISIBLE);
mBorder.setVisibility(View.VISIBLE);
}
mTextHint1.setVisibility(View.VISIBLE);
mTextHint2.setVisibility(View.VISIBLE);
mTriangleButton.animate().rotation(0);
mTriangleButton.animate().setDuration(500);
mAccPasswords.setVisibility(View.GONE);
mAccNameEmail.setVisibility(View.GONE);
mSignUpButton.setBackgroundDrawable(getResources()
.getDrawable(R.drawable.sign_up_shape));
mSignUpButton.setTextColor(getResources().getColor(
R.color.orange));
mLoginFormView.setVisibility(View.VISIBLE);
mSignInButton.setVisibility(View.VISIBLE);
mForgotPasswordView.setVisibility(View.VISIBLE);
mCreateAccountQuestion
.setText(R.string.acc_question_welcome);
mCreateAccountWord.setText(R.string.acc_welcome);
mHaveAccountButton.setVisibility(View.GONE);
} else {
// Slider
if (BookshelfApp.isTablet(context)) {
if(getActivity().getResources().getConfiguration().orientation==Configuration.ORIENTATION_LANDSCAPE) {
mDeseretLogo.setVisibility(View.GONE);
mSquigle.setVisibility(View.GONE);
mBorder.setVisibility(View.GONE);
imm.toggleSoftInput(InputMethodManager.RESULT_SHOWN, 0);
}
view.animate().translationX(-view.getWidth() / 4);
view.animate().setDuration(500);
mLearnMore.animate().translationX(view.getWidth() / 2);
mLearnMore.animate().setDuration(500);
mLearnMore.animate().setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animator animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animator animation) {
mLearnMore.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationCancel(Animator animation) {
// TODO Auto-generated method stub
}
});
}
//XXX
else if (!BookshelfApp.isTablet(context)) {
mDeseretLogo.setVisibility(View.GONE);
mSquigle.setVisibility(View.GONE);
mBorder.setVisibility(View.GONE);
}
mTextHint1.setVisibility(View.GONE);
mTextHint2.setVisibility(View.GONE);
mLoginFormView.setVisibility(View.GONE);
mSignInButton.setVisibility(View.GONE);
mForgotPasswordView.setVisibility(View.GONE);
mTriangleButton.animate().rotation(180);
mTriangleButton.animate().setDuration(300);
mAccPasswords.setVisibility(View.VISIBLE);
mAccNameEmail.setVisibility(View.VISIBLE);
mSignUpButton.setBackgroundDrawable(getResources()
.getDrawable(R.drawable.sign_in_shape));
mSignUpButton.setTextColor(getResources().getColor(
R.color.white));
mCreateAccountQuestion.setText(R.string.acc_question);
mCreateAccountWord.setText(R.string.acc_done);
mHaveAccountButton.setVisibility(View.VISIBLE);
}
}
});
I have a fragment that has an animation of textView fadein. The animation must start after some time delay say 2 seconds after fragment is loaded. I wrote a code for this. but the animation part is done and then the view is rendered. How can I load the fragment and after some time delay start my animation
My code is as below: Note: the class extends Fragment
Animation animFadein;
MenuClickHelper mClickHelper;
TextView tv;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_main_menu,
container, false);
mClickHelper = new MenuClickHelper(rootView, getFragmentManager());
tv = (TextView) rootView.findViewById(R.id.tvPresentation);
animFadein = AnimationUtils.loadAnimation(getActivity()
.getApplicationContext(), R.anim.fade_in);
animFadein.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
if (animation == animFadein) {
Toast.makeText(getActivity().getApplicationContext(),
"Animation Stopped", Toast.LENGTH_SHORT).show();
}
}
});
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return rootView;
}
Thread.sleep(2000); dont block your main using the sleep method instead you can use the Handler class and use postdelay to delay the animation:
sample:
change this:
try {
Thread.sleep(2000);
tv.startAnimation(animFadein);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
to
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
tv.startAnimation(animFadein);
}
}, 2000); //will start animation in 2 seconds
You can achieve the same result with
android:startOffset="2000"
in your XML animation set file.
I've write an Animation for make text of a TextView blink, and i would perform an action after animation ends.
It's possible to intercept end of animation in some way?
AnimationListener listener = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
// Do your stuff
}
};
I want to create an android project. Which there is a layout that I want it to move smoothly on another layout. I have tried to use thread in order to do this. But in the result of my code, the layout jumps to its final position and do not move smoothly from the offset to its destination.
abs1 = (AbsoluteLayout) findViewById(R.id.absoluteLayout2);
ImageButton ib1 = (ImageButton) findViewById(R.id.imageButton1);
ib1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
Runnable r = new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
try {
display(100);
display(100);
display(100);
display(100);
display(100);
display(100);
display(100);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void display(int i) throws InterruptedException {
AbsoluteLayout.LayoutParams param = (AbsoluteLayout.LayoutParams) abs1
.getLayoutParams();
param.x = param.x + 10;
// param.y=param.x+20;
abs1.setLayoutParams(param);
if (Thread.interrupted()) {
throw (new InterruptedException());
}
Thread.sleep(i);
}
};
r.run();
main file:
<AbsoluteLayout
android:id="#+id/absoluteLayout2"
android:layout_width="107dp"
android:layout_height="308dp"
android:layout_x="10dp"
android:layout_y="12dp"
android:background="#color/red" >
<ImageButton
android:id="#+id/imageButton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_x="0dp"
android:layout_y="0dp"
android:background="#null"
android:src="#drawable/calendar" />
EDIT: this is available starting from API 11
Just use an ObjectAnimator for that:
ObjectAnimator moveToSide = ObjectAnimator.ofFloat(myView, "translationX", 0f, 400f);
moveToSide.setDuration(700);
moveToSide.start();
Just try it out with different float values. Now, it starts from it's original position to 400f along the X-axis.
Afterwards it will stay in this position. You could also add an AnimatorListener if you want to do some stuff on the start or at the end.
moveToSide.addListener(new AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {
}
#Override
public void onAnimationRepeat(Animator animation) {
}
#Override
public void onAnimationEnd(Animator animation) {
}
#Override
public void onAnimationCancel(Animator arg0) {
}
});
Your Runnable is actually running on Android's UI thread.
So sleep() will block UI's drawing process, show the view on final position.
Use a Thread to wrap it.
(new Thread(new Runnable() {
#Override
public void run() {
// your code
}
}
})).start();
Then, remember that updating views from non-UI thread is forbidden.
You should use runOnUiThread to update views.
runOnUiThread(new Runnable() {
#Override
public void run() {
display(100);
}
}
Maybe, use Android's Animation class is a better way to do this.