I'm trying to go around different functionality integrated with Android Material Design but I can't to do this type of animation when a view fill another like that :
Do you know how to do it or a library/project an example that does this?
I tried to implement this below API 21
add gradle dependancy
dependencies {
compile 'com.github.ozodrukh:CircularReveal:1.0.6#aar'
}
My activity xml is
activity_reval_anim.xml
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".RevalAnimActivity">
<ImageView
android:id="#+id/img_top"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:background="#color/color_primary"
android:src="#drawable/ala"/>
<io.codetail.widget.RevealLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_below="#+id/img_top"
android:background="#color/color_primary">
<LinearLayout
android:visibility="invisible"
android:id="#+id/ll_reveal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/color_accent"
android:orientation="horizontal"
></LinearLayout>
</io.codetail.widget.RevealLinearLayout>
<ImageButton
android:id="#+id/img_floating_btn"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_alignParentRight="true"
android:layout_marginRight="40dp"
android:layout_marginTop="170dp"
android:background="#drawable/expand_btn"/>
</RelativeLayout>
My Activity java is
RevalAnimActivity.java
public class RevalAnimActivity extends ActionBarActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reval_anim);
final ImageButton mFloatingButton = (ImageButton) findViewById(R.id.img_floating_btn);
mFloatingButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
animateButton(mFloatingButton);
}
});
}
private void animateButton(final ImageButton mFloatingButton) {
mFloatingButton.animate().translationXBy(0.5f).translationY(150).translationXBy(-0.9f)
.translationX(-150). setDuration(300).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
animateReavel((int) mFloatingButton.getX(), 150,mFloatingButton);
}
});
}
private void animateReavel(int cx, int cy, final ImageButton mFloatingButton) {
final View myView = findViewById(R.id.ll_reveal);
// get the final radius for the clipping circle
float finalRadius = hypo(myView.getWidth(), myView.getHeight());
SupportAnimator animator =
ViewAnimationUtils.createCircularReveal(myView, cx, cy, 0, finalRadius);
animator.addListener(new SupportAnimator.AnimatorListener() {
#Override
public void onAnimationStart() {
mFloatingButton.setVisibility(View.INVISIBLE);
myView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationEnd() {
Toast.makeText(getApplicationContext(), "Done", Toast.LENGTH_LONG)
.show();
}
#Override
public void onAnimationCancel() {
}
#Override
public void onAnimationRepeat() {
}
});
animator.setInterpolator(new AccelerateDecelerateInterpolator());
animator.setDuration(1000);
animator.start();
}
static float hypo(int a, int b) {
return (float) Math.sqrt(Math.pow(a, 2) + Math.pow(b, 2));
}
}
The solution to do that is pathInterpolator and the name of this effect is Curved Motion.
Animations in material design rely on curves for time interpolation
and spatial movement patterns. With Android 5.0 (API level 21) and
above, you can define custom timing curves and curved motion patterns
for animations.
You can see how to implement it here :
http://developer.android.com/training/material/animations.html#CurvedMotion
And sample on GitHub HERE :
Related
I would like to expand/collapse an ImageView but start from 50% picture to expand at 100%, collapse to 50% not under.
I already took a look at some popular questions and answers on SO but I didn't find how to manage only half. I also want to modify on the height of view, not the width.
What I tried :
public static void expand(final View v) {
v.measure(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
final int targtetHeight = v.getMeasuredHeight();
v.getLayoutParams().height = 0;
v.setVisibility(View.VISIBLE);
Animation a = new Animation()
{
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
v.getLayoutParams().height = interpolatedTime == 1
? ViewGroup.LayoutParams.WRAP_CONTENT
: (int)(targtetHeight * interpolatedTime);
v.requestLayout();
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int)(targtetHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
public static void collapse(final View v) {
final int initialHeight = v.getMeasuredHeight();
Animation a = new Animation() {
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
if (interpolatedTime == 1) {
v.setVisibility(View.VISIBLE);
} else {
v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime);
v.requestLayout();
}
}
#Override
public boolean willChangeBounds() {
return true;
}
};
a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density));
v.startAnimation(a);
}
as I said it's not what I want because it make disappeared totally and it change the width.
I also tried this snippet but there is no animation :
mImageDrawable = (ClipDrawable) pic.getDrawable();
mImageDrawable.setLevel(5000);//use set level to expand or collapse manually but no animation.
clip:
<?xml version="1.0" encoding="utf-8"?>
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="vertical"
android:drawable="#drawable/test_pic"
android:gravity="top" />
Use Transition API which is available in support package (androidx). Just call TransitionManager.beginDelayedTransition then change height of view. TransitionManager will handle this changes and it will provide transition which will change imageView with animation.
scaleType of ImageView here is centerCrop thats why image scales when collapse and expand. Unfortunetly there is no "fill width and crop bottom" scaleType, so if you need it I think it can be done throught scaleType = matrix .
import androidx.appcompat.app.AppCompatActivity;
import androidx.transition.TransitionManager;
public class MainActivity extends AppCompatActivity {
private ImageView image;
private ViewGroup parent;
boolean collapse = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
image = findViewById(R.id.image);
parent = findViewById(R.id.parent);
findViewById(R.id.btn).setOnClickListener(view -> {
collapse = !collapse;
collapse();
});
}
private void collapse() {
TransitionManager.beginDelayedTransition(parent);
//change layout params
int height = image.getHeight();
LayoutParams layoutParams = image.getLayoutParams();
layoutParams.height = !collapse ? height / 2 : height * 2;
image.requestLayout();
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<Button
android:id="#+id/btn"
android:text="start"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<ImageView
android:id="#+id/image"
android:layout_width="match_parent"
android:layout_height="300dp"
android:scaleType="centerCrop"
android:src="#drawable/qwe" />
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="random text"
android:layout_margin="8dp"/>
</LinearLayout>
UPDATE:
There is beginDelayedTransition(ViewGroup, Transtion) method. beginDelayedTransition(ViewGroup) by default use AutoTransition as transition.
So if you need handle start/end of transition you can do it like this:
AutoTransition transition = new AutoTransition();
transition.addListener(new TransitionListenerAdapter(){
#Override
public void onTransitionStart(#NonNull Transition transition) {
//TODO
}
#Override
public void onTransitionEnd(#NonNull Transition transition) {
//TODO
}
});
TransitionManager.beginDelayedTransition(parent, transition);
I'm trying to reproduce this animation from an iOS app in Android. and I'm stuck
If anyone knows how to create them will be deeply grateful. Don't mind the logo in the center, just those rings pulsating. (is possible 3 at a time, short break, repeat)
Here's a possible solution, but it's quite ugly and I'm sure something nicer can be made
3 imageviews one on top of eachother
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
>
<ImageView
android:id="#+id/imageView_circle1"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
app:srcCompat="#drawable/circle"
/>
<ImageView
android:id="#+id/imageView_circle2"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
app:srcCompat="#drawable/circle"
/>
<ImageView
android:id="#+id/imageView_circle3"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
app:srcCompat="#drawable/circle"
/>
<ImageView
android:id="#+id/imageView_logo"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:scaleType="fitCenter"
app:srcCompat="#drawable/logo"
/>
</RelativeLayout>
a drawable circle.xml
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<solid android:color="#DDDDDD"/>
</shape>
an animation zoom_and_fade.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="false">
<alpha
android:duration="3500"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
<scale
android:duration="3500"
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="50"
android:toYScale="50" />
</set>
on Activity:
imageView_circle1 = (ImageView) findViewById(R.id.imageView_circle1);
imageView_circle2 = (ImageView) findViewById(R.id.imageView_circle2);
imageView_circle3 = (ImageView) findViewById(R.id.imageView_circle3);
anim1 = AnimationUtils.loadAnimation(this, R.anim.zoom_and_fade);
anim2 = AnimationUtils.loadAnimation(this, R.anim.zoom_and_fade);
anim3 = AnimationUtils.loadAnimation(this, R.anim.zoom_and_fade);
anim2.setStartOffset(800);
anim3.setStartOffset(1600);
imageView_circle1.startAnimation(anim1);
imageView_circle2.startAnimation(anim2);
imageView_circle3.startAnimation(anim3);
anim2.setAnimationListener(new Animation.AnimationListener() {
#Override public void onAnimationStart(Animation animation) {
}
#Override public void onAnimationEnd(Animation animation) {
imageView_circle1.startAnimation(anim1);
imageView_circle2.startAnimation(anim2);
imageView_circle3.startAnimation(anim3);
}
#Override public void onAnimationRepeat(Animation animation) {
}
});
I don't think you can achieve same result with only XML.
This is really rough code (Literally 5 minutes) using canvas. But I think with some minor changes you can get really nice Animation.
Check out the video. https://www.youtube.com/watch?v=378Jjc4amD8.
I'll improve if you like it.
public class CircleAnimationView extends View {
private Paint[] paints = new Paint[3];
private int[] colors = new int[3];
private float[] circleRadius = new float[3];
public CircleAnimationView(Context context) {
super(context);
init();
}
public CircleAnimationView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
colors[0] = ContextCompat.getColor(getContext(), R.color.gray1);
colors[1] = ContextCompat.getColor(getContext(), R.color.gray2);
colors[2] = ContextCompat.getColor(getContext(), R.color.gray3);
for (int i = 0; i < paints.length; i++) {
paints[i] = new Paint();
paints[i].setAntiAlias(true);
paints[i].setStyle(Paint.Style.FILL);
paints[i].setColor(colors[i]);
}
}
public void startCircleAnimation() {
CircleRadiusAnimation animation = new CircleRadiusAnimation();
animation.setDuration(1500);
animation.setRepeatCount(Animation.INFINITE);
startAnimation(animation);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, circleRadius[0], paints[0]);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, circleRadius[1], paints[1]);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, circleRadius[2], paints[2]);
}
private class CircleRadiusAnimation extends Animation {
public CircleRadiusAnimation() {
setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
reset();
}
});
}
public void reset() {
circleRadius[0] = 0;
circleRadius[1] = 0;
circleRadius[2] = 0;
CircleAnimationView.this.requestLayout();
CircleAnimationView.this.invalidate();
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation transformation) {
circleRadius[0] += 10;
if (interpolatedTime > 0.3) {
circleRadius[1] += 10;
Log.d("animate", "2nd circle");
}
if (interpolatedTime > 0.6) {
circleRadius[2] += 10;
Log.d("animate", "3nd circle");
}
CircleAnimationView.this.requestLayout();
CircleAnimationView.this.invalidate();
}
}
}}
We want a Meter animation in TextView
To make it a little more interesting, I want each digit come from top to bottom or bottom to top ?
Right now I using listview for achieving this, I have also tried with TextSwitcher but its have a limitation of two child only.
I'm using getListView().smoothScrollToPosition(0...3...6...6...n);
Is there a simple way of doing this? because right now , we need to maintain 3 ListView and Adapter as well for maintaining this.
Please refer link to more understand this question
Display StopWatch Timer animated like the petrol pump meter using NSTimer
ListView's might be good enough solution, but I've implemented it with a custom View (FrameLayout), which contains inside 2 TextViews, which are animating based on the value changes:
The idea of code is very basic:
You pass to setValue desired value;
If it's bigger than current one - start animation from from bottom to top (and vice versa) to increment/decrement current value by 1. Here, we animating two TextViews to replace each other;
In AnimationEnd listener, check if we reached desired value - if not - do one more run (recursively);
public class DigitTextView extends FrameLayout {
private static int ANIMATION_DURATION = 250;
TextView currentTextView, nextTextView;
public DigitTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public DigitTextView(Context context) {
super(context);
init(context);
}
private void init(Context context) {
LayoutInflater.from(context).inflate(R.layout.digit_text_view, this);
currentTextView = (TextView) getRootView().findViewById(R.id.currentTextView);
nextTextView = (TextView) getRootView().findViewById(R.id.nextTextView);
nextTextView.setTranslationY(getHeight());
setValue(0);
}
public void setValue(final int desiredValue) {
if (currentTextView.getText() == null || currentTextView.getText().length() == 0) {
currentTextView.setText(String.format(Locale.getDefault(), "%d", desiredValue));
}
final int oldValue = Integer.parseInt(currentTextView.getText().toString());
if (oldValue > desiredValue) {
nextTextView.setText(String.format(Locale.getDefault(), "%d", oldValue-1));
currentTextView.animate().translationY(-getHeight()).setDuration(ANIMATION_DURATION).start();
nextTextView.setTranslationY(nextTextView.getHeight());
nextTextView.animate().translationY(0).setDuration(ANIMATION_DURATION).setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {}
#Override
public void onAnimationEnd(Animator animation) {
currentTextView.setText(String.format(Locale.getDefault(), "%d", oldValue - 1));
currentTextView.setTranslationY(0);
if (oldValue - 1 != desiredValue) {
setValue(desiredValue);
}
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
}).start();
} else if (oldValue < desiredValue) {
nextTextView.setText(String.format(Locale.getDefault(), "%d", oldValue+1));
currentTextView.animate().translationY(getHeight()).setDuration(ANIMATION_DURATION).start();
nextTextView.setTranslationY(-nextTextView.getHeight());
nextTextView.animate().translationY(0).setDuration(ANIMATION_DURATION).setListener(new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animation) {}
#Override
public void onAnimationEnd(Animator animation) {
currentTextView.setText(String.format(Locale.getDefault(), "%d", oldValue + 1));
currentTextView.setTranslationY(0);
if (oldValue + 1 != desiredValue) {
setValue(desiredValue);
}
}
#Override
public void onAnimationCancel(Animator animation) {}
#Override
public void onAnimationRepeat(Animator animation) {}
}).start();
}
}
}
And it's XML:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="48dp"
android:layout_height="56dp"
android:padding="8dp"
android:background="#drawable/rounded_blue_rect">
<TextView
android:id="#+id/currentTextView"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:gravity="center"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/nextTextView"
android:textColor="#FFFFFF"
android:textSize="18sp"
android:layout_gravity="center"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</FrameLayout>
And it's very easy to use:
Add to layout:
<klogi.com.myapplication.DigitTextView
android:id="#+id/digitTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
And set Value in code:
DigitTextView digitTextView = (DigitTextView) findViewById(R.id.digitTextView);
digitTextView.setValue(5);
Upd:
Another option to use, from what I see, is to set up a bit customized NumberPicker
I hope, it helps!
Ever since Robinhood won the Material design awards they have open sourced there custom TextView just like you are describing.
Check out Robinhood's Ticker library
This code performs the same animation where number rolldown from top to bottom.
Rolling-TextView-Animation
You can also use a handler to get the desired effect. Using this, you won't have to make any custom views.
Create a function handleTextView which takes in initialValue, finalValue and targetTextview as arguments. The method is-
private void handleTextView(int initialValue, int finalValue, final TextView targetTextview) {
DecelerateInterpolator decelerateInterpolator = new DecelerateInterpolator(1f);
final int newInitialValue = Math.min(initialValue, finalValue);
final int newFinalValue = Math.max(initialValue, finalValue);
final int difference = Math.abs(finalValue - initialValue);
Handler handler = new Handler();
for (int count = newInitialValue; count <= newFinalValue; count++) {
//Time to display the current value to the user.
int time = Math.round(decelerateInterpolator.getInterpolation((((float) count) / difference)) * 100) * count;
final int finalCount = ((initialValue > finalValue) ? initialValue - count : count);
handler.postDelayed(new Runnable() {
#Override
public void run() {
targetTextview.setText(finalCount.toString());
}
}, time);
}
}
UPDATE:
Option 2- You can use a value animator as well-
private void handleTextView(int initialValue, int finalValue, final TextView textview) {
ValueAnimator valueAnimator = ValueAnimator.ofInt(initialValue, finalValue);
valueAnimator.setDuration(1500);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
textview.setText(valueAnimator.getAnimatedValue().toString());
}
});
valueAnimator.start();
}
By using this method we do not need to do any math.
I have a LinearLayout with some views init (transparent grey background, TextView, View, ...). And I want to animate that with a slideIn, slideOut animation (defined in xml).
When the first animation is finished, the second animation starts. During animation you can see a stuttering.
I nearly checked all posts, no one helped !
There is no complicated code.
Load animation from xml and start animation. If the first stops, the other starts.
here is my layout of the view, which will animated:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/overlay_deal"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="#dimen/spacing_small">
<TextView
android:id="#+id/text_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="left"
android:padding="2dp"
android:textAppearance="#style/TextAp.Dyn.Fixed.Small"
android:textColor="#color/white"
android:textStyle="bold" />
<TextView
android:id="#+id/text_header_promo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="2dp"
android:text="#string/Corporate_Label_Title"
android:textAppearance="#style/TextAp.Dyn.Fixed.Small"
android:textColor="#color/white" />
</LinearLayout>
<View
android:id="#+id/text_header_underline"
android:layout_width="match_parent"
android:layout_height="3dp" />
<View
android:id="#+id/underline_spacer"
android:layout_width="match_parent"
android:layout_height="15dp"
android:background="#color/white"
android:visibility="gone" />
</LinearLayout>
This is the code:
private void initAnimations(Context context, final View defaultMoodBannerView) {
final int slideInFromTopAnimationId = R.anim.slide_in_from_top;
final int slideOutToTopAnimationId = R.anim.slide_out_to_top;
final int animationDuration = context.getResources().getInteger(android.R.integer.config_mediumAnimTime);
animationDefaultMoodBannerChangeToCorporate = AnimationUtils.loadAnimation(context, slideOutToTopAnimationId);
animationDefaultMoodBannerChangeToCorporate.setDuration(animationDuration);
animationDefaultMoodBannerSlideInFromTop = AnimationUtils.loadAnimation(context, slideInFromTopAnimationId);
animationDefaultMoodBannerSlideInFromTop.setDuration(animationDuration);
animationCorporateMoodBannerChangeToDefault = AnimationUtils.loadAnimation(context, slideOutToTopAnimationId);
animationCorporateMoodBannerChangeToDefault.setDuration(animationDuration);
animationCorporateMoodBannerSlideInFromTop = AnimationUtils.loadAnimation(context, slideInFromTopAnimationId);
animationCorporateMoodBannerSlideInFromTop.setDuration(animationDuration);
animationCorporateMoodBannerSlideOutToTop = AnimationUtils.loadAnimation(context, slideOutToTopAnimationId);
animationCorporateMoodBannerSlideOutToTop.setDuration(animationDuration);
animationDefaultMoodBannerChangeToCorporate.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (corporateMoodBannerView != null) {
if (defaultMoodBannerView != null) {
defaultMoodBannerView.setVisibility(View.GONE);
}
corporateMoodBannerView.setVisibility(View.VISIBLE);
corporateMoodBannerView.startAnimation(animationDefaultMoodBannerSlideInFromTop);
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
animationCorporateMoodBannerChangeToDefault.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (defaultMoodBannerView != null) {
if (corporateMoodBannerView != null) {
corporateMoodBannerView.setVisibility(View.GONE);
}
defaultMoodBannerView.setVisibility(View.VISIBLE);
defaultMoodBannerView.startAnimation(animationDefaultMoodBannerSlideInFromTop);
}
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
}
I have an Activity with some elements like ImageView, Button, ToggleButton, ... . And a subview (LinearLayout) that contains an HorizontalScrollView of ImageView.
The subview is an element that I want to hide / show with an animation.
My animation works successfully. But when I touch a ToggleButton or I apply a Filter, the subview is reseted and back to its origin position.
I have deduce that the subview is replaced in its origin when an element of the view visually change.
But I don't understand why...
The Activity class
public class CameraActivity extends Activity implements PictureCallback
{
private ToggleButton flashButton;
private Button filterScrollButton;
private LinearLayout filterScrollView;
private LinearLayout filterScrollViewLayout;
private Boolean filtersIsOpened = false;
private ImageView filterImageView;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_camera);
// Show the Up button in the action bar.
getActionBar().setDisplayHomeAsUpEnabled(true);
flashButton = (ToggleButton)findViewById(R.id.button_flash);
filterScrollButton = (Button)findViewById(R.id.button_open_filters);
filterScrollView = (LinearLayout)findViewById(R.id.camera_scroll_filters);
filterScrollViewLayout = (LinearLayout)findViewById(R.id.camera_scroll_filters_layout);
}
...
private void initScrollFilters()
{
String[] filters = getResources().getStringArray(R.array.array_filters);
for (final String string : filters)
{
ImageView v = new ImageView(CameraActivity.this);
int imageFilterId = -1;
if (string != null && !string.isEmpty())
{
final int imageId = getResources().getIdentifier("#drawable/filter_" + string, null, getPackageName());
imageFilterId = getResources().getIdentifier("#drawable/filter_" + string, null, getPackageName());
v.setImageDrawable(getResources().getDrawable(imageId));
}
final int finalImageFilterId = imageFilterId;
v.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View view) {
Log.d(string + " filter image is touched");
CameraActivity.this.cameraManager.setImageFilter(finalImageFilterId); // Apply the new filter into filterImageView
}
});
filterScrollViewLayout.addView(v, 100, 100);
}
}
private void initListeners()
{
// Flash
flashButton.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
{
// camera parameters is changed
}
});
// Filter scroll view
filterScrollButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v)
{
Log.d("You click the filter scroll button men!!");
final float direction = (CameraActivity.this.filtersIsOpened) ? -1 : 1;
final float yDelta = -100;
final Animation animation = new TranslateAnimation(0, 0, 0, yDelta * direction);
animation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
#Override
public void onAnimationEnd(Animation animation)
{
TranslateAnimation anim = new TranslateAnimation(0.0f, 0.0f, 0.0f, 0.0f);
anim.setDuration(1);
CameraActivity.this.filterScrollView.startAnimation(anim);
int top = (int) (CameraActivity.this.filterScrollView.getTop() + (yDelta * direction));
CameraActivity.this.filterScrollView.setTop(top);
}
});
animation.setDuration(500);
CameraActivity.this.filterScrollView.startAnimation(animation);
CameraActivity.this.filtersIsOpened = ! CameraActivity.this.filtersIsOpened;
}
});
}
...
}
The xml view
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".CameraActivity" >
<CameraPreview
android:id="#+id/camera_preview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:id="#+id/camera_preview_filter"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:rotation="90"
android:scaleType="center"
android:contentDescription="#string/content_desc_overlay" />
<LinearLayout
android:id="#+id/camera_scroll_filters"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="-40dp"
android:paddingTop="40dp"
android:orientation="vertical"
android:clickable="false"
android:longClickable="false" >
<Button
android:id="#+id/button_open_filters"
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_gravity="top|center_horizontal"
android:text="Filters" >
</Button>
<HorizontalScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FF00FF00"
android:scrollbars="none" >
<LinearLayout
android:id="#+id/camera_scroll_filters_layout"
android:layout_width="wrap_content"
android:layout_height="100dp"
android:layout_gravity="bottom"
android:orientation="horizontal" >
</LinearLayout>
</HorizontalScrollView>
</LinearLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="bottom"
android:background="#FF000000" >
</FrameLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:onClick="onCaptureClick"
android:text="#string/button_capture_text" />
</FrameLayout>