自定义的ImageView从ListAdapter中消失了

3

好的,我的问题类似于这个ListView条目中背景图片突然消失

但是这个问题可以通过在普通ImageView上使用setImageResource来解决,但我想让列表的所有元素都存在动画效果,而这需要一个自定义的ImageView类来允许动画运行。有人知道为什么这些图片在滚动列表后会消失吗?也许如何修复它呢?非常感谢!

这是我的ListAdapter:

    package com.mmgworldwide.layout.listadapters;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;

import com.mmgworldwide.R;
import com.mmgworldwide.customviews.SpinLoadingAnim;
import com.mmgworldwide.data.FWREvent;
import com.mmgworldwide.data.ImageThreadLoader;
import com.mmgworldwide.data.ImageThreadLoader.ImageLoadedListener;
import com.mmgworldwide.layout.ListDivider;
import com.mmgworldwide.data.Personality;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.text.SpannableString;
import android.text.style.UnderlineSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class PersonalityListAdapter extends ArrayAdapter<Object>{

    private Context parentContext;
    public ArrayList<Object> items_list_ref;
    private ImageThreadLoader imageLoader = new ImageThreadLoader();

    public PersonalityListAdapter(Context context, int resource, int textViewResourceId, ArrayList<Object> items_list) {
        super(context, resource, textViewResourceId, items_list);
        items_list_ref = items_list;
        parentContext = context;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Object node = (Object) items_list_ref.get(position);
        LayoutInflater inflater = (LayoutInflater) parentContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        if(node instanceof ListDivider){
            //make new div bar
            View div = inflater.inflate(R.layout.list_bar, parent, false);
            TextView div_label = (TextView) div.findViewById(R.id.div_label);
            div_label.setText(((ListDivider) node).label.toUpperCase());
            return div;
        }

        View row = inflater.inflate(R.layout.picture_list, parent, false);

        TextView name_txt = (TextView) row.findViewById(R.id.name_txt);
        TextView title_txt = (TextView) row.findViewById(R.id.title_txt);
        final ImageView portrait_img = (ImageView) row.findViewById(R.id.portrait);
        final ImageView load_cnt = (ImageView) row.findViewById(R.id.portrait_loadDisplay);

        name_txt.setText(((Personality) node).getName());
        SpannableString title_underlined = new SpannableString(((Personality) node).getTitle());
        title_underlined .setSpan(new UnderlineSpan(), 0, title_underlined.length(), 0);
        title_txt.setText(title_underlined);

        load_cnt.setVisibility(View.VISIBLE);

        return row;
    }

这是我的自定义ImageView类。
package com.mmgworldwide.customviews;

import android.R;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.AnimationDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

public class SpinLoadingAnim extends ImageView{

    AnimationDrawable animation;
    private final Integer FRAME_SPEED = 20;

    public SpinLoadingAnim(Context context, AttributeSet attrs){
        super(context, attrs);

         //setBackgroundColor(Color.GREEN);


        animation = new AnimationDrawable();
        animation.addFrame(context.getResources().getDrawable(com.mmgworldwide.R.drawable.spinner_00000), FRAME_SPEED);
        animation.addFrame(context.getResources().getDrawable(com.mmgworldwide.R.drawable.spinner_00001), FRAME_SPEED);
        animation.addFrame(context.getResources().getDrawable(com.mmgworldwide.R.drawable.spinner_00002), FRAME_SPEED);
        animation.addFrame(context.getResources().getDrawable(com.mmgworldwide.R.drawable.spinner_00003), FRAME_SPEED);

        animation.setOneShot(false);

        this.setBackgroundDrawable(animation);
        this.post(new Starter());
    }

    class Starter implements Runnable {
        public void run() {
            animation.start();

        }

    }

以下是我的布局XML代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:background="#FFFFFF"
  android:gravity="center_vertical"
  android:paddingTop="10dp"
  android:paddingBottom="10dp"
  android:paddingLeft="10dp"
  android:paddingRight="10dp">
    <ImageView android:layout_width="60dp" android:layout_height="60dp" android:id="@+id/portrait" android:layout_centerVertical="true"></ImageView>


    <com.mmgworldwide.customviews.SpinLoadingAnim
        android:id="@+id/portrait_loadDisplay" 
        android:layout_width="20dp" android:layout_height="20dp"
        android:background="#939598"
        android:layout_centerVertical="true" android:layout_marginLeft="20dp"
        android:layout_alignParentBottom="true" 
        android:layout_alignParentLeft="true" />



    <ImageView android:layout_height="wrap_content" android:layout_width="wrap_content" android:layout_centerVertical="true" android:id="@+id/arrow" android:src="@drawable/list_arrow" android:layout_alignParentRight="true"></ImageView>
    <LinearLayout android:layout_toRightOf="@id/portrait" android:layout_toLeftOf="@id/arrow" android:layout_centerVertical="true" android:orientation="vertical" android:layout_height="wrap_content" android:layout_width="wrap_content" android:baselineAligned="true" android:paddingLeft="15dp" android:paddingRight="15dp">
        <TextView android:text="CHEF NAME" android:id="@+id/name_txt" android:layout_width="wrap_content" android:textColor="#000000" android:textStyle="bold" 
            android:layout_height="wrap_content" android:paddingBottom="2dp" android:textSize="15sp"></TextView>
        <TextView android:text="Chef Title" android:id="@+id/title_txt" android:layout_width="wrap_content" android:textColor="#000000" 
            android:layout_height="wrap_content" android:textSize="13sp"></TextView>
    </LinearLayout>


</RelativeLayout>

每5个 "preloader" 图形中仍然会消失一个,但感谢Michele的帮助,这有很大帮助,使事情更加清晰。

package com.mmgworldwide.layout;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.mmgworldwide.R;
import com.mmgworldwide.data.DataConnection;
import com.mmgworldwide.data.ImageThreadLoader;
import com.mmgworldwide.data.Personality;

//http://code.google.com/p/and-conference/source/browse/trunk/src/com/totsp/conference/PresentationList.java

public class Personalities extends Activity{

    private ListView listView;
    private ArrayAdapter<Object> adapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.personalities);

        listView = (ListView) findViewById(R.id.personalitylistview);
        listView.setDrawingCacheEnabled(false);


        addListAdapter();

        setFooterView("more");
    }

    private void addListAdapter(){
        ArrayList<Object> adaptList = makeAdaptList();

        adapter = new PersonalityListAdapter(this, 0, adaptList);
        listView.setAdapter(adapter);
    }

    private ArrayList<Object> makeAdaptList(){
        ArrayList<Object> adaptList = new ArrayList<Object>();
        String currentDivDate = " ";
        for(Personality aEvent : DataConnection.fwrInfo.getPersonalityList()){
            adaptList.add(aEvent);
        }

        return adaptList;
    }

    private void setFooterView(String highlight){
        Footer footer = (Footer) findViewById(R.id.footer);
        footer.setHighlight(highlight);
    }

    //***********************************************************************************************************************************************
    //ViewHolder
    //***********************************************************************************************************************************************
    static class ViewHolder {
        private TextView tView1;
        private TextView tView2;
        private ImageView iView1;
    }

    //***********************************************************************************************************************************************
    //PersonalityListAdapter
    //***********************************************************************************************************************************************
    private class PersonalityListAdapter extends ArrayAdapter<Object>{

        LayoutInflater vi = (LayoutInflater) Personalities.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        private Context parentContext;
        public ArrayList<Object> items_list_ref;
        private ImageThreadLoader imageLoader = new ImageThreadLoader();

        public PersonalityListAdapter(final Context context, final int resId, final ArrayList<Object> presentations) {
            super(context, resId, presentations);
            this.items_list_ref = presentations;
            parentContext = context;
        }

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

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

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            //Log.d("TROY", "adding view");
            View v = convertView;

            if (v == null) {
                //Log.d("TROY", "inflation");
                v = vi.inflate(R.layout.picture_list, parent, false);
                ViewHolder viewHolder = new ViewHolder();

                viewHolder.tView1 = (TextView) v.findViewById(R.id.name_txt);
                viewHolder.tView2 = (TextView) v.findViewById(R.id.title_txt);
                viewHolder.iView1 = (ImageView) v.findViewById(R.id.portrait);

                v.setTag(viewHolder);
            }

            Object p = items_list_ref.get(position);

            if (p != null) {
                //Log.d("TROY", "setting stuff");
                ViewHolder viewHolder = (ViewHolder) v.getTag();
                viewHolder.tView1.setText("hi");
            }

            return v;
        }
    }

}

这是正在发生的情况的屏幕截图(为什么第五个预加载图形不显示?): enter image description here 编辑——
好的,我添加了getCount和getItemId覆盖,但仍然存在相同的问题,我想从头开始尝试一个只有listView的项目,同样的问题,我放了一个测试项目来演示这个令人沮丧的问题。在这个测试中,我甚至没有向适配器添加任何数据,动画只对其中一些起作用,就像我的主项目一样。
非常感谢您到目前为止的耐心和帮助,Michele,您非常棒。 http://faceonfire.com/temp/ListTester.zip

你能用静态的.png图片测试一下吗?并且你能提供com.mmgworldwide.customviews.SpinLoadingAnim的xml文件吗? - Michele
静态PNG文件可以正常工作,只有在添加动画时才会出现问题。SpinLoadingAnim在“这是我的自定义ImageView类”下面(对于糟糕的标签表示抱歉)。 - troy
我注意到的是,当ViewHolder停止首次膨胀“picture_list”适配器时,那些不显示的就会出现,之后就没有再发生过任何膨胀,但是仍然不会显示动画,无论滚动多少次都不会显示,而且似乎是持久性的,例如如果第7个适配器没有显示,则在给定列表的分辨率和长度的情况下将始终不显示。不确定这是否有帮助,但必须在这里有一些线索,可以帮助我解决这个奇怪的问题。 - troy
1
hm是SpinAnimation在你的ViewHolder中缓存吗?无法找到portrait_loadDisplay,不管怎样我编辑了我的答案,请试一下。 - Michele
在http://faceonfire.com/temp/ListTester.zip上上传了一个工作示例,展示了这个问题,我仍然对这个特定的问题感到困惑。 - troy
显示剩余2条评论
1个回答

2

ListViews是高度优化的数据结构。为了遵守列表规则并使系统更加容易,您应该使用ViewHolders。

当您滚动ListView时,系统会通过缓存项目在持有器中来提高性能。 请阅读如何在Android中“平滑”加载Listview

您还可以尝试设置

yourListView.setDrawingCacheEnabled(false);

编辑:好的,那么尝试使用XML设置动画。

http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html

例如:

<!-- Animation frames are wheel0.png -- wheel5.png files inside the
 res/drawable/ folder -->
 <animation-list android:id="selected" android:oneshot="false">
    <item android:drawable="@drawable/wheel0" android:duration="50" />
    <item android:drawable="@drawable/wheel1" android:duration="50" />
    <item android:drawable="@drawable/wheel2" android:duration="50" />
    <item android:drawable="@drawable/wheel3" android:duration="50" />
    <item android:drawable="@drawable/wheel4" android:duration="50" />
    <item android:drawable="@drawable/wheel5" android:duration="50" />
 </animation-list>

编辑2:请尝试实现getCount和getItemId,你的List边界可能存在问题,也许在滚动后Android无法找到列表的位置。哦,你能否用随机数据测试它,而不是一直使用相同的项目(也许使用一些奇怪的哈希值(默认getItemId实现?)来始终表示相同的项目内容)。

@Override
public int getCount() {
    return <yourdatastructure>.getSize();
}

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

好的,我明白了,我已经实现了一个ViewHolders模板,它帮助了很多。我也添加了setDrawingCacheEnabled(false)...现在我的预加载图形消失更少了,但每5个中仍然有一些原因。我将在下面展示我的新代码。 - troy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接