Android - 当我在自定义ListView中单击其中一个动画时,为什么动画可以在许多其他列表项上运行?

时间:2015-08-01 08:53:05

标签: android listview animation

private class MyAdapter extends BaseAdapter {

    private LayoutInflater inflater;
    ArrayList<HashMap<String, Object>> data;  **// contains one Button and two TextViews**

    public MyAdapter(Context context, ArrayList<HashMap<String, Object>> data) {
        inflater = LayoutInflater.from(context);
        this.data = data;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

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

        final titlesHolder holder;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.list_title, null);
            holder = new titlesHolder();
            holder.Title = (TextView)convertView.findViewById(R.id.itemTitle);
            holder.Text = (TextView)convertView.findViewById(R.id.itemText);
            holder.bt = (Button)convertView.findViewById(R.id.button);

            convertView.setTag(holder);
        } else {
            holder = (titlesHolder)convertView.getTag();
        }
        holder.Title.setText(data.get(position).get("itemTitle").toString());
        holder.Text.setText(data.get(position).get("itemText").toString());
        holder.bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                ObjectAnimator.ofFloat(holder.Title, "RotationX", 0.0F, 360.0F).setDuration(500).start();
                holder.Title.clearAnimation();
            }
        });
        return convertView;
    }

    private class titlesHolder {
        public TextView Title;
        public TextView Text;
        public Button bt;
    }

}`

这是MyAdapter的代码。我添加了一个动画绑定按钮。 但是,例如,当我点击位置为0 的项目时,No.10,No.20 ...项目也会动画。它实在让我迷惑!

2 个答案:

答案 0 :(得分:1)

好的,我终于做到了。问题源于ListView的内存节省策略。所以我在自定义持有者中添加了一个名为anim的ObjectAnimation来保存每个convertView的动画,并且每次调用getView()来调用anim.cancel()来构建一个新视图。

private class MyAdapter extends BaseAdapter {
    private LayoutInflater inflater;
    ArrayList<HashMap<String, Object>> data;

    public MyAdapter(Context context, ArrayList<HashMap<String, Object>> data) {
        inflater = LayoutInflater.from(context);
        this.data = data;
    }

    @Override
    public int getCount() {
        return data.size();
    }

    @Override
    public Object getItem(int position) {
        return data.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

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

        final titlesHolder holder;

        if (convertView == null) {
            convertView = inflater.inflate(R.layout.list_title, null);
            holder = new titlesHolder();
            holder.Title = (TextView)convertView.findViewById(R.id.itemTitle);
            holder.Text = (TextView)convertView.findViewById(R.id.itemText);
            holder.bt = (Button)convertView.findViewById(R.id.button);
            convertView.setTag(holder);
        } else {
            holder = (titlesHolder)convertView.getTag();
        }
        if (holder.anim != null)
            holder.anim.cancel();
        holder.Title.setText(data.get(position).get("itemTitle").toString());
        holder.Title.setRotationX(0.0f);
        holder.Text.setText(data.get(position).get("itemText").toString());
        holder.bt.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //data.remove(position);
                //v.setVisibility(View.INVISIBLE);
                final ObjectAnimator anim;
                anim = ObjectAnimator.ofFloat(holder.Title, "RotationX", 0.0F, 360.0F).setDuration(500);
                holder.anim = anim;
                anim.start();
            }
        });
        return convertView;
    }

    private class titlesHolder {
        public TextView Title;
        public TextView Text;
        public Button bt;
        public ObjectAnimator anim;
    }

}

答案 1 :(得分:0)

问题很可能是由于ListView的内存节省策略导致的,其中新行在用户滚动时被创建和销毁,而不是立即使所有行都可用。这使ListView非常有效,但意味着&#34;奇怪&#34;在滚动时,行通常会重复其状态,这听起来就像您在此处遇到的行为。

我建议的解决方案是添加一个存储行状态的额外变量,然后根据行是否应处于动画结束或动画就绪状态,在getView()中绘制其视图。

例如:

private class MyAdapter extends BaseAdapter {

    private LayoutInflater inflater;
    ArrayList<HashMap<String, Object>> data;  **// contains one Button and two TextViews**
    ArrayList<Boolean> checkedState;

    public MyAdapter(Context context, ArrayList<HashMap<String, Object>> data) {
        inflater = LayoutInflater.from(context);
        this.data = data;
        checkedState = new ArrayList<>(data.size());
        Collections.fill(checkedState, Boolean.FALSE);
}

在动画结束时,将checkedState(position)设置为true(如果动画朝相反方向再次设置false)。

然后,在getView()中,根据行的位置及其位置与checkedState数组的关联来绘制行。