子控件实现全屏动画的某些坑

转载请附原文地址:http://www.jianshu.com/p/f9c0b00efd14

前言

因为公司UI需要撸一个动效,然后我又一个人没有人约,别人在嗨嗨嗨,嘿嘿嘿,呵呵呵的时候,我只能在家里默默撸代码。一个很简单的位移动画,因为嵌套布局,出现了一些蛋疼的坑。记录一下,以后碰就可以绕过了。
在这里感谢洋葱司机提供思路,帮我解决了这个问题

需求

效果图

需求是,这四个分享控件按照比例,分布在屏幕靠近中央的矩形范围内,每个图标左右,上下的间距都是按权重来分配,避免在大屏幕太靠中间,小屏幕又太靠边。弹窗弹出时,四个图标依次从屏幕底部飞入。

布局

根布局为LinearLayout,orientation="vertical"
每一排图标为一个水平的LinearLayout

动画

布局写完了,开始撸动画。
这里很容易想到,用TranslateAnimation,so easy

  • 第一个坑来了。(子控件被限制视图)
    因为四个控件的父布局是水平的LinearLayout(简称二级布局),当控件移动到二级布局的边缘时就没有视图了,看不见了~坑爹啊。
    于是我去求助,见多识广的洋葱老司机给了我一个思路,在window上加一个布局用来做动画,这个布局只用来做动画,动画完成后消失,布局背景设置为透明。
    先写一个动画布局,把需要做动效的控件copy一份到这个布局中
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:background="#00ffffff"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
      <!-- 这里放你的控件-->        
</RelativeLayout>
  • 又踩了个坑(布局特性)
    一开始根布局用的是线性布局,结果有两个控件被挤出去了。。。
    这是个小问题

  • 在代码中添加动画图层

View animWindow=LayoutInflater.from(mActivity).inflate(R.layout.popupwindow_anim, null);
WindowManager.LayoutParams params = new WindowManager.LayoutParams(
        WindowManager.LayoutParams.MATCH_PARENT,
        WindowManager.LayoutParams.MATCH_PARENT,
        0, 0, 
       WindowManager.LayoutParams.TYPE_TOAST, 
       WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,                  
       PixelFormat.RGBA_8888);
windowManager.addView(animWindow, params);

拿到四个子控件

LinearLayout weixinCircle = (LinearLayout) animWindow.findViewById(R.id.ll_share_wx_circle);
LinearLayout weixin = (LinearLayout) animWindow.findViewById(R.id.ll_share_wx);
LinearLayout sina = (LinearLayout) animWindow.findViewById(R.id.ll_share_sina);
LinearLayout copy = (LinearLayout) animWindow.findViewById(R.id.ll_share_url);
  • 获取子控件的坐标
    为了让动画图层中的控件位置和实际位置精确重合,需要计算一下每个控件的位置,getLocationInWindow(location);可以获取在窗口内的坐标,具体用什么方法获取看具体需求,这里我的popwindow已经对statusbar做了适配处理,所以直接获取window坐标就可以了
getLocationInWindow(location);
getLocationOnScreen(location);
getGlobalVisibleRect(rect);

不一一列举了,搜一下一堆。
这里有个坑,如果绘制还没有完成的情况下去获取坐标,会得到0,并没有什么卵用
怎么判断绘制完毕,也有很多方法,也不一一列举了,我用的 ViewTreeObserver

ViewTreeObserver viewTreeObserver = mWeixinCircle.getViewTreeObserver();
viewTreeObserver
        .addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mWeixinCircle.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                startEnterAnimation();
            }
        });

别忘了remove

  • 绘制完成后获取坐标启动动画,并监听
    动画的代码就不写,几行代码。原来的popwindow初始化后,将四个控件隐藏
    常用的监听方法,在onAnimationEnd中,将四个控件显示出来,并remove动画图层
ta.setAnimationListener(new Animation.AnimationListener() {
    @Override
    public void onAnimationStart(Animation animation) {    }
    @Override
    public void onAnimationEnd(Animation animation) {
      mWeixinCircle.setVisibility(View.VISIBLE);
      mWeixin.setVisibility(View.VISIBLE);
      mSina.setVisibility(View.VISIBLE);
      mCopy.setVisibility(View.VISIBLE);
      windowManager.removeView(animWindow);
    }
    @Override
    public void onAnimationRepeat(Animation animation) {    }
});

坑爹的又来了
测试中,这个方法在进入动画时正常,退出动画时没有被调用!
查阅官方文档,当动画被设置为无限重复时,不会被调用。

This callback is not invoked for animations with repeat count set to INFINITE.

WTF?我没有设置重复啊?
上stackoverflow找到一个相关问题,这哥们儿是这么回答的
原文链接:http://stackoverflow.com/questions/5474923/onanimationend-is-not-getting-called-onanimationstart-works-fine

AnimationEnd
is not reliable. If you don't want to rewrite your code with custom views that override OnAnimationEnd, use postDelayed.
While it MAY seem ugly, I can guarantee it's very reliable. I use it for ListViews that are inserting new rows while removing with animation to other rows. Stress testing a listener with AnimationEnd proved unreliable. Sometimes AnimationEnd
was never triggered. You might want to reapply any transformation in the postDelayed
function in case the animation didn't fully finish, but that really depends on what type of animation you're using.

坑爹啊,用postDelayed吧,起码靠谱~

handler.postDelayed(new Runnable() {
    @Override
    public void run() {
        ULog.d("isEnter=" + isEnter);
        if (isEnter) {
            mWeixinCircle.setVisibility(View.VISIBLE);
            mWeixin.setVisibility(View.VISIBLE);
            mSina.setVisibility(View.VISIBLE);
            mCopy.setVisibility(View.VISIBLE);
        } else {
            CustomShareBoard.this.dismiss();
        }
        windowManager.removeView(animWindow);
    }
}, 700);

最后祝大家节日快乐

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容