首页 > 解决方案 > 使用自定义适配器更新过滤后的列表视图

问题描述

我正在创建一个音乐播放器。除其他外,该课程假定将新歌曲添加到播放列表中。将弹出一个新窗口,其中包含可用歌曲,并添加选中的歌曲。可以过滤歌曲,并且选中复选框时所选行将更改颜色。过滤有效,所有内容都按照预期的方式添加,但是......

问题是当我检查一首歌曲/一些歌曲然后点击搜索过滤器并且软键盘弹出所选行的颜色更改为默认颜色时,(歌曲仍然被检查并且可以添加到播放列表)。当检查歌曲并隐藏键盘时,也会发生同样的事情。

另一个问题是,当列表被过滤时,先前选择的行的颜色也会消失,当搜索框被清除时,歌曲仍然处于选中状态。

而且我不明白这种情况是如何发生的以及为什么会发生,因此如何解决这个问题。请问有人有什么想法吗?

我想我不明白过滤后的更新是如何工作的,以及 notifyDataSetChanged() 究竟做了什么。

这是适配器代码:

public class MyTrackAdapter extends ArrayAdapter<File> 
{
    private final Activity context;   
    private ArrayList<File> album, temp;   
    private ArrayList<File> piosenki;

    public MyTrackAdapter(Activity context, ArrayList<File> album) 
    {   
        super(context, R.layout.adapter_traki, album);   

        this.context = context;   
        this.temp = new ArrayList<File>(album);
        this.album = album;   
        this.piosenki=new ArrayList<File>();        
    } 

    public View getView(int position, View view, ViewGroup parent) 
    {   
        LayoutInflater inflater = context.getLayoutInflater();   
        final View rowView = inflater.inflate(R.layout.adapter_traki, null,true);   
        final CheckBox cb_plus = (CheckBox) rowView.findViewById(R.id.add);
        final int position1=position;

        final TextView txt = (TextView) rowView.findViewById(R.id.list_text);   

        if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
        else rowView.setBackgroundResource(R.color.bpcolor);

        txt.setText(album.get(position1).getName().toString().replace(".mp3",""));   

        cb_plus.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener()
        {
            @Override 
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
            {
                if (cb_plus.isChecked())
                {
                    cb_plus.setBackgroundResource(R.drawable.x2);       
                    txt.setTextColor(context.getResources().getColor(R.color.bdcolor));

                    rowView.setBackgroundResource(R.color.acolor);
                    piosenki.add(album.get(position1));
                }
                else 
                {
                    cb_plus.setBackgroundResource(R.drawable.plus);
                    txt.setTextColor(context.getResources().getColor(R.color.gcolor));

                    if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
                    else rowView.setBackgroundResource(R.color.bpcolor);
                    piosenki.remove(album.get(position1));
                }
            }
        }); 

        return rowView;        
    } 

    public void showTost(String s)
    {
        Toast.makeText(context, s, Toast.LENGTH_SHORT).show();
    }

    public ArrayList<File> getpiosenki()
    {   
        return piosenki;
    }

    public Filter getFilter()
    {           
        return filtr;
    }

    private Filter filtr = new Filter()
    {   
        protected FilterResults performFiltering(CharSequence s)
        {   
            FilterResults r = new FilterResults();
            ArrayList<File> f = new ArrayList<File>();

            if(s==null || s.length()==0) f.addAll(temp);                            
            else
            {   
                String ss=s.toString().toLowerCase().trim();

                for(File ff : temp) if(ff.getName().replace(".mp3", "").toLowerCase().contains(ss)) f.add(ff);                                  
            }

            r.values=f;
            r.count=f.size();

            return r;           
        } 

        protected void publishResults(CharSequence s, FilterResults r)
        {   
            album.clear();
            album.addAll((ArrayList)r.values);
            notifyDataSetChanged(); 

        } 
    };
}   

和播放列表类:

public class Playlist extends Activity implements TextWatcher
{
    int where;
    long pos;
    String pllist;
    ArrayList<String> lstp, lsts;
    ArrayList<Long> lsti;
    ArrayList<Integer> lstx;
    DBHandler db;

    private TextView txt1, txt2;
    ImageView pic;
    private ListView lv_traki;

    ListView lv_traki2add;
    PopupWindow pw;
    View popupv;
    TextView etext;
    MyTrackAdapter tadapter;
    ImageView add2list;
    ArrayList <File> piosenki, toadd;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.playlist);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        db = new DBHandler(getApplicationContext());    

        Intent tnt = getIntent();
        Bundle bn = tnt.getExtras();

        lstp = (ArrayList) bn.getParcelableArrayList("path");
        lsts = (ArrayList) bn.getParcelableArrayList("song"); 
        lsti = (ArrayList) bn.getParcelableArrayList("indx");
        lstx = (ArrayList) bn.getParcelableArrayList("pause"); 
        pos = bn.getLong("pos", 0);
        where = bn.getInt("skad", 0);
        pllist = bn.getString("album");

        piosenki = (ArrayList) bn.getParcelableArrayList("full"); 

        setData(0, lstp.size());    

        songlist(); 

        lv_traki.setOnItemClickListener(new AdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View v, int i, long l)
            {

                Intent it;          
                lstp.clear();
                                lsti.clear();
                                lsts.clear();
                                lstx.clear();

                db.gett1path(pos, lstp);
                db.gett1song(pos, lsts);
                db.gett1pause(pos, lstx);
                db.gett1id(pos, lsti); 

                it=new Intent(getApplicationContext(), Player.class);       
                it.putExtra("path", lstp).putExtra("nazwa", lsts).putExtra("pause", lstx).putExtra("pos",i).putExtra("skad",4);
                startActivity(it);

            }                       
        });

        if(where==5) lv_traki.performItemClick(lv_traki.getAdapter().getView(0, null, null), 0, lv_traki.getAdapter().getItemId(0));

        add2list = (ImageView) findViewById(R.id.btn_addtoplay);
        toadd = new ArrayList<File>();

        add2list.setOnClickListener(new View.OnClickListener() 
        {
            public void onClick(View view) 
            {           
                popupv = ((LayoutInflater) getApplicationContext().getSystemService("layout_inflater")).inflate(R.layout.popup_addtolist, null);
                ImageView btn01 = (ImageView) popupv.findViewById(R.id.btn_addtoplay);
                FrameLayout fl = (FrameLayout) findViewById(R.id.frameLayout1);
                etext = (EditText) popupv.findViewById(R.id.etext);
                etext.addTextChangedListener(Playlist.this); 

                lv_traki2add = (ListView) popupv.findViewById(R.id.lst_traki2add);
                tadapter = new MyTrackAdapter(Playlist.this, piosenki);
                lv_traki2add.setAdapter(tadapter);

                toadd=tadapter.getpiosenki();

                btn01.setOnClickListener(new View.OnClickListener() 
                {
                    public void onClick(View view) 
                    {
                        if(toadd.size()>0)  
                    {   
                        for (File addt1 : toadd) 
                            {
                                db.addt1(pos, addt1);                               
                            }

                            lstp.clear();
                            lsts.clear();
                            lstx.clear();
                            lsti.clear();

                            db.gett1path(pos, lstp);
                            db.gett1song(pos, lsts);
                            db.gett1pause(pos, lstx);
                            db.gett1id(pos, lsti);
                            lv_traki.setAdapter(null);

                            setData(0, lstp.size());    

                            MyPlaylistAdapter adapter=new MyPlaylistAdapter(Playlist.this, lsts, lstp, lsti, lstx, pos, pllist, lv_traki, txt2);   
                            lv_traki.setAdapter(adapter);   

                            for(int x=0; x<lv_traki2add.getChildCount(); x++)
                            {                           
                                CheckBox cb = lv_traki2add.getChildAt(x).findViewById(R.id.add);                                                
                                cb.setChecked(false);                                    
                            }

                        pw.dismiss();
                        showTost("Songs Added");
                    }               
                    else pw.dismiss();                                                                                     
                    }
                });

                pw = new PopupWindow(popupv, -1, -1, true);
                pw.showAtLocation(fl, 17, 0, 0);
            }
        });

    } 

    private void songlist()
    {
        lv_traki = (ListView) findViewById(R.id.lst_traki);

        MyPlaylistAdapter adapter=new MyPlaylistAdapter(this, lsts, lstp, lsti, lstx, pos, pllist, lv_traki, txt2);   
        lv_traki.setAdapter(adapter);   
    }

    public void setData(int z, int size)
    {
        MediaMetadataRetriever mmr = new MediaMetadataRetriever(); 
        MediaMetadataRetriever tmp = new MediaMetadataRetriever(); 
        mmr.setDataSource(lstp.get(z));

        txt1 = (TextView) findViewById(R.id.txt1);
        txt2 = (TextView) findViewById(R.id.txt2);
        pic = (ImageView) findViewById(R.id.img_bg);

        int tmax = 0;
        for(int i=0;i<size;i++) 
        {
            tmp.setDataSource(lstp.get(i));
            tmax+=Integer.parseInt(tmp.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)); 
            tmax+=lstx.get(i)*1000;
        }

            txt1.setText(pllist);

            if (size>1) txt2.setText(size+" songs;   "+mili_t(tmax)); 
            else txt2.setText("1 song;   "+mili_t(tmax)); 

        Bitmap bm; 
        Drawable d;

        byte [] img = mmr.getEmbeddedPicture();

        if(img!=null)
        {
            bm = BitmapFactory.decodeByteArray(img, 0, img.length); 
            d = new BitmapDrawable(getResources(), bm); 
            pic.setBackground(d);
        }
        else
        {
            pic.setBackgroundResource(R.drawable.no_image);
            pic.getLayoutParams().height = 400;
            pic.getLayoutParams().width = 400;

            pic.setScaleType(ScaleType.CENTER_INSIDE);   
        }
    }


    public String mili_t(int t)
    {
        int s = (int) (t / 1000) % 60 ;
        int m = (int) ((t / (1000*60)) % 60);
        int h = (int) ((t / (1000*60*60)) % 24);
        String dt="", dh, ds, dm;

        if(h>0)
        {
            dh=Integer.toString(h);
            if(h<10) dh="0"+dh;
            dt=dt+dh+":";
        }
        if(m>=0)
        {
            dm=Integer.toString(m);
            if(m<10) dm="0"+dm;
            dt=dt+dm+":";
        }
        if(s>=0)
        {
            ds=Integer.toString(s);
            if(s<10) ds="0"+ds;
            dt=dt+ds;
        }

        return dt;
    }

    public void showTost(String s) 
    { 
        Toast.makeText(getApplicationContext(), s, Toast.LENGTH_SHORT).show(); 
    } 

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) 
        {
            tadapter.getFilter().filter(s);                               
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {}

        @Override
        public void afterTextChanged(Editable s) {}

}

和 xml :

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/popupwrap"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@color/bdcolor">

<RelativeLayout
    android:id="@+id/popup"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/bdcolor">

    <EditText
        android:id="@+id/etext"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColorHint="@color/bbcolor"
        android:hint="SEARCH FILTER"
        android:background="@drawable/etext"
        android:textSize="24sp"
        android:textCursorDrawable="@drawable/cursor"
        android:textColor="@color/gcolor"
        android:inputType="text"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="80dp"
        android:layout_marginTop="10dp" 
        android:layout_marginBottom="10dp"  
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"/>

        <ImageView
            android:id="@+id/btn_addtoplay"
            android:layout_width="40dp"
            android:layout_height="40dp"
        android:layout_marginBottom="10dp"
            android:layout_marginRight="10dp"
            android:src="@drawable/check1"
            android:clickable="true"
            android:layout_alignParentRight="true" 
            android:layout_marginTop="10dp" 
            android:layout_centerVertical="true"/>

</RelativeLayout>   

    <ListView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"    
        android:id="@+id/lst_traki2add">
    </ListView>


</LinearLayout>

标签: androidlistviewfilter

解决方案


原因很简单 - 您OnCheckedChangeListener在每次(取消)检查后都会触发并且正在改变背景。每次调用notifyDataSetChanged()整个列表都会重新绘制,因此背景颜色将if(position1 %2 == 1)在方法中再次设置条件getView,但侦听器不会再次触发。通过手动监听器调用查看他的代码

CompoundButton.OnCheckedChangeListener listener = new CompoundButton.OnCheckedChangeListener()
    {
        @Override 
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked)
        {
            if (cb_plus.isChecked())
            {
                cb_plus.setBackgroundResource(R.drawable.x2);       
                txt.setTextColor(context.getResources().getColor(R.color.bdcolor));

                rowView.setBackgroundResource(R.color.acolor);

                if(piosenki.get(album.get(position1)) != null) // won't duplicate
                    piosenki.add(album.get(position1));
            }
            else 
            {
                cb_plus.setBackgroundResource(R.drawable.plus);
                txt.setTextColor(context.getResources().getColor(R.color.gcolor));

                if(position1 %2 == 1) rowView.setBackgroundResource(R.color.bbcolor);
                else rowView.setBackgroundResource(R.color.bpcolor);

                piosenki.remove(album.get(position1));
            }
        }
    }
boolean isAdded = ...;
cb_plus.setChecked(isAdded);

cb_plus.setOnCheckedChangeListener(listener); // set listener after setting (un)checked
listener.onCheckedChanged(cb_plus, isAdded); // manual call

isAddedCheckBox是您检查或不检查的条件,可能是piosenki.contains(album.get(position1));piosenki.get(album.get(position1)) != null;。您还可以从getView方法中删除一些重复的行,例如具有背景或 textcolor 设置的行 - 这些将在手动侦听器调用中调用

PS。也piosenki改为songs;)


推荐阅读