I have linear layout like below
<LinearLayout
android:id="#+id/pilihwaktu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="125dp">
<com.testing.CustomLinearLayout
android:id="#+id/oneway"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/field_background"
android:padding="5dp"
android:layout_weight=".50">
....
</com.testing.CustomLinearLayout>
<com.testing.CustomLinearLayout
android:id="#+id/roundtrip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/field_background"
android:padding="5dp"
android:layout_weight=".50">
....
</com.testing.CustomLinearLayout>
</LinearLayout>
and it will show view like this
+---------------+---------------+
| | |
| oneway | roundtrip |
| | |
+---------------+---------------+
I want to make the roundtrip is gone as the default and when the Checkbox is checked, I want to animate roundtrip so it will restore things to the above state (and oneway section will animate as it follows so it looks smooth). And when the checkbox is not checked roundtrip will animate to hide or gone
I've tried to follow this link but it wasn't animated and it looks like ObjectAnimator is simple way to do it...
What is the correct way to do this?
Easy way:
Firstly, add to your parent LinearLayout this attribute:
<LinearLayout
android:id="#+id/pilihwaktu"
...
android:animateLayoutChanges="true"
... />
And later set checked change listener in the code like this:
yourCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,boolean isChecked) {
roundTip.setVisibility(isChecked ? View.VISIBLE : View.GONE);
}
});
More hard way:
This is for expand, it's simple to make it for collapse. Use this in the onCheckedChange, if it's checked
updateListener = new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
// Get params:
final LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) roundTip.getLayoutParams();
params.weight = (Float) animation.getAnimatedValue();
roundTip.setLayoutParams(loparams);
}
};
animatorListener = new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
roundTip.setVisibility(View.VISIBLE);
}
};
animator = ValueAnimator.ofFloat(0f, 0.5f);
animator.addUpdateListener(updateListener);
animator.addListener(animatorListener);
animator.setDuration(500);
animator.start();
Related
I have a view that looks like this:
https://i.stack.imgur.com/zKe01.png
When clicked, I want to animate the grey background color so that it slides from the right side to 50% of its initial width:
https://i.stack.imgur.com/s96BX.png
Here is the relevant portion of the layout xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content_view"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginBottom="4dp">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="1.0"/>
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="#+id/guideline"
android:background="#drawable/background" />
</androidx.constraintlayout.widget.ConstraintLayout>
I've tried the following:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(contentView);
constraintSet.setGuidelinePercent(guideline.getId(), 0.5f);
TransitionManager.beginDelayedTransition(contentView);
constraintSet.applyTo(contentView);
}
});
But instead of the background color sliding from the right to the left (100% to 50%), it sort of just cross-fades.
What am I doing wrong? How would I change my code so the animation SLIDES the background color when the guideline percent changes?
You can use android.animation.ValueAnimator to change the percentage value of your guideline inside your constraintLayout, the code would be like this:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// initialize your guideline
// Guideline guideline = findViewById ....
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.5f);
// set duration
valueAnimator.setDuration(1000);
// set interpolator and updateListener to get the animated value
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
// update guideline percent value through LayoutParams
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) guideline.getLayoutParams();
// get the float value
lp.guidePercent = (Float) animation.getAnimatedValue();
// update layout params
guideline.setLayoutParams(lp);
}
});
valueAnimator.start();
}
});
Working on this app in which I'am trying to manage show/hide animation on a LinearLayout.
The problem I have is, on toggling the visibility it seems to hide any children the second time..
To make my story more clear here a screenshot:
on start - hidden
1st click - shows linear layout with children (textview)
2th click - hids linear layout again
3th click - shows linear layout but no children (textview)
Layoutfile:
<TextView
android:id="#+id/tv_lecture"
style="#style/Text.Primary.Light"
android:singleLine="true" />
<LinearLayout
android:visibility="gone"
android:id="#+id/grades_container"
style="#style/Container.Vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="10"/>
</LinearLayout>
code:
private void animate(final LinearLayout gradesContainer) {
if (gradesContainer.getVisibility() == View.GONE) {
gradesContainer.animate()
.translationY(gradesContainer.getHeight())
.alpha(1.0f)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
gradesContainer.setVisibility(View.VISIBLE);
gradesContainer.setAlpha(0.0f);
}
});
}
else {
gradesContainer.animate()
.translationY(0)
.alpha(0.0f)
.setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
gradesContainer.setVisibility(View.GONE);
}
});
}
}
On lecture TextView click will trigger the method: animate()
So whats the problem here? Can't figure it out thats why I'am asking you guys. Thanks!
If you are aiming for just the simple animation. You can just go on ahead and use animateLayoutChanges in your xml.
Cheers! :)
I'm working on getting a animation to work. I'm moving a search bar from the middle of the screen to the top of the screen. The animation works fine, but once it's moved I can't interact with anything. I've updated the position but can't interact with it regardless. Here's what I've got so far:
private void moveSearchToTop()
{
FrameLayout root = (FrameLayout) findViewById( R.id.rootLayout );
DisplayMetrics dm = new DisplayMetrics();
this.getWindowManager().getDefaultDisplay().getMetrics( dm );
statusBarOffset = dm.heightPixels - root.getMeasuredHeight();
int originalPos[] = new int[2];
mSearchBar.getLocationOnScreen( originalPos );
search_top = statusBarOffset - originalPos[1];
TranslateAnimation anim = new TranslateAnimation( 0, 0, 0, search_top);
anim.setDuration(500);
anim.setFillAfter(true);
anim.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mSearchBar.layout(0, search_top, 0, mSearchBar.getHeight() + search_top);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
mSearchBar.startAnimation(anim);
}
and here's what the view looks like in xml:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:id="#+id/search_bar"
android:background="#android:drawable/dialog_holo_light_frame">
<ImageView
android:id="#+id/search_icon"
android:layout_width="wrap_content"
android:onClick="onSearchClick"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:src="#drawable/search"/>
<EditText
android:id="#+id/search_field"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:singleLine="true"
android:hint="Search"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="25dp"
android:layout_gravity="center_vertical"
android:src="#drawable/camera"/>
</LinearLayout>
Do I need to update the position of all of the child elements too? Thanks for a push in the right position.
No, you won't need to modify the child views. They will go where the search bar goes.
It looks to me like you are using your search_top variable both as a delta (for the TranslateAnimation constructor) and as a position within its parent (in the call to layout). It's really a delta, so the call to layout is incorrect.
Is the parent of your searchBar the "root" FrameLayout? If so, then you just want to use 0 as the new y coordinate in the call to layout. Also, you are using 0 as the right coordinate, which means that it has no width after the animation. This call would position your search bar at the upper-left edge of its parent, and maintain its current width and height:
mSearchBar.layout(0, 0, mSearchBar.getWidth(), mSearchBar.getHeight());
I also would recommend that you do not use screen position. It's safer to just set the position of views within parent views. For example, if the search bar's parent really is root, then you could get the delta with:
search_top = - mSearchBar.getTop();
I am new in Android animation and my requirement is to translate a view from one layout to layout in a single xml file on click of that view.
Scenario:
Suppose I click a button, present on the top of the header in a xml file,and it should move/translate downwards (it should give an impact that it lies on the other layout downwards to header), and also I want that when the user clicks on the same again, it should now move to its original position.
Here I am explaining with my xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/app_bg"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/top"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/header"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<Button
android:id="#+id/btnSearchHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:background="#drawable/search_icon" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/bottom"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/app_transparent"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_marginTop="10dp"
android:visibility="visible" >
<Button
android:id="#+id/btnMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:text="ABC" />
<Button
android:id="#+id/btnSearchSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/btnMenu"
android:text="CDE" />
</RelativeLayout>
</LinearLayout>
MORE PRECISE REQUIREMENT SPECIFICATION (Kindly read carefully:)
Here I have two sub inner layouts:-
Top Layout - id-> top
Bottom Layout- id -> bottom
Now a view (Button -> btnSearchHeader) is lying in my top layout and I want to animate the same to the bottom layout (it should give an impact that it is translated with a translate animation to the bottom layout) on click of that button and when the user clicks on that button, it should again translate back to its original position with a translate animation .. i.e it should show back in the top layout
I have no idea how to give these impacts using translate animations, however i just have a basic translate animation knowledge which is insufficient for me to work upon my requirement.
Any type of related help is appreciable.
Thanks
Have you tried something simple like the following?
final int topHeight = findViewById(R.id.top).getHeight();
final int bottomHeight = findViewById(R.id.bottom).getHeight();
final View button = findViewById(R.id.btnSearchHeader);
final ObjectAnimator moveDownAnim = ObjectAnimator.ofFloat(button, "translationY", 0.F, topHeight + bottomHeight / 2 - button.getHeight() / 2);
final ObjectAnimator moveUpAnim = ObjectAnimator.ofFloat(button, "translationY", topHeight + bottomHeight / 2 - button.getHeight() / 2, 0.F);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (0.F == v.getTranslationY())
moveDownAnim.start();
else
moveUpAnim.start();
}
});
If you actually need the button view to change parents, you can use AnimatorListener to achieve this at the end of each animation. Something like:
moveDownAnim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
((ViewGroup)findViewById(R.id.top)).removeView(button);
((ViewGroup)findViewById(R.id.bottom)).addView(button);
((RelativeLayout)button.getLayoutParams()).addRule(RelativeLayout.CENTER_IN_PARENT);
button.setTranslationY(0.F); // Since it is now positioned in the new layout, no need for translation.
}
#Override
public void onAnimationCancel(Animator animation) { /* NOP */ }
#Override
public void onAnimationRepeat(Animator animation) { /* NOP */ }
#Override
public void onAnimationStart(Animator animation) { /* NOP */ }
});
(And analogous listener for the moveUpAnim.)
However, I doubt you need to actually do this to achieve the visual effect you want. But if you do this part, you will probably also need to set a fixed height for your top view as opposed to wrap_content. (Otherwise, if a layout pass happens while the button has been moved to the bottom view, the top layout's height might go to 0 if there's nothing else in it.) Easiest would be to just do this directly in the xml layout file. However, if you want to "do it on the fly", you can change the layout's height in the onAnimationEnd() method using something like:
#Override
public void onAnimationEnd(Animator animation) {
final ViewGroup topLayout = findViewById(R.id.top);
topLayout.getLayoutParams().height = topLayout.getHeight(); // Keep it the same height...
topLayout.removeView(button);
((ViewGroup)findViewById(R.id.bottom)).addView(button);
((RelativeLayout)button.getLayoutParams()).addRule(RelativeLayout.CENTER_IN_PARENT);
button.setTranslationY(0.F); // Since it is now positioned in the new layout, no need for translation.
}
i have 2 views in a RelativeLayout like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<View
android:id="#+id/view1"
android:layout_width="match_parent"
android:layout_height="200dp"
android:background="#drawable/shape_red"/>
<View
android:id="#+id/view2"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_below="#id/view1"
android:background="#drawable/shape_blue"/>
</RelativeLayout>
now, i animate the y property of view1 from 0 to 300. but i want view2 to change its position according to view1 - because view2 is set to be below (layout-below) view1.
as this isn't working, i tried to add an onAnimationEnd listener to the animation. like this:
ObjectAnimator ani = ObjectAnimator.ofFloat(view1, "Y", 200);
ani.setDuration(2000);
ani.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, view2.getHeight());
params.addRule(RelativeLayout.BELOW, view1.getId());
view2.setLayoutParams(params);
}
});
but view2 didn't change its position at all.
i would like to avoid making a new animation for view2 if possible, so please don't bother to suggest one. ;)
does anyone have some suggestions?
Check this if it solves your problem:
ani.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
LayoutParams params = view2.getLayoutParams();
// change it ...
params.addRule(RelativeLayout.BELOW, view1.getId());
view2.setLayoutParams(params);
}
});