Scale view to parent layout size - android

I am trying to scale a view to layout size by using object animator. The view is a LinearLayout. The view does stretch, but not till the screen size in both the directions (i.e X and Y).
Here is the code.
I feel that either the problem is with this:
The formula to calculate how much zoom must be done.
zoomTillX = screen_width/zoomView_width;
zoomTillY = screen_height/zoomView_height;
Or with the Animation property code that is done in a wrong way.
Please let me know how can I achieve a zoom in.
public class MainActivity extends AppCompatActivity {
TextView tv;
double screen_height;
LinearLayout zoomView;
double screen_width;
double zoomTillX;
double zoomTillY;
double zoomView_width;
double zoomView_height;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = (TextView) findViewById(R.id.tv);
zoomView = (LinearLayout) findViewById(R.id.zoomView);
DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
screen_height = (double)dm.heightPixels;
screen_width = (double)dm.widthPixels;
zoomView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
zoomView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
zoomView_width = (double)zoomView.getMeasuredWidth();
zoomView_height = (double)zoomView.getMeasuredHeight();
}
});
zoomView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
#Override
public void run() {
if(zoomView_width > 0 && zoomView_height > 0)
{
zoomTillX = screen_width/zoomView_width;
zoomTillY = screen_height/zoomView_height;
Log.d("VIEW GET X IS ",String.valueOf(zoomView.getX()));
Log.d("VIEW GET Y IS ",String.valueOf(zoomView.getY()));
ObjectAnimator scaleDownX = ObjectAnimator.ofFloat(zoomView, "scaleX", (float)(zoomTillX));
ObjectAnimator scaleDownY = ObjectAnimator.ofFloat(zoomView, "scaleY",(float)(zoomTillY));
List<Animator> oaList = new ArrayList<Animator>();
oaList.add(scaleDownX);
oaList.add(scaleDownY);
AnimatorSet ani = new AnimatorSet();
ani.playTogether(oaList);
ani.setDuration(500);
ani.start();
}else{
handler.postDelayed(this,300);
}
}
},500);
}
});
}
}
This is how it looks finally.

That can be done via ValueAnimator.
Having this layout as the content of activity:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:id="#+id/view"
android:layout_width="170dp"
android:layout_height="170dp"
android:background="#3143ff"/>
</FrameLayout>
And in activity's onCreate():
final View view = findViewById(R.id.view);
final View contentView = findViewById(R.id.content_frame);
contentView.setOnClickListener(v -> {
final int screenWidth = contentView.getWidth();
final int screenHeight = contentView.getHeight();
ValueAnimator widthAnimator = ValueAnimator.ofInt(view.getWidth(), screenWidth);
ValueAnimator heightAnimator = ValueAnimator.ofInt(view.getHeight(), screenHeight);
widthAnimator.setDuration(1500);
heightAnimator.setDuration(1500);
widthAnimator.addUpdateListener(animation -> {
view.getLayoutParams().width = (int) animation.getAnimatedValue();
view.requestLayout();
});
heightAnimator.addUpdateListener(animation -> {
view.getLayoutParams().height = (int) animation.getAnimatedValue();
view.requestLayout();
});
widthAnimator.start();
heightAnimator.start();
});
This will be the result:
Transitions API
We've implemented this animation ourselves. But why won't we let the system take care of building all this animators?
There's a Transitions API, which will take the heavy lifting for us. All we have to do, is to ask the framework to detect layout changes, create appropriate animators and run the animations.
So, all the code above can be changed to following, which will result in exactly same output:
contentView.setOnClickListener(v -> {
final int screenWidth = contentView.getWidth();
final int screenHeight = contentView.getHeight();
// Uncomment this, if you want Transitions API to run default animation
// TransitionManager.beginDelayedTransition(contentView);
Transition autoTransition = new AutoTransition();
autoTransition.setDuration(1500);
// With this overload you can control actual transition animation
TransitionManager.beginDelayedTransition(contentView, autoTransition);
// After `beginDelayedTransition()` function perform changes to the layout
// Transitions framework will detect those changes and perform appropriate animations
view.getLayoutParams().width = screenWidth;
view.getLayoutParams().height = screenHeight;
view.requestLayout();
view.invalidate();
});

Related

How to start an animation immediately on activity launch without any start delay

My MainAactivity starts with a background music( via service) and I have implemented an animation which should start as soon as the activity is launched along with the background music, but the animation starts after 10 seconds of activity launch(music starts with activity launch), even though I have not implemented any start delay. Can someone help me? I am new to android.
I have followed the following tutorial for animation:
https://www.javacodegeeks.com/2012/10/android-leaf-fall-like-animation-using.html
My MainActivity.java:
private int[] PICTURES = {
R.mipmap.f1, R.mipmap.f2, R.mipmap.f3, R.mipmap.f4,
};
private Rect display_Size = new Rect();
private RelativeLayout root_Layout;
private ArrayList<View> all_imageViews = new ArrayList<View>();
private float scale;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent i = new Intent(this,MusicService.class);
startService(i);
Display display = getWindowManager().getDefaultDisplay();
display.getRectSize(display_Size);
DisplayMetrics metrics = new DisplayMetrics();
display.getMetrics(metrics);
scale = metrics.density;
root_Layout = (RelativeLayout) findViewById(R.id.main_layout);
new Timer().schedule(new ExecTime(),0 , 1000);
}
private Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
int viewId = new Random().nextInt(PICTURES.length);
Drawable d = getResources().getDrawable(PICTURES[viewId]);
LayoutInflater inflater = LayoutInflater.from(MainActivity.this);
ImageView imageView = (ImageView) inflater.inflate(R.layout.animated_image_view, null);
imageView.setImageDrawable(d);
root_Layout.addView(imageView);
all_imageViews.add(imageView);
RelativeLayout.LayoutParams animationLayout = (RelativeLayout.LayoutParams) imageView.getLayoutParams();
animationLayout.setMargins(0, (int)(-3000*scale), 0, 0);
animationLayout.width = (int) (50*scale);
animationLayout.height = (int) (50*scale);
startAnimation(imageView);
}
};
public void startAnimation(final ImageView animView) {
animView.setPivotX(animView.getWidth()/2);
animView.setPivotY(animView.getHeight()/2);
final ValueAnimator animator = ValueAnimator.ofFloat(0, 1);
animator.setDuration(15000);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
int angle = 50 + (int)(Math.random() * 101);
int move = new Random().nextInt(display_Size.right);
#Override
public void onAnimationUpdate(ValueAnimator animation) {
float value = (Float) (animation.getAnimatedValue());
animView.setRotation(angle*value);
animView.setTranslationX((move-100)*value);
animView.setTranslationY((display_Size.bottom + (3000*scale))*value);
}
});
animator.start();
}
private class ExecTime extends TimerTask {
#Override
public void run() {
handler.sendEmptyMessage(Constants.EMPTY_MESSAGE);
}
}
When application is launched android creates a new process that during it charge and create a black/white screen based on the application theme or the theme of the activity that is entry point.
This load can be increased if our application is complex and overwrites the application object, which is normally used to initialize the analytics.
Read this article for more info. http://saulmm.github.io/avoding-android-cold-starts

I want to display the image view at different position on the screen randomly

Here the ImageView is displaying only at one position, after closing the activity the next time the activity is opened the ImageView will be on another position... I want to display the ImageView randomly at diff position on the same activity itself. The image view should appear on one point suddenly the next second ImageView should disappear from that position and appear on the next position. How can i do it?
public class page2 extends ActionBarActivity {
ImageView b2;
int count = 0;
Handler handler = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_page2);
Intent c = getIntent();
String name = c.getStringExtra("t");
Toast.makeText(getApplicationContext(), name, Toast.LENGTH_SHORT).show();
b2 = (ImageView) findViewById(R.id.redball);
AbsoluteLayout.LayoutParams absParams =
(AbsoluteLayout.LayoutParams)b2.getLayoutParams();
DisplayMetrics displaymetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
int width = displaymetrics.widthPixels;
int height = displaymetrics.heightPixels;
Random r = new Random();
absParams.x = r.nextInt(width ) ;
absParams.y = r.nextInt(height );
b2.setLayoutParams(absParams);
Animation animation = AnimationUtils.loadAnimation(page2.this, R.anim.fade);
// Animation animation1 = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.activity_move);
b2.startAnimation(animation);
// b2.startAnimation(animation1);
b2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
count = count + 1;
}
});
handler = new Handler();
final Runnable t = new Runnable() {
public void run() {
Intent d = new Intent(getApplicationContext(), Page3.class);
d.putExtra("count", count);
d.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(d);
}
};
handler.postDelayed(t, 4000);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_page2, menu);
return true;
}
Don't use AbsoluteLayout, Why not use a custom view draw it?
You can achieve this by using Imageview within FrameLayout. Just change the layoutParams of the image to change its position.
As I understand it, you want that each time the activity is opened, so f you dont want to actually view to the user that the ImageView moves, why are you using Animation? You may just dynamically add the ImageView to the activity each time, and each time assign it different Margin attributes.
LinearLayout layout = (LinearLayout) view.findViewById(R.id.linear);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
params.setMargins(0, 0, 10, 0); //substitute parameters for left, top, right, bottom
ImageView iv = new ImageView(getActivity());
iv.setLayoutParams(params);
iv.setImageResource(R.drawable.yourimage);
layout.addView(iv);
for calucation
ContainerHeight = blinkerContainer.getHeight(); // total height of screen
ContainerWidth = blinkerContainer.getWidth(); //total width
blinkerHeight = blinkView.getHeight();
blinkerWidth = blinkView.getWidth();
minTopMargin = 30;
minLeftMargin = 30;
maxTopMargin = ContainerHeight - blinkerHeight - 30;
maxLeftMargin = ContainerWidth - blinkerWidth - 30;
for positioning
LinearLayout.LayoutParams params = (android.widget.LinearLayout.LayoutParams) blinkView
.getLayoutParams();
params.leftMargin = minLeftMargin
+ new Random().nextInt(maxLeftMargin - minLeftMargin);
params.topMargin = minTopMargin
+ new Random().nextInt(maxTopMargin - minTopMargin);
and you can use AlaramManager for Scheduling
Your solution is almost correct. Unfortunately, it looks like you're restarting the activity from your timer. Instead, you should just trigger the redraw.
This question has a couple of solutions on how to create a recurring timer. The solution with runOnUiThread() should allow you to execute the randomisation and re-displaying of the ImageView.

How to rotate an ImageView, not just the image, programmatically

I need to rotate an ImageView using an animation, so that the width and height of the ImageView also change.
I have tried using ViewPropertyAnimator, using View.animate but this just rotates the image, and not the actual view itself.
I need to use this so I can work out the x and y coords of the view after it has been rotated, and also the width and height of it.
I have made a test app to just rotate a card image, and I have taken pictures with the layouts visible to show what I mean.
As you can see in the code, I've also tried to force change the width and height in a runnable after the animation has finished, but this doesn't work. Nor does using scaleX/scaleY to try and change things.
public class MyActivity extends Activity implements View.OnClickListener{
RelativeLayout temp;
ImageView card;
int rotation = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
card = (ImageView) findViewById(R.id.card);
card.setOnClickListener(this);
}
#Override
public void onClick(final View v) {
final Runnable e1 = new Runnable() {
public void run() {
Toast.makeText(MyActivity.this, "After1 w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
int w = v.getMeasuredWidth();
int h = v.getMeasuredHeight();
v.getLayoutParams().width = h;
v.getLayoutParams().height = w;
v.setLayoutParams(v.getLayoutParams());
Toast.makeText(MyActivity.this, "After2 w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
}
};
int[] cardCoords = new int[2];
v.getLocationOnScreen(cardCoords);
Toast.makeText(MyActivity.this, "x="+cardCoords[0]+" y="+cardCoords[1], Toast.LENGTH_SHORT).show();
Toast.makeText(this, "Before w="+v.getMeasuredWidth()+" h="+v.getMeasuredHeight(), Toast.LENGTH_SHORT).show();
rotation = rotation + 90;
v.animate().
setDuration(1000).
rotationBy(90);
//scaleX((float) v.getMeasuredHeight() / (float) v.getMeasuredWidth()).
//scaleY((float) v.getMeasuredHeight() / (float) v.getMeasuredWidth()).
//.withEndAction(e1);
}
}
You should be looking to rotate a view, not the image then.
Rotating a view in Android

Transform a ImageView while moving animation (keep ratio)

I'm making an animation that a View moving and transform it self to another form at the same time.
Here is animation description:
I don't know how to do it. Any solution for me?
Any advice is appreciated.
=================================================================
UPDATE
I've tried TranslateAnimation + ScaleAnimation with AnimationSet but my ImageView scaled very urgly.
Here is start image, using centerCrop:
Here is result of Translate + ScaleAnimation:
But this is result that I want (centerCrop with same src above):
How to transform + moving but keep image ratio like that ? I don't want my image ratio changed.
Thanks for help.
Here's what you can expect from this answer:
Also note that the code provided here was written for test purposes, and thus isn't optimized.
I have used Animator (available for api >= 11) to achieve the effect you have described as I don't find TranslateAnimation and ScaleAnimation 'good' enough in terms of outcome.
There are 3 things happening here:
width is changing
height is changing
'x' value for the imageview is changing
You will need to provide the final values for these 3 parameters: finalWidth, finalHeight and final X placement.
We will use valueAnimator to get animated values for the width and height on every update, and then use these values to update the LayoutParams of ImageView.
The animate button (in the gif above) calls the following method:
public void animate() {
// This is to get the screen dimensions
final Point p = new Point();
getWindowManager().getDefaultDisplay().getSize(p);
// First, define the starting values
final int startingWidth = mImageView.getWidth();
final int startingHeight = mImageView.getHeight();
final int startingXValue = mImageView.getX():
// Next, define the final values
// For this example, the final width will be half of screen-width
final int finalWidth = p.x / 2;
// Just an arbitrary final value for height. You will have to decide
// what the final height should be
final int finalHeight = p.y - ivv.getTop() - 300;
// final `X` placement of the imageview
int finalXValue = p.x / 2 - finalWidth / 2;
// ValueAnimator to generate changes in width
final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Get animated width value update
int newWidth = (int) vaW.getAnimatedValue();
// Get and update LayoutParams from imageview
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
// ValueAnimator to generate changes in height
final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Get animated height value update
int newHeight = (int) vaH.getAnimatedValue();
// Get and update LayoutParams from imageview
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
// Used to provide translate animation
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", startingXValue,
finalXValue);
// To play these 3 animators together
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
The layout used for the activity in this example is nothing special:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:background="#android:color/holo_blue_dark" >
<Button
android:id="#+id/bAnimate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="animate"
android:layout_gravity="center_horizontal" />
<ImageView
android:id="#+id/ivToAnimate"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="animate"
android:layout_gravity="right"
android:src="#drawable/index"
android:scaleType="centerCrop" />
</LinearLayout>
Edit: To reset ImageView's position, size & scale:
Declare starting and final values as class variables:
int startingWidth, startingHeight, startingXValue,
finalWidth, finalHeight, finalXValue;
// this method will only be called ONCE.
// Use appropriate values to initialize starting and final values
public void initialize() {
final Point p = new Point();
getWindowManager().getDefaultDisplay().getSize(p);
startingWidth = mImageView.getWidth();
startingHeight = mImageView.getHeight();
startingXValue = mImageView.getX():
finalWidth = p.x / 2;
finalHeight = p.y - ivv.getTop() - 300;
finalXValue = p.x / 2 - finalWidth / 2;
}
// Call this method whenever you need to animate forward
// `animate()` method // refer above for comments
public void animate() {
final ValueAnimator vaW = ValueAnimator.ofInt(startingWidth, finalWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newWidth = (int) vaW.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
final ValueAnimator vaH = ValueAnimator.ofInt(startingHeight, finalHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newHeight = (int) vaH.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", startingXValue,
finalXValue);
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
Animate back:
// `animateBack()` method // similar execution to `animate()`
// Notice how the starting and final values have been switched
public void animateBack() {
final ValueAnimator vaW = ValueAnimator.ofInt(finalWidth, startingWidth);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newWidth = (int) vaW.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.width = newWidth;
mImageView.setLayoutParams(lp);
}
});
final ValueAnimator vaH = ValueAnimator.ofInt(finalHeight, startingHeight);
vaW.addUpdateListener(new AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
int newHeight = (int) vaH.getAnimatedValue();
LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
mImageView.getLayoutParams();
lp.height = newHeight;
mImageView.setLayoutParams(lp);
}
});
ObjectAnimator oa = ObjectAnimator.ofFloat(
mImageView, "X", finalXValue, startingXValue);
AnimatorSet as = new AnimatorSet();
as.playTogether(vaW, vaH, oa);
as.setDuration(5000);
as.start();
}
first link is to create a set of animtions.
second link - Animation for Translate.
third link - Animation for Scaling.
create the translate and scaling animation add them to the Animationset
AnimationSet
TranslateAnimation
ScaleAnimation
To keep the same ratio in the ImageView, try to use these attributes:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerInside"
android:src="#drawable/your_image" />

Animate view sliding out of another view, pushing views below out of the way

I have a list of buttons. When I press a button, a View should slide in a downwards motion out of the button, like this:
Start:
Halfway:
End:
How would I go about this? The View that should slide out is bigger than the button, so first hiding the View behind the button and then sliding it downwards causes the View to be visible above the button. That should not happen.
Any ideas or examples on how to approach this?
I believe the simplest approach is to extend Animation class and override applyTransformation() to change the view's height as follows:
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.Transformation;
import android.widget.LinearLayout;
public class MyCustomAnimation extends Animation {
public final static int COLLAPSE = 1;
public final static int EXPAND = 0;
private View mView;
private int mEndHeight;
private int mType;
private LinearLayout.LayoutParams mLayoutParams;
public MyCustomAnimation(View view, int duration, int type) {
setDuration(duration);
mView = view;
mEndHeight = mView.getHeight();
mLayoutParams = ((LinearLayout.LayoutParams) view.getLayoutParams());
mType = type;
if(mType == EXPAND) {
mLayoutParams.height = 0;
} else {
mLayoutParams.height = LayoutParams.WRAP_CONTENT;
}
view.setVisibility(View.VISIBLE);
}
public int getHeight(){
return mView.getHeight();
}
public void setHeight(int height){
mEndHeight = height;
}
#Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
super.applyTransformation(interpolatedTime, t);
if (interpolatedTime < 1.0f) {
if(mType == EXPAND) {
mLayoutParams.height = (int)(mEndHeight * interpolatedTime);
} else {
mLayoutParams.height = (int) (mEndHeight * (1 - interpolatedTime));
}
mView.requestLayout();
} else {
if(mType == EXPAND) {
mLayoutParams.height = LayoutParams.WRAP_CONTENT;
mView.requestLayout();
}else{
mView.setVisibility(View.GONE);
}
}
}
}
To use it, set your onclick() as follows:
int height;
#Override
public void onClick(View v) {
if(view2.getVisibility() == View.VISIBLE){
MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.COLLAPSE);
height = a.getHeight();
view2.startAnimation(a);
}else{
MyCustomAnimation a = new MyCustomAnimation(view2, 1000, MyCustomAnimation.EXPAND);
a.setHeight(height);
view2.startAnimation(a);
}
}
Regards.
Use something like:
Animation a = new ScaleAnimation(1, 1, 0, 1, Animation.RELATIVE_TO_SELF, (float) 0.5, Animation.RELATIVE_TO_SELF, (float) 0);
a.setFillAfter(true);
view.setAnimation(a);
a.setDuration(1000);
view.startAnimation(a);
Here is simple example of hand-made animation, that provide what you want. It works in test app, but I'm not sure that there is no bugs:
public class MainActivity extends Activity implements OnClickListener {
private Timer timer;
private TimerTask animationTask;
private View view1;
private View view2;
boolean animating;
boolean increasing = true;
int initHeight = -1;
private LayoutParams params;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
timer = new Timer();
view1 = findViewById(R.id.view1);// clickable view
view1.setOnClickListener(this);
view2 = findViewById(R.id.view2);// animated view
params = view2.getLayoutParams();
}
#Override
protected void onDestroy() {
super.onDestroy();
timer.cancel();
}
#Override
public void onClick(View v) {
Toast.makeText(this, "start animating...", Toast.LENGTH_SHORT).show();
animationTask = new TimerTask() {
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
if (animationFinished()) {
animating = false;
cancel();//canceling animating task
return;
}
params.height += increasing ? 1 : -1;
view2.setLayoutParams(params);
}
});
}
private boolean animationFinished() {
int viewHeight = view2.getHeight();
if (increasing && viewHeight >= initHeight) {
return true;
}
if (!increasing && viewHeight <= 0) {
return true;
}
return false;
}
};
//if we already animating - we just change direction of animation
increasing = !increasing;
if (!animating) {
animating = true;
int height = view2.getHeight();
params.height = height;
view2.setLayoutParams(params);//change param "height" from "wrap_conent" to real height
if (initHeight < 0) {//height of view - we setup it only once
initHeight = height;
}
timer.schedule(animationTask, 0, 10);//changing repeat time here will fasten or slow down animation
}
}
}
Maybe you can set the height to 0 and gradually increase the height. But then you will have the problem that you have to be sure your text is aligned at the bottom of the view. And also to know what the maximal height of the view should be.
use a sliding list adapter so much easier than messing around with animations
https://github.com/tjerkw/Android-SlideExpandableListView
Simply pass android:animateLayoutChanges to LinearLayout that holds all the views, you will achieve your desired result.
I would do it like that. First the layout for the whole collapsible panel component: (pseudo xml)
RelativeLayout (id=panel, clip)
LinearLayout (id=content, alignParentBottom=true)
LinearLayout (id=handle, above=content)
This should ensure that the content is always below the handle.
Then when you need to collapse:
Animate the top margin of content from 0 to -content.height
Animate the height of the panel from current to current-content.height

Categories

Resources