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() {
        //...(略)
    }
});
时间: 2024-10-08 00:08:04

android View 关于transient的相关文章

Android View体系(二)实现View滑动的六种方法

相关文章: Android View体系(一)视图坐标系 1.View的滑动简介 View的滑动是Android实现自定义控件的基础,同时在开发中我们也难免会遇到View的滑动的处理.其实不管是那种滑动的方式基本思想都是类似的:当触摸事件传到View时,系统记下触摸点的坐标,手指移动时系统记下移动后的触摸的坐标并算出偏移量,并通过偏移量来修改View的坐标. 实现View滑动有很多种方法,这篇文章主要讲解六种滑动的方法,分别是:layout().offsetLeftAndRight()与offs

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~ 首先我们先写个简单的例子来测试View的事件转发的流程~ 1.案例 为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~ MyButton [java] view plain copy package com.example.zhy_event03; import android.content.Context; import andr

Android View 触摸事件传递机制

PS:以现在的眼光看以前写的博客感觉写的很烂,或许或一段时间再看现在的博客会有同样的感觉.所以每时每刻都去学习,去发现和理解新的东西. 引言 由于之前写的一篇关于Android事件传递顺序的博客质量太差,可能是理解不到位的原因,故最近又花了许多时间再次去看Android源码,看完之后有了新的理解,所以打算重新整理这篇博客.理解Android触摸事件传递机制有助于日后的开发以及自定义一些手势效果等.注意:这篇博客是基于Android2.0源码来分析的,不管老版本还是新版本的Android,其内部触

java.lang.NoSuchMethodException: [class android.view.View]

05-24 11:38:35.884: E/AndroidRuntime(1819): FATAL EXCEPTION: main05-24 11:38:35.884: E/AndroidRuntime(1819): Process: com.example.activitytest, PID: 181905-24 11:38:35.884: E/AndroidRuntime(1819): java.lang.IllegalStateException: Could not find a met

Android View measure (三) 常用方法

ViewGroup.measureChildren() ViewGroup.measureChild() ViewGroup.measureChildWithMargins() /** * Ask one of the children of this view to measure itself, taking into * account both the MeasureSpec requirements for this view and its padding * and margins

(android学习笔记)Android View

Android View类: 1.所有的Android组件均是View的子类. 2.所有的组件均可以进行两种配置,一是通过方法进行配置.二是通过XML进行配置. TextView类: 1.对于文本组件而言主要的目的是静态的显示一些文字,类似于标签的功能. 2.其是android.widget.TextView类,是android.view.View类的直接子类. 3.插入超链接的方法: 1)在XML文件中的TextView组件配置中写:android:autoLink="all" 会自

Android View框架总结(八)ViewGroup事件分发机制

请尊重分享成果,转载请注明出处: http://blog.csdn.net/hejjunlin/article/details/52298780 上篇分析了View的事件分发流程,留了一个问题:如果上面的EventButton继承TextView的话,按下抬起,会有一个现象,我可以告诉大家现象:就是只有dispatchTouchEvent ACTION_DOWN,onTouch ACTION_DOWN,onTouchEvent ACTION_DOWN这三个,你移动,或者抬起,是没有MOVE,或者

android view从无到有的过程

在搜集Android view绘制流程的相关知识时,发现这里面的流程还是有些复杂的,准备了好几天,才敢提起笔来.下面就直入主题吧! view绘制流程是从ViewRoot的performTraversals()方法中开始的,在该方法中会执行view绘制的三部曲,即:measure(测量视图的大小),layout(确定视图的位置)draw(绘制视图的内容).下面这张图明确的展示了该过程: 1.measure的过程 public final void measure(int widthMeasureS

Android View的事件分发机制

准备了一阵子,一直想写一篇事件分发的文章总结一下.这个知识点实在是太重要了. 一个应用的布局是丰富的,有TextView,ImageView,Button等.这些子View的外层还有ViewGroup.如RelativeLayout.LinearLayout.作为一个开发人员,我们会思考.当点击一个button,Android系统是如何确定我点的就是button而不是TextView的?然后还正确的响应了button的点击事件. 内部经过了一系列什么过程呢? 先铺垫一些知识能更加清晰的理解事件分