I have an issue on Android and can't understand why. I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/Container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background_primary">
<RelativeLayout
android:id="#+id/RecyclerViewContainer"
android:layout_below="#+id/UpdatesBanner"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/RecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none"
android:clipToPadding="false"
android:splitMotionEvents="false"
android:requiresFadingEdge="none"
android:overScrollMode="never" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/holo_red_dark" />
</RelativeLayout>
<Droid.UIElements.UIBanner
android:id="#+id/UpdatesBanner"
android:layout_width="match_parent"
android:layout_height="130dp"
android:layout_alignParentTop="true"
android:background="#android:color/holo_green_dark" />
</RelativeLayout>
</android.support.design.widget.CoordinatorLayout>
UIBanner is a custom view that content 2 buttons. One of them is binded on a Hide function which will animate the view.
public void Hide()
{
ObjectAnimator animation = ObjectAnimator.OfFloat(this, "TranslationY", TranslationY, TranslationY - Height);
animation.Start();
}
This works but the view under the banner keep the same size and does not expand. If i only make a visibility gone on the banner then it works but no animation performed.
Following the states before and after animation:
Found a solution, don't know if it is the best way to achieve this bu well i have to animate the second view too. Following the code:
ObjectAnimator bannerAnimation = ObjectAnimator.OfFloat(banner, "TranslationY", banner.TranslationY, banner.TranslationY - banner.Height);
ObjectAnimator viewAnimation = ObjectAnimator.OfFloat(recycler, "ScaleY", recycler.ScaleY, recycler.ScaleY - banner.Height);
AnimatorSet set = new AnimatorSet();
set.PlayTogether(bannerAnimation, viewAnimation);
set.Start();
Best solution is ValueAinmator
ValueAnimator viewAnim = ValueAnimator.OfInt(view.MeasuredHeight, viewHeight);
viewAnim.AddUpdateListener(new UpdateListener(view));
AnimatorSet set = new AnimatorSet();
set.AnimationEnd += (sender, e) => EndAnim();
set.Play(viewAnim);
set.Start();
And the listener
class UpdateListener : Java.Lang.Object, IAnimatorUpdateListener
{
Android.Views.View view;
public UpdateListener(Android.Views.View pView)
{
view = pView;
}
public void OnAnimationUpdate(ValueAnimator animation)
{
int value = (int)animation.AnimatedValue;
ViewGroup.LayoutParams layoutParams = view.LayoutParameters;
layoutParams.Height = value;
view.LayoutParameters = layoutParams;
}
}
Related
I have an odd error/side effect happening with my Android app I am doing right now for a school project.
The end goal is supposed to be a view that gets revealed after pressing a button at the top of the screen. It is initially placed invisibly and toggled after that.
However, for some reason the root view it gets attached to is also having its visibility toggled, which so happens to be the main layout of the fragment it is in. So effectively, the initial setVisibility() call is causing my entire fragment to disappear.
Any reason why?
EDIT: Giving the layout a FrameLayout to be attached to fixes the problem. However, the question still remains: what is causing this behaviour?
Code:
#Override
public void onStart() {
super.onStart();
//prep timeselector view for transitions
dashboardContainer = this.getView().findViewById(R.id.dashboardContainer);
vgTimeSelector = getLayoutInflater().inflate(R.layout.viewgroup_timeselector,dashboardContainer);
vgTimeSelector.setVisibility(View.INVISIBLE);
//add timeselector popup
bellButton = this.getView().findViewById(R.id.notificationButton);
bellButton.setOnClickListener(togglerListener);
}
private void toggleTimeSwitcherView () {
//this is all animation stuff for timeselector
int x = vgTimeSelector.getRight();
int y = vgTimeSelector.getTop();
int endRadius = (int) Math.hypot(vgTimeSelector.getWidth(),vgTimeSelector.getHeight());
if (vgTimeSelector.getVisibility() == View.INVISIBLE) {
vgTimeSelector.setVisibility(View.VISIBLE);
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, 0, endRadius);
animator.start();
}
else {
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, endRadius, 0);
animator.start();
vgTimeSelector.setVisibility(View.INVISIBLE);
}
}
XML:
Fragment Layout:
<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=".DashboardFragment"
android:id="#+id/dashboardContainer">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/notificationButton"
android:layout_alignParentRight="true"
android:layout_margin="16dp"
android:text="Bell"/>
...
</RelativeLayout>
Child View:
<?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="wrap_content"
android:padding="16dp"
android:background="#color/darkGrey"
android:id="#+id/timeselector"
android:animateLayoutChanges="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:text="Notify me later"
android:id="#+id/notifyTV"
android:textSize="24sp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center"
android:layout_below="#id/notifyTV">
<TimePicker
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:timePickerMode="spinner" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="N"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Y"/>
</LinearLayout>
</RelativeLayout>
You are toggling the visibility of the entire dashboardContainer.
I believe this dashboardContainer.setVisibility(View.VISIBLE);
should be replaced with vgTimeSelector.setVisibility(View.VISIBLE) and
dashboardContainer.setVisibility(View.INVISIBLE); with vgTimeSelector.setVisibility(View.INVISIBLE)
//this is all animation stuff for timeselector
int x = vgTimeSelector.getRight();
int y = vgTimeSelector.getTop();
int endRadius = (int) Math.hypot(vgTimeSelector.getWidth(),vgTimeSelector.getHeight());
if (vgTimeSelector.getVisibility() == View.INVISIBLE) {
dashboardContainer.setVisibility(View.VISIBLE);
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, 0, endRadius);
animator.start();
}
else {
Animator animator = ViewAnimationUtils.createCircularReveal(vgTimeSelector, x, y, endRadius, 0);
animator.start();
dashboardContainer.setVisibility(View.INVISIBLE);
}
Is there any way to hide a view without flickering its above view?
I am trying to hide a View below MapView. Once I set its visibility to GONE, MapView flickers. As I have to add more markers dynamically, couldn't able to keep MapView and bottomView in FrameLayout, since the bottomView will hide those markers in small size screens.
Layout:
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true">
<com.myapp.widgets.MapPlacePicker
android:id="#+id/lay_fr_map_inc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="#+id/options_layout" />
<LinearLayout
android:id="#+id/options_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:animateLayoutChanges="true"
android:background="#FFFFFF"
android:orientation="vertical"
android:visibility="visible">
<com.myapp.widgets.FontTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="10dp"
android:text="Please select a location!!"
android:textAppearance="#android:style/TextAppearance.Small" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.aigestudio.wheelpicker.WheelPicker
android:id="#+id/main_option_view"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:layout_weight="0.5"
app:wheel_atmospheric="true"
app:wheel_curved="false"
app:wheel_item_space="15dp"
app:wheel_item_text_color="#ffafafaf"
app:wheel_item_text_size="12dp"
app:wheel_selected_item_text_color="#color/colorPrimary"
app:wheel_visible_item_count="3" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
Output:
I have also tried TranslationAnimation, but no luck. Its showing more gray space than before.
int fromY = (visibility == View.GONE) ? 0 : optionLayout.getHeight();
int toY = (visibility == View.GONE) ? optionLayout.getHeight() : 0;
if (visibility == View.VISIBLE) {
optionLayout.setVisibility(visibility);
}
TranslateAnimation animate = new TranslateAnimation(
0, // fromXDelta
0, // toXDelta
fromY, // fromYDelta
toY); // toYDelta
animate.setDuration(1000);
animate.setInterpolator(new AccelerateDecelerateInterpolator());
//animate.setFillAfter(false);
animate.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
if (visibility == View.GONE)
optionLayout.setVisibility(visibility);
optionLayout.clearAnimation();
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
optionLayout.startAnimation(animate);
I don't see any flickering in that animation; if you want to avoid the vertical resizing behavior of lay_fr_map_inc then you can just remove this attribute:
android:layout_above="#+id/options_layout"
...and maybe make the height match_parent. Then, lay_fr_map_inc will stay full height, but the bottom portion will be hidden by options_layout when it appears (instead of scooting upwards).
Don't forget to change the map padding when you do this, so you don't obscure the Google logo (which is a violation of the rules): setPadding()
I have a LinearLayout that contains some views...
<?xml version="1.0" encoding="utf-8"?>
<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="match_parent"
android:animateLayoutChanges="true"
android:id="#+id/carSelectLayout"
android:orientation="vertical"
android:weightSum="100"
android:background="#C9C9C9">
<LinearLayout
android:id="#+id/LogoFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"
android:orientation="vertical" />
<LinearLayout
android:id="#+id/CarCategoryFragment"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="50"
android:orientation="vertical"/>
</LinearLayout>
Is there any way to change a view weight with animation? Somthing like LayoutChanges Animation...
Edited:
LayoutChanges Animation only works for add, remove or change visibilty of a view!!!
You can use ValueAnimator and then add update listener where you change your layout parameters programaticly.
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int value = (Integer) valueAnimator.getAnimatedValue();
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, 100);
lp.weight = value;
animatedView.setLayoutParams(lp);
}
});
mAnimator.start();
You may want to check how to customize layout changes animation by taking a look at http://developer.android.com/reference/android/animation/LayoutTransition.html and the method http://developer.android.com/reference/android/animation/LayoutTransition.html#setAnimator(int, android.animation.Animator)
I have a layout(parent view) and a textview(child view) inside this layout. Applying scale animation on parent view but when scale animation is applied to parent view its child view also scales.Is there any way to stop child from animation ? Including the code
Layout File
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.tfg.social.MainActivity$PlaceholderFragment" >
<FrameLayout
android:id="#+id/top_layout"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_gravity="center"
android:background="#ffff00"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:layout_gravity="center"
android:text="Top Layout"
android:background="#000000"
android:adjustViewBounds="true"
android:textAppearance="?android:attr/textAppearanceMedium" />
</FrameLayout>
Animation method
protected void expandLayout(View view) {
ObjectAnimator scaleUpY = ObjectAnimator.ofFloat(view, "scaleY", 5f);
scaleUpY.setDuration(1000);
AnimatorSet scaleAnimation = new AnimatorSet();
scaleAnimation.play(scaleUpY);
scaleAnimation.start();
}
Try this out -
ValueAnimator valueAnimator = ObjectAnimator.ofInt(start, end);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int val = (Integer) valueAnimator.getAnimatedValue();
LayoutParams layoutParams = (LayoutParams) getLayoutParams();
layoutParams.height = val;
setLayoutParams(layoutParams);
}
});
valueAnimator.setDuration(300);
valueAnimator.start();
I am using pinch zoom to just horizontaly zoom my custom view. It works fine, but the outside scroll view is not resizing with its content, and there are ugly blank space arround the view.
My Layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<AbsoluteLayout
android:id="#+id/wrapper"
android:layout_width="wrap_content"
android:layout_height="0px"
android:layout_weight="1">
<HorizontalScrollView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:fillViewport="true"
android:id="#+id/scrollview">
<Auda.WaveFormView
android:id="#+id/waveform"
android:layout_height="fill_parent"
android:layout_width="2000dp"
android:layout_weight="1" />
</HorizontalScrollView>
</AbsoluteLayout>
<LinearLayout
style="#style/ToolbarBackground"
android:layout_width="fill_parent"
android:layout_height="62dip"
android:gravity="center">
<ImageButton
android:id="#+id/play"
android:layout_width="71dip"
android:layout_height="52dip"
android:layout_marginTop="6dip"
android:layout_marginBottom="6dip"
style="#android:style/MediaButton"
android:src="#android:drawable/ic_media_play" />
</LinearLayout>
My zooming code
ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1, 1, 0, 0);
scaleAnimation.Duration = 0;
scaleAnimation.FillAfter = true;
this.view.StartAnimation (scaleAnimation);
Although your view is now (for example) drawn on half of the screen, it is really still occupying the full screen. You can verify this by adding a ClickListener to the view and trying to press the blank area you marked.
To solve this, you can add an AnimationListener to your ScaleAnimation. In the onAnimationEnd, simply update the LayoutParams of your Auda.WaveFormView. For example:
ScaleAnimation scaleAnimation = new ScaleAnimation(1f / prevScale, 1f / mScale, 1, 1, 0, 0);
scaleAnimation.Duration = 0;
scaleAnimation.FillAfter = true;
this.view.StartAnimation (scaleAnimation);
//after your are done with your animation
//set the animation listener
scaleAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationEnd(Animation animation) {
//this might not be the right logic
//especially that you are using scales relative to prevScale
this.view.getLayoutParams().width = v.getWidth() / mScale;
}
#Override
public void onAnimationStart(Animation animation) {}
#Override
public void onAnimationRepeat(Animation animation) {}
});
Try to change the layout width to fill_parent instead of wrap content