zoukankan      html  css  js  c++  java
  • android View 关于transient

    今天来研究一下 ListView 的删除动画

    由于 ListView 卷动时会把画面上的 item 重用以显示不同数据

    这样会导致我们可能会删除到非正确的 item

    或是出现显示上的问题(该 item 显示的数据已经不同但是动画却还在它上面跑)

    要解决这个问题就要使用 View 类别在 API 16 加入的新 method


    public void setHasTransientState (boolean hasTransientState)

    当设为 true 的时候,就告诉系统这个 View 应该尽可能的被保留,直到setHasTransientState(false)被呼叫

    要注意这是可以重复设置的,也就是说每一个setHasTransientState(true)都要搭配一个setHasTransientState(false)才能回复

    //Listview 的 OnItemClickListener 的内容
    //本范例点了 item 后会淡出并删除该 item
    public void onItemClick(AdapterView
     
      parent, final View view, int position, long id) {
        final String item = (String) parent.getItemAtPosition(position);
        ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.ALPHA, 0);
        anim.setDuration(500);
        view.setHasTransientState(true); //设为 true 宣告 item 要被追踪
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                myListview.remove(item);
                adapter.notifyDataSetChanged(); //重新整理 listview
                view.setAlpha(1);
                view.setHasTransientState(false); //完成后设定回 false
            }
        });
        anim.start();
    }
    

    另一种方法是用 ViewPropertyAnimator 来解决

    public void onItemClick(AdapterView
     
      parent, final View view, int position, long id) {
        final String item = (String) parent.getItemAtPosition(position);
        view.animate()
            .setDuration(500)
            .alpha(0)
            .withEndAction(new Runnable() {
                @Override
                public void run() {
                    myListview.remove(item);
                    adapter.notifyDataSetChanged();
                    view.setAlpha(1);
                }
            }
        );
    }
    

    但以上两种方式最大的问题就是 API 16 以后才能使用(用到了 withEndAction 跟 setHasTransientState)

    (该死的 Android Fragmentation…)

    让我们看看另一个例子

    在 DevBytes: Animating ListView Deletion: Now on Gingerbread! 里

    他用了一个继承自 ArrayAdapter 的自定义 adapter

    override 掉 public boolean hasStableIds() 让它总是回传 true ,用来取代 setHasTransientState(true)

    //用来取代 setHasTransientState(true)
    @Override
    public boolean hasStableIds() {
        return true; //总是回传 true,用来取代 setHasTransientState(true)
    }
    

    而 withEndAction 的部分则用 setAnimationListener 取代

    //API 11 之前的方法
    TranslateAnimation translator = new TranslateAnimation(startX, endX, startY, endY);
    translator.setDuration(150);
    view.startAnimation(translator);
    view.getAnimation().setAnimationListener(new AnimationListenerAdapter() {
        @Override
        public void onAnimationEnd(Animation animation) {
            new Runnable() {
                @Override
                public void run() {
                    //...(略)
                }
            }
        }
    });
    

    这样可以让 Gingerbread(API 10) 或更早的 Android 版本兼容

    如果是 4.0 (API 14)之后的版本

    还是用 view.animate() 跟 ObjectAnimator 来做

    //API 小于 16 但大于等于 14 可以这样做
    view.animate().setDuration(150);
    ObjectAnimator anim = ObjectAnimator.ofFloat(view, View.TRANSLATION_X, startX, endX);
    anim.setDuration(150);
    anim.start();
    setAnimatorEndAction(anim, new Runnable() {
        @Override
        public void run() {
            //...(略)
        }
    });
  • 相关阅读:
    flex学习网站地址
    ASP.NET 开发人员应该知道的8个网站
    登入页面添加图片有重复页面出现怎么办
    一行代码是有两个??
    c# 枚举基础有[flags]和没有的的区别
    c#中[Flags] 枚举类型定义问题_百度知道
    写出一条Sql语句:取出表A中第31到第40记录(SQLServer,以自动增长的ID作为主键,注意:ID可能不是连续的。
    Margin和Padding之间的区别
    对于top.ascx里面可以不可以放置css的文件进行一个讲解
    设计模式之--适配器模式(Adapter)
  • 原文地址:https://www.cnblogs.com/xiaorenwu702/p/5672300.html
Copyright © 2011-2022 走看看