我知道,之前曾问过这个问题,但我还没有找到合适的答案。
有没有办法隐藏ListView
中的某些项而不更改源数据?
我尝试将项目视图的可见性设置为已消失,它将不再显示,但为此项目保留的位置仍然存在。
我也设置了:
android:dividerHeight="0dp"
android:divider="#FFFFFF"
没有成功。
答案 0 :(得分:21)
您可以编写自己的ListAdapter
或其中一个现有的子类。
在ListAdapter
中,您只需根据需要返回getCount()
,getItem()
和getItemId()
的修改值,过滤掉您不想显示的项目。
答案 1 :(得分:11)
我尝试了多种解决方案,包括setVisibitlity(View.GONE)
并对一个默认的null
视图进行了充气,但所有这些解决方案都有一个共同的问题,即隐藏项目之间的分隔线被叠加在一起并造成不良影响大名单中的灰色空间。
如果您的ListView
由CursorAdapter
支持,那么最佳解决方案是用CursorWrapper
打包。
所以我的解决方案(基于@RomanUsachev回答here)是这样的:
<强> FilterCursorWrapper 强>
public class FilterCursorWrapper extends CursorWrapper {
private int[] index;
private int count = 0;
private int pos = 0;
public boolean isHidden(String path) {
// the logic to check where this item should be hidden
// if (some condintion)
// return false;
// else {
// return true;
// }
return false;
}
public FilterCursorWrapper(Cursor cursor, boolean doFilter, int column) {
super(cursor);
if (doFilter) {
this.count = super.getCount();
this.index = new int[this.count];
for (int i = 0; i < this.count; i++) {
super.moveToPosition(i);
if (!isHidden(this.getString(column)))
this.index[this.pos++] = i;
}
this.count = this.pos;
this.pos = 0;
super.moveToFirst();
} else {
this.count = super.getCount();
this.index = new int[this.count];
for (int i = 0; i < this.count; i++) {
this.index[i] = i;
}
}
}
@Override
public boolean move(int offset) {
return this.moveToPosition(this.pos + offset);
}
@Override
public boolean moveToNext() {
return this.moveToPosition(this.pos + 1);
}
@Override
public boolean moveToPrevious() {
return this.moveToPosition(this.pos - 1);
}
@Override
public boolean moveToFirst() {
return this.moveToPosition(0);
}
@Override
public boolean moveToLast() {
return this.moveToPosition(this.count - 1);
}
@Override
public boolean moveToPosition(int position) {
if (position >= this.count || position < 0)
return false;
return super.moveToPosition(this.index[position]);
}
@Override
public int getCount() {
return this.count;
}
@Override
public int getPosition() {
return this.pos;
}
}
当您的Cursor
准备就绪后,请使用您想要的列索引<{1}}提供
FilterCursorWrapper
如果您进行过滤和排序,请不要忘记在任何地方使用FilterCursorWrapper filterCursorWrapper = new FilterCursorWrapper(cursor, true,DATA_COLUMN_INDEX);
dataAdapter.changeCursor(filterCursorWrapper);
:
FilterCursorWrapper
并且为了刷新列表,这足以使用空过滤器进行查询:
dataAdapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
String selection = MediaStore.Video.Media.DATA + " LIKE '%" + constraint.toString().toLowerCase() + "%'";
return new FilterCursorWrapper(context.getContentResolver().query(videoMediaUri, columns, selection, null, null), true, DATA_COLUMN_INDEX);
}
});
并且您已完成,只需更改dataAdapter.getFilter().filter("");
方法的逻辑,即可控制显示或隐藏隐藏的项目。而且好处是你不会看到不受欢迎的分隔线堆积起来。 : - )
答案 2 :(得分:11)
如果你想隐藏这样的项目:
convertView.setLayoutParams(new AbsListView.LayoutParams(-1,1));
convertView.setVisibility(View.GONE);
不能是AbsListView.LayoutParams(-1,0);
如果重新使用convertview,你应该在下面添加它以将其设置为高度:
if(convertView.getVisibility() == View.GONE) {
convertView.setVisibility(View.VISIBLE);
convertView.setLayoutParams(new AbsListView.LayoutParams(-1,-2));
}
答案 3 :(得分:4)
在某些情况下,您有一个简单的解决方案:
我必须在列表视图中隐藏视图,因为填充视图的项目无效,所以我不想看到视图:
在我的列表适配器中:
public class PlanListAdapter extends BaseAdapter{
//some code here : constructor ......
// my code that create the view from the item list (one view by item ...)
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.my_layout, null);
if(my_data_are_not_valid) {
//just create an empty view
convertView = new Space(context);
}
else {
//populate the view with data here
populate(convertView);
}
return convertView;
}
//some code here to populate the view ...
}
答案 4 :(得分:2)
我有一个CursorAdapter
无法使用支持数组进行修改,因为在从数据库获取结果之后检查项是否应该显示。我已经在bindView(View v, Context context, Cursor c)
中以与其他帖子中描述的方法类似的方式实现了解决方案。 我认为最好的方法是覆盖bindView()
方法而不是getView(int position, View convertView, ViewGroup parent)
,因为你应该在getView()中对convertView进行null-ckecking。
第二件事:我试图在View v
中隐藏bindView(View v, Context context, Cursor c)
,但它无效。经过调查,我发现我必须隐藏视图中的每个元素(包括包含文本,图像等的布局)。
答案 5 :(得分:1)
黑客就是将要隐藏的列表项的高度设置为0.
但是,正如seretur所说,正确的方法是删除该项目并使用notifyDataSetChanged()
。为什么这种解决方案不适合您的情况?
答案 6 :(得分:1)
如果您创建自己的adapter
,则可以使用public View getView(int position, View convertView, ViewGroup parent)
方法执行此操作。如果您计划在某个时刻显示不可见的项目,这可能很有用。例如:
if(item.getYourRequirement == undesiredVlue)
convertView.setVisibility(View.GONE);
else
convertView.setVisibility(View.VISIBLE);
我希望这会有所帮助
答案 7 :(得分:1)
为我解决此问题的简单方法,在调用方法“setAdapter”之前解析并检查活动列表,例如:
for(Object a : list){
//here must be some condition for getting all items without hidden
newList += a;
}
setAdapter(newList);
答案 8 :(得分:0)
这是我的解决方案:
// This is a startup function that will execute when everything is loaded
$(function () {
// When a keyup event is triggered in your "search" element...
$(".search").keyup(function () {
// Grab the contents of the search box
var searchId = $(this).val();
// Build a data string (i.e. string=searchTerm), you didn't previously need the
// escaping slashes
var dataString = 'search=' + searchId;
// Now check if actually have a search term (you may prefer to check the length
// to ensure it is actually empty)
if(searchId.length != 0) {
// There is a search, so do something here
}
}
}
答案 9 :(得分:0)
listview_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp" >
<ImageView
android:id="@+id/imgView"
android:layout_width="40dp"
android:layout_height="20dp"/>
<TextView
android:id="@+id/totalTime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="14dp"
android:text="16 分鐘"
android:layout_weight="1"
android:paddingLeft="10dp" />
<TextView
android:id="@+id/currentTime"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="14dp"
android:text="11:46"
android:layout_weight="1"
android:gravity="right"
android:paddingLeft="10dp" />
<ImageView
android:id="@+id/img"
android:layout_width="40dp"
android:layout_height="20dp"
/>
</LinearLayout>
MainActivity.java
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
view.findViewById(R.id.img).setVisibility(View.GONE);
}
});
这对我有效。
答案 10 :(得分:0)
对我来说,一个简单的解决方案是使用自定义的行布局创建自己的适配器,其中包含所有内容的包装(例如LinearLayout),并在我的适配器的getView()方法中将此包装可见性设置为View.GONE。不想显示该项目。无需修改数据集或维护两个列表。创建ListView时,我还将其设置为不自动显示分隔线:
android:divider="@null"
android:dividerHeight="0dp"
并绘制自己的分隔线(当我不需要该分隔线时也将其设置为GONE)。否则,您会看到多个分隔线或一条粗灰线,其中隐藏了多个项目。