【问题标题】:View Recycling in ListView with AnimationDrawable使用 AnimationDrawable 在 ListView 中查看回收
【发布时间】:2015-12-29 12:34:11
【问题描述】:

所以我有一个带有自定义适配器的 ListView,它允许我在项目点击时“选择”一个项目。 现在列表的每一行都有一个图像视图,它的可绘制我在选择各个项目时更改为“选定”图像。在我的 Lollipop 设备上运行良好。

我在列表适配器的构造函数中构造了Drawables

public DoubleRowSelectableArrayAdapter(Context context, int resource2, List<Recording> recordings) {
    super(context, resource2, recordings);

    idle = ContextCompat.getDrawable(context,R.drawable.idleicon);
    animation = (AnimationDrawable) ContextCompat.getDrawable(context, R.drawable.animation);
}

现在,如您所见,“选定”项目是一个 AnimationDrawable,只要选择一个视图就会播放(顺便说一句,它是单选模式)。

视图在 getView 方法中更新

@Override
public View getView(int position, View convertView, ViewGroup parent) {

    if (convertView == null) {
        LayoutInflater layoutInflater = LayoutInflater.from(getContext());
        convertView = layoutInflater.inflate(resource, null);
    }

    if (position == selection) {
        Log.d("getView", "selection = position");
        convertView.setSelected(true);
        convertView.setPressed(true);

        //get the imageview from the current row
        final ImageView pic = ((ImageView) convertView.findViewById(R.id.iconview));
        pic.setImageDrawable(animation);
    }
    else{
        Log.d("getView","else");
        convertView.setSelected(false);
        convertView.setPressed(false);

        //set idle icon
        ((ImageView) convertView.findViewById(R.id.iconview)).setImageDrawable(idle);
    }

我会假设 AnimationDrawable 对所有列表项都具有“全局”状态。因此,在构造函数中启动一次动画应该让动画一直播放,对于每个列表项。

我设法让每个项目都播放动画,例如通过在构造函数中或在 getView 方法中调用 post() 来启动它。但是,我省略了那部分代码,因为我想专注于稍微不同的事情。

问题出在: 当我在播放动画时选择不同的列表项(oneshot = false),如果新选择的项目的动画低于旧项目的位置,则将播放,但如果它高于列表中的旧项目位置,则不会播放。 所以,我选择了第一项。动画播放。选择第二项,动画播放。选中第三项,播放动画....选中第 10 项,播放动画。在另一个方向,这是行不通的。如果我播放第 10 个项目的动画并选择位置 1-9 的项目之一,则根本不会播放动画。在播放新动画之前,我必须等待正在运行的动画结束。

如果每次调用 getView 时我都从资源中获取 Drawable,这种行为就会发生变化——那么它工作得非常好。所以在getView

AnimationDrawable d = (AnimationDrawable) getContext().getResources().getDrawable(R.drawable.animation);
pic.setImageDrawable(d);
d.start(); //or by post() call, etc. -- however working.

我的猜测是这与列表中的视图回收有关。我应该怎么做才能在每次 getView 调用中保存(昂贵的?)可绘制资源的实例化?

问题:为什么会这样?如何正确设置动画?为每个新动画开始(可能不是)从资源中获取可绘制动画是否聪明?怎么做才对?

【问题讨论】:

    标签: android android-listview imageview android-animation animationdrawable


    【解决方案1】:

    这是为什么呢? 每当播放动画时,都会在幕后生成一个线程并将值应用于目标对象。该线程是同步的,因此一次只能有一个进程进入。因此,您必须为每个视图创建单独的动画对象。

    如何正确设置动画?我应该怎么做才能在每次 getView 调用中从资源中保存可绘制对象的(昂贵的?)实例化?为每个新动画开始(可能不是)从资源中获取可绘制动画是否聪明?怎么做才对? 你做得对,你必须在每个 getview() 调用中创建 animationDrawable 。如果您想摆脱为视图创建多次drawable(昂贵的任务),请将animationDrawable设置为标签并在每次getView调用时检索它,如果它为null则重新初始化。

    如果不告诉我,希望你能得到答案。

    【讨论】:

    • 谢谢。但是,为什么动画会播放当前选中项下方选中的列表项?
    • 因为每次与listView交互。调用其适配器的notifyDataSetChanged() 方法以确保根据新数据集绘制所有内容。这意味着为适配器中的每个数据集值调用 getView 方法,这些值在设备屏幕上可见,并且您已对适配器进行编码以动画选定项目。因此,每次 listView 刷新其项目时,所有可见视图都会重新绘制。这就是当您在 listView 中选择另一个项目时所选项目动画的原因。
    猜你喜欢
    • 2015-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-26
    • 1970-01-01
    • 2015-04-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多