Disabling all animations in an android app - android

I want to disable all the animations that happen when launching a new activity in my android app (for all the activities). Is there a way to achieve this once and for all? Or should I go to each and every activity and use Intent.FLAG_ACTIVITY_NO_ANIMATION or overridePendingTransition or both?

You can use style if you want:
<style name="noAnimTheme" parent="android:Theme">
<item name="android:windowAnimationStyle">#null</item>
</style>
And set them for your activity:
<activity android:name=".ui.ArticlesActivity" android:theme="#style/noAnimTheme">
</activity>
Let me know if thats what you meant...
Credit to #Santosh https://stackoverflow.com/a/9312957/3180983
When I built my app, I used only one activity. On the activity there was 4 Custom views. Each custom view represent another "Activity" its not really activity... Im playing with few custom view so each one is another window...
Here is the code with animation (*** IF you don't want animation SKIP THIS CODE to the next goToRegistrationPage() down below.):
//This code change the view so that the register form will appear. instead of changing activity with animation.
public void goToRegistrationPage()
{
Animation animationRightX1 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x1);
//animationRightX1.
Animation animationRightX2 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x2);
Animation animationRightX3 = AnimationUtils.loadAnimation(this, R.anim.translate_right_x3);
final int width = this.getWindowManager().getDefaultDisplay().getWidth();
layout.MainView.setVisibility(View.GONE);
layout.MainLogin.startAnimation(animationRightX1);
layout.MainRegister.startAnimation(animationRightX1);
animationRightX1.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
layout.layoutScroll.scrollTo((width*2), 0);
layout.MainView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
And here is the code without the animation (This is what you need):
//This code change the view so that the register form will appear. instead of changing activity
//Go to the registration form from the main view.
public void goToRegistrationPageFromMainView()
{
final int width = this.getWindowManager().getDefaultDisplay().getWidth();
layout.layoutScroll.scrollTo((width*2), 0); // its width*2 because there is the "some other view" so it need to go 2 times width to the right side...
}
So basically what you do here is scrolling windows with width amount of pixels.
layoutscroll is the pink color in the picture.
layout is a class which I created to store all the layouts... its a personal preference you could do this.layoutscroll....
Mainview, other view, and registration form are custom views that extending linearlayout... you can attach to each one of them XML file with linear layout inflater...
Ofcorse that you make the scroll view unscrollable....

Related

Android: How to create bed design in xml?

Actually i am able to create this design by using RotateAnimation but getting problem when i want to change it and applying any animation.We know, Animation does not alter the actual properties of the View, it only animates it. So every time i am facing the issue like :
animation get back to its real state after finishing the animation and
start every time from initial position.
So to avoid this i want to apply static design in xml . I tried using android:rotation but not getting as per the exact requirement.
suggestions and helps will be mostly appreciable. Please suggest.
I know android:fillAfter="true" causes many problems!
Another option would be you could add animation listeners to the animation and once that animation finished, you manually set final transfomrations to the views.
yourAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
/* Here, you could set them manually */
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});

FloatingActionButton expand into a new activity

On the android material design principles page, one of the examples shows a FAB expanding into a new full screen. (Under "Full Screen")
http://www.google.com/design/spec/components/buttons-floating-action-button.html#buttons-floating-action-button-transitions
I've tried to implement the same effect in my app, but with little success.
I managed to create a FAB that expands into a view using this code as reference: https://gist.github.com/chris95x8/882b5c5d0aa2096236ba.
It worked, but I was wondering whether I could apply the same effect to an activity transition. I've tried looking it up and playing with it myself but could not find anything that might work.
I know I could make the FAB expand into a Fragment and not a whole new activity, but I'm not sure if that's what being done, and whether that's optimal or not.
And so my question is, is there a way to implement the fab-expanding reveal effect as an activity transition, or is it supposed to just reveal a new fragment?
I am developing an app which expands a FloatingActionButton into a new Activity. I'm not sure that if you like my implementation, but please see pictures at first:
So the first picture shows MainActivity and the last one shows SecondActivity, which is "expanded" from FAB.
Now, I want to mention that I'm not actually expanding a FAB into a new Activity but I can let user feel that the new page is expanded from that FAB, and I think that's enough for both developers and users.
Here's implementation:
Preparation:
A FloatingActionButton of course,
Visit https://github.com/kyze8439690/RevealLayout and import this library to your project. It is used to play reveal animation. It has a custom BakedBezierInterpolator to control reveal animation and make it material-styled.
Steps:
create activity_main.xml like this:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--Your main content here-->
<RevealLayout
android:id="#+id/reveal_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible">
<View
android:id="#+id/reveal_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
</RevealLayout>
</FrameLayout>
find Views:
mRevealLayout = (RevealLayout) findViewById(R.id.reveal_layout);
mRevealView = findViewById(R.id.reveal_view);
expand when user clicks FAB:
mFab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mFab.setClickable(false); // Avoid naughty guys clicking FAB again and again...
int[] location = new int[2];
mFab.getLocationOnScreen(location);
location[0] += mFab.getWidth() / 2;
location[1] += mFab.getHeight() / 2;
final Intent intent = new Intent(MainActivity.this, SecondActivity.class);
mRevealView.setVisibility(View.VISIBLE);
mRevealLayout.setVisibility(View.VISIBLE);
mRevealLayout.show(location[0], location[1]); // Expand from center of FAB. Actually, it just plays reveal animation.
mFab.postDelayed(new Runnable() {
#Override
public void run() {
startActivity(intent);
/**
* Without using R.anim.hold, the screen will flash because of transition
* of Activities.
*/
overridePendingTransition(0, R.anim.hold);
}
}, 600); // 600 is default duration of reveal animation in RevealLayout
mFab.postDelayed(new Runnable() {
#Override
public void run() {
mFab.setClickable(true);
mRevealLayout.setVisibility(View.INVISIBLE);
mViewToReveal.setVisibility(View.INVISIBLE);
}
}, 960); // Or some numbers larger than 600.
}
});
And here is hold.xml in res/anim:
<set
xmlns:android="http://schemas.android.com/apk/res/android"
android:shareInterpolator="false">
<translate
android:duration="960" <!-- Enough-large time is OK -->
android:fromXDelta="0%"
android:fromYDelta="0%"
android:toXDelta="0%"
android:toYDelta="0%"/>
</set>
That's all.
Improvements:
RevealLayout has a bug(plays rectangular instead of circular reveal animation) for devices under API 17(Android 4.2), you can add these lines in constructor of it:
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR2) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
If your SecondActivity contains complicated contents, a simple View used as reveal_view in the layout.xml isn't enough/perfect. You can include the second layout inside the RevealLayout reveal_layout. It seems wasteful and hard to control if the second layout won't appear same at every time. But for me, it will. So you can make other improvements if you should.
If you want to implement totally same animation shown in Material Design Guide, you can set layout_height of the RevealLayout into a specific number instead of match_parent. After expanding animation ends(or some time after the animation plays, which should make the whole process of animation smoothly), then you can animate translationY. The important point is, just cheat users visually by controlling animation duration.
Finally, this is my own experience/attempt and I'm a beginner in developing Android apps. If there are any mistakes/further improvements, please leave comments/edit my answer. Thank you.
I made a custom activity, based on this question Circular reveal transition for new activity , that handle the CircularRevealAnimation and his reverse effect when the activity finish:
public class RevealActivity extends AppCompatActivity {
private View revealView;
public static final String REVEAL_X="REVEAL_X";
public static final String REVEAL_Y="REVEAL_Y";
public void showRevealEffect(Bundle savedInstanceState, final View rootView) {
revealView=rootView;
if (savedInstanceState == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
rootView.setVisibility(View.INVISIBLE);
ViewTreeObserver viewTreeObserver = rootView.getViewTreeObserver();
if(viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
circularRevealActivity(rootView);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
rootView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
rootView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
}
});
}
}
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void circularRevealActivity(View rootView) {
int cx = getIntent().getIntExtra(REVEAL_X, 0);
int cy = getIntent().getIntExtra(REVEAL_Y, 0);
float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());
// create the animator for this view (the start radius is zero)
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, 0, finalRadius);
circularReveal.setDuration(400);
// make the view visible and start the animation
rootView.setVisibility(View.VISIBLE);
circularReveal.start();
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home: onBackPressed();break;
return super.onOptionsItemSelected(item);
}
}
#Override
public void onBackPressed() {
destroyActivity(revealView);
}
private void destroyActivity(View rootView) {
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP)
destroyCircularRevealActivity(rootView);
else
finish();
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
private void destroyCircularRevealActivity(final View rootView) {
int cx = getIntent().getIntExtra(REVEAL_X, 0);
int cy = getIntent().getIntExtra(REVEAL_Y, 0);
float finalRadius = Math.max(rootView.getWidth(), rootView.getHeight());
// create the animator for this view (the start radius is zero)
Animator circularReveal = ViewAnimationUtils.createCircularReveal(rootView, cx, cy, finalRadius, 0);
circularReveal.setDuration(400);
circularReveal.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
rootView.setVisibility(View.INVISIBLE);
finishAfterTransition();
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
});
// make the view visible and start the animation
rootView.setVisibility(View.VISIBLE);
circularReveal.start();
}
}
You can extend this with your own activity and call in your onCreate the method 'showRevealEffect' like this:
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_activity_layout);
//your code
View root= findViewById(R.id.your_root_id);
showRevealEffect(savedInstanceState, root);
}
You also have to use a transparent theme like this one:
<style name="Theme.Transparent" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">#android:color/transparent</item>
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
<item name="colorControlNormal">#android:color/white</item>
</style>
In the end, to launch this activity you should pass via extra the coordinates where the animation should start:
int[] location = new int[2];
fab.getLocationOnScreen(location);
Intent intent = new Intent(this, YourRevealActivity.class);
intent.putExtra(SearchActivity.REVEAL_X, location[0]);
intent.putExtra(SearchActivity.REVEAL_Y, location[1]);
startActivity(intent);
you can use this lib [https://github.com/sergiocasero/RevealFAB][1]
[1]: https://github.com/sergiocasero/RevealFAB 3rd party its easy and simple to use
Add to your layout
<RelativeLayout...>
<android.support.design.widget.CoordinatorLayout...>
<!-- YOUR CONTENT -->
</android.support.design.widget.CoordinatorLayout>
<com.sergiocasero.revealfab.RevealFAB
android:id="#+id/reveal_fab"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fab_color="#color/colorAccent"
app:fab_icon="#drawable/ic_add_white_24dp"
app:reveal_color="#color/colorAccent" />
</RelativeLayout>
Important: This component goes above your content. You can use Coordinator, LinearLayout... or another Relative layout if you want :)
As you can see, you have 3 custom attributes for customizing colors and icon
Setting information about intent:
revealFAB = (RevealFAB) findViewById(R.id.reveal_fab);
Intent intent = new Intent(MainActivity.this, DetailActivity.class);
revealFAB.setIntent(intent);
revealFAB.setOnClickListener(new RevealFAB.OnClickListener() {
#Override
public void onClick(RevealFAB button, View v) {
button.startActivityWithAnimation();
}
});
Don't forget call onResume() method!
#Override
protected void onResume() {
super.onResume();
revealFAB.onResume();
}
Someone investigated the implementation of transition between activities from Plaid. Her example were published via https://github.com/hujiaweibujidao/FabDialogMorph.
Briefly speaking, she transits two activities with:
The FAB as the shared element.
The layout in the target activity with the same android:transitionName as the FAB.
To smooth the animation, MorphDrawable (extended from Drawable) and MorphTransition (extended from ChangeBounds) are implemented and applied.

Android fragment animation first time stuck

I am doing an animation inside a fragment.
I have 2 views on top of each other, one of them set on View.GONE.
when I press a button I want my 2nd fragment to translate animation from the bottom to top.
I am doing it fine and it's working great,
the problem is that in my first run, the xml view is gone, but he is in the same Y he is suppose to be.
so the first animation I do isn't doing anything, just switch from GONE to VISIBLE, after that, I press dismiss and the fragment goes away and comes back just like I want too.
my problem is just the first run.
how can I set my view Y to be 100% below my screen?
here's the code I use :
private void moreCustomAnimation() {
int yOffset = moreMenuFrameLayout.getMeasuredHeight();
TranslateAnimation moveAnim = new TranslateAnimation(0, 0, yOffset, 0);
moveAnim.setDuration(500);
moveAnim.setFillAfter(true);
blackView.setVisibility(View.VISIBLE);
moreMenuFrameLayout.setVisibility(View.VISIBLE);
moreMenuFrameLayout.startAnimation(moveAnim);
moveAnim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
on the way out of the screen I use the same code just switch the
yOffset to the other Y integer, and set the view to GONE at animation end.
thanks a lot in advance for any help !
You can use the onGlobalLayout event to set the position of the view.
Like this:
moreMenuFrameLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
moreMenuFrameLayout.setTranslationY(moreMenuFrameLayout.getMeasuredHeight());
moreMenuFrameLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
This event happens when your views get their actual size and position before being drawn to the screen. However, they happen every time the view is drawn so you must remember to remove the listener right after the first time.
HTH
First time you can add the 'yOffset' value to the view orginal points
moreMenuFrameLayout.setY(currentYpostition + yOffset)
and this will place the view to the bottom of the screen. You can enable the visibility when the animation starts.

Buttons on an animated view respond to clicks even when off screen?

I have a LinearLayout, I'm applying a translation animation to it. I'm filling the animation before and after. Visually it works fine. The animation ends by translating the view off screen. But if I click an x,y coordinate on screen that happens to be where the view was at some point during its animation, a button on the view has its click listener fire.
The only solution I've found is to add an animation listener, and when the animation ends, mark the buttons on the (now out of view) layout to visibility=gone, enabled=false. This seems bizarre - the view is no longer on screen, but it's still responding to click events. Is this a known thing, I'm probably not setting the animation up correctly?
Thanks
----- Update --------
I refactored my animation a little. Instead of using animation.setFillAfter(true), I set the layout's visibility to GONE when the animation is complete. Now it doesn't register clicks when off-screen. Still interested to know if this is a known thing, as it'd be easier to simply not have to add an animation listener etc.
Translate Animations on lower level API( below honey comb) changes where the button is drawn, but not where the button physically exists within the container. So, you are on your own to handle this situation. For more information about this you can refer to this link. One way is to actually change the location of the button in the layout(not by animation). Here is how you can achieve this:
params = (LayoutParams) mBtn.getLayoutParams();
TranslateAnimation animation = new TranslateAnimation(0, 0, 0, 400);
animation.setDuration(2000);
animation.setAnimationListener(mAnimationListener);
mBtn.startAnimation(animation);
....
....
private AnimationListener mAnimationListener = new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
params.topMargin = params.topMargin + 400;
mButton.setLayoutParams(params);
}
};
Here by changing the layout params we are changing the physical position of the button.
In your case as view is going off the screen so you just need to change the visibility of the button(View.GONE) on animation end.

OnclickListener for Animated View

found many question on same issue.
How to set OnClickListener on the ImageView after rotation animation
How to write the onclick listener for a view after animation?
i also have same issue, any suggestion ?
You ought to write a fresh, concise question about your specific issue rather than just pointing to other questions. The two questions linked to aren't entirely clear.
I assume your issue is that after applying an animation (such as a TranslateAnimation, for example) to a View, the View no longer responds to touch events in its new position. The reason for this is because the View hasn't been moved to the new position in terms of layout parameters, but rather it has had a transformation applied.
The solution is quite simple: immediately after the animation has completed, actually move the View to the new position. You could set myAnimation.setFillAfter() = false, and set a listener to physically move the View to the target location when the animation has finished:
myAmazingAnimation.setFillAfter() = false;
myAmazingAnimation.setAnimationListener(new Animation.AnimationListener(){
#Override
public void onAnimationEnd(Animation animation) {
// Now actually move the View using LayoutParams
}
#Override
public void onAnimationRepeat(Animation animation) {
}
#Override
public void onAnimationStart(Animation animation) {
}
});
Another variation is to physically move the View at the beginning before animation is applied, and then apply an animation that makes the View start where it used to be and end at 0,0.

Categories

Resources