android - 使用自定义适配器更新过滤后的列表视图
问题描述
我正在创建一个音乐播放器。除其他外,该课程假定将新歌曲添加到播放列表中。将弹出一个新窗口,其中包含可用歌曲,并添加选中的歌曲。可以过滤歌曲,并且选中复选框时所选行将更改颜色。过滤有效,所有内容都按照预期的方式添加,但是......
问题是当我检查一首歌曲/一些歌曲然后点击搜索过滤器并且软键盘弹出所选行的颜色更改为默认颜色时,(歌曲仍然被检查并且可以添加到播放列表)。当检查歌曲并隐藏键盘时,也会发生同样的事情。
另一个问题是,当列表被过滤时,先前选择的行的颜色也会消失,当搜索框被清除时,歌曲仍然处于选中状态。
而且我不明白这种情况是如何发生的以及为什么会发生,因此如何解决这个问题。请问有人有什么想法吗?
我想我不明白过滤后的更新是如何工作的,以及 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>
解决方案
原因很简单 - 您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
isAdded
CheckBox
是您检查或不检查的条件,可能是piosenki.contains(album.get(position1));
或piosenki.get(album.get(position1)) != null;
。您还可以从getView
方法中删除一些重复的行,例如具有背景或 textcolor 设置的行 - 这些将在手动侦听器调用中调用
PS。也piosenki
改为songs
;)
推荐阅读
- r - 从季度到年度数据
- php - 为什么我可以在 PHP5 中传递不带引号的回调函数?
- django - 如何为 WSGIPassAuthorization On 设置配置文件以在 django 中使用 apache 进行令牌身份验证
- php - 包含另一个 php 文件后页面不显示内容
- c# - Powershell 字符串插值是否支持格式说明符
- node.js - 是否可以使用 TestCafé 比较两个图像以验证确切的图像是否可用?
- c# - Telegram Bot 无法接收 preCheckoutQuery 更新
- node.js - 如果在 package.json 中不满足依赖关系,项目为什么仍然运行和构建?
- opencv - 本质分解的稳定翻译
- javascript - 如何使用 JavaScript 在点击时突出显示元素?