关于view的visible和gone动画的坑

title: "关于view的visible和gone动画的坑"
date: 2016-05-31 00:38:33
categories: android
tags:[android,Animator]


需求:如图所示,我需要做一个View的显示和消失的动画。看似简单,但是坑还是不少。消失的动画很简单,难点在visible的动画。因为动画是发生在visible之后,所以导致会生硬的将其他的view移到右边,然后在进行动画.

从传统动画到属性动画,各种尝试,结果失败告终。

  • 直接让整个view进行左移让checkbox移动到屏幕外,然后再需要的时候进行移动回来,结果还是很生硬,不知道为什么

跟同事讨论下,他的建议是:visible快速的一个动画左移,然后再一个动画缓慢的右移回来。实践下效果能够缓慢出来,但是view会一闪而过,体验十分不好。

按着这个思路,我们可以移动其他的view,通过遮住这个checkbox,来达到效果,那么只需要改变布局即可。

效果:
enter image description here
<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/bg_white"
    android:minHeight="@dimen/dp_90">
    <CheckBox
        android:id="@+id/cb_select"
        android:layout_width="@dimen/dp_36"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_marginLeft="@dimen/dp_12"
        android:button="@null"
        android:checked="@{data.isSelected}"
        android:drawableLeft="@drawable/selector_checkbox_red"
        android:maxHeight="@dimen/dp_90"
        android:onClick="@{data.onClick()}"
        bind:visibility="@{data.isEditMode}" />
    <LinearLayout
        bind:move="@{data.isEditMode}"
        android:layout_centerVertical="true"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="@dimen/dp_9">

        <ImageView
            android:id="@+id/iv_goods_pic"
            android:layout_width="@dimen/dp_61"
            android:layout_height="@dimen/dp_61"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:background="@drawable/shape_imageview_bg"
            android:src="@{data.img}" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dp_13"
            android:layout_marginTop="@dimen/dp_21"
            android:layout_weight="1"
            android:text="@{data.name}"
            android:textColor="@color/black_43"
            android:textSize="@dimen/font_11" />
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="right"
            android:layout_marginBottom="@dimen/dp_12"
            android:layout_marginTop="@dimen/dp_14"
            android:text="@{XmlUtil.formatPrice(data.skuPrice)}"
            android:textColor="@color/font_red_41"
            android:textSize="@dimen/font_11" />
    </LinearLayout>
</RelativeLayout>

对应的绑定代码:

@BindingAdapter("bind:visibility")
public static void showVisibility(final View view, boolean visible) {
    if (view.getTag() == null) {
        view.setTag(true);
    }
    if (visible) {
        view.animate().alpha(1);
    } else {
        view.animate().alpha(0);
    }
}
@BindingAdapter("bind:move")
public static void animMove(final ViewGroup viewGroup, boolean visible) {
    if (viewGroup.getTag() == null) {
        viewGroup.setTag(true);
    }
    if (visible) {
        viewGroup.animate().translationX(Systems.dpToPx(viewGroup.getContext(), 36));
    } else {
        viewGroup.animate().translationX(0);
    }
}


另一种实现方式思路--通过改变高度达到要求

通过改变将要显示view的高度/宽度来达到要求。即:宽度/高度 从0开始逐步变成指定的高度。因为visible的时候,高度为0所以看不到一闪而过的情况。
来源:android群英传

效果图:


下面提供关键代码:

private void animOpen(final  View view){
    view.setVisibility(View.VISIBLE);
    ValueAnimator va = createDropAnim(view,0,mHiddenViewMeasuredHeight);
    va.start();
}

private void animClose(final  View view){
    int origHeight = view.getHeight();
    ValueAnimator va = createDropAnim(view,origHeight,0);
    va.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setVisibility(View.GONE);
        }
    });
    va.start();
}

/**
 * 使用动画的方式来改变高度解决visible不一闪而过出现
 * @param view
 * @param start 初始状态值
 * @param end 结束状态值
 * @return
 */
private ValueAnimator createDropAnim(final  View view,int start,int end) {
    ValueAnimator va = ValueAnimator.ofInt(start, end);
    va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int value = (int) animation.getAnimatedValue();//根据时间因子的变化系数进行设置高度
            ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
            layoutParams.height = value;
            view.setLayoutParams(layoutParams);//设置高度
        }
    });
    return  va;
}

这种方式的缺点很明显:只能从上而下出现,为什么?

因为android的view默认的坐标系是左上角,也就意味着高度只能从上而下扩展。

当遇到从下而上出现则束手无策。开发还真的遇到这样的需求。但有之前的经验+转场动画setAlpha的思路,想到以下方式:

  • xml设置view为gone
  • 当设置为visible之前,将view设置为setAlpha(0)
  • 快速的动画(setDuration(1)),将view移动到当前显示屏幕之外并设置setAlpha(1)
  • 正常的动画,从下移动到上出现。

效果图:

实现代码:

binding.btnShow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//bottom layout的出现于消失
if(isFirst){
    binding.llLayoutBottom.setAlpha(0);
    binding.llLayoutBottom.setVisibility(View.VISIBLE);
}
Tasks.handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        if(isEdit&&isFirst){
            logger.e("bottom="+binding.llLayoutBottom.getBottom());
            binding.llLayoutBottom.animate()
            .y(binding.llLayoutBottom.getBottom())
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    if(isFirst){
                        binding.llLayoutBottom.setAlpha(1);
                        logger.e("getTop="+binding.llLayoutBottom.getTop());
                        binding.llLayoutBottom.animate().y(binding.llLayoutBottom.getTop()).setDuration(1000);
                        isFirst=false;
                    }
                }
            })
            .setDuration(1);
        }else if(isEdit){//非第一次的情况执行
            logger.e("getTop="+binding.llLayoutBottom.getTop());
            binding.llLayoutBottom.animate()
            .y(binding.llLayoutBottom.getTop()).setDuration(1000);    
        }
        else  {
            logger.e("getBottom="+binding.llLayoutBottom.getBottom()+"getHeight"+binding.llLayoutBottom.getHeight());
            binding.llLayoutBottom.animate()
            .y(binding.llLayoutBottom.getBottom()).setDuration(1000);
        }

    }
}, 500);

}
});

上述代码总结:

  1. 为了偷懒直接使用animate()方法,却忘记了一旦进行监听AnimatorListener后,只要每执行一次动画,对应的方法就会执行一次,导致在打log中onAnimationEnd一直执行,迫使之前实现的效果一直都不正确。动画总是移动回来再移动回去。
  1. 关于坐标系的问题,发现使用屏幕的高度-llLayoutBottom.getHeight()不靠谱,对应的view只出现一半。暂时不明,所以直接使用getBottom、getTop来设置。可以发现动画的移动并没有其真实的坐标:getBottom、getTop来时原来的
  2. log+debug会加快调试的时间
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容