在Android中,如何从onlistitemclick更改单个listview行中小部件的可见性?
我的最终目标是将中的信息源从数组更改为光标。这里有一个链接到。其要点是,单击列表中的一行,正文将在列出的标题下打开,然后再次单击它,正文将消失。我不想记住便笺是否打开,也不想通过视图循环保持它打开,也不想在打开一个或任何其他我能想到的奇特排列时关闭所有其他 大多数情况下,一切都正常工作,但当onListItemClick事件处理程序启动、更改可见性以及在Android中,如何从onlistitemclick更改单个listview行中小部件的可见性?,android,listview,visibility,Android,Listview,Visibility,我的最终目标是将中的信息源从数组更改为光标。这里有一个链接到。其要点是,单击列表中的一行,正文将在列出的标题下打开,然后再次单击它,正文将消失。我不想记住便笺是否打开,也不想通过视图循环保持它打开,也不想在打开一个或任何其他我能想到的奇特排列时关闭所有其他 大多数情况下,一切都正常工作,但当onListItemClick事件处理程序启动、更改可见性以及notifyDataSetChanged()s时,列表会做一些奇怪的事情,包括单击两次以更改可见性,而不重新测量自身,导致列表行每隔三次左右只为自
notifyDataSetChanged()
s时,列表会做一些奇怪的事情,包括单击两次以更改可见性,而不重新测量自身,导致列表行每隔三次左右只为自身腾出空间
之前的一次尝试导致了一个完美的工作列表,除了单击时,我想隐藏和显示的每一行中的块都会隐藏和显示,教程中的列表工作得非常好,但当然,在所有内容中都使用静态大小,所以只不过是一个模板
我确信问题要么是获取附加到列表行的可见性信息,要么是在设置之后更改它
以下是onListItemClick
:
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
((NotesCursorAdapter) getListAdapter()).toggle(position, v);
}
使用notescrsoradapter
中的切换方法:
public void toggle(int position, View view) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.mExpanded[position] = !holder.mExpanded[position];
notifyDataSetChanged();
}
notescorsoradapter
外部的ViewHolder
:
static class ViewHolder {
public TextView title;
public TextView body;
public boolean mExpanded[];
}
以及notescrsoradapter
本身:
class NotesCursorAdapter extends CursorAdapter {
private static final int VISIBLE = 0;
private static final int GONE = 8;
public NotesCursorAdapter(Context context, Cursor c) {
super(context, c);
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, null, true);
ViewHolder holder = new ViewHolder();
holder.title = (TextView) rowView
.findViewById(R.id.title);
holder.body = (TextView) rowView
.findViewById(R.id.body);
holder.mExpanded = new boolean[cursor.getCount()];
rowView.setTag(holder);
return rowView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.title.setText(cursor.getString(cursor
.getColumnIndexOrThrow(DbAdapter.KEY_TITLE))
+ holder.mExpanded[cursor.getPosition()]);
holder.body.setText(cursor
.getString(cursor
.getColumnIndexOrThrow(DbAdapter.KEY_BODY)));
holder.body
.setVisibility(holder.mExpanded[cursor.getPosition()] ? VISIBLE : GONE);
}
public void toggle(int position, View view) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.mExpanded[position] = !holder.mExpanded[position];
notifyDataSetChanged();
}
}
我不知道下一步该往哪里看。我是否需要创建自己的getView()
方法?我能从getItem()
中得到有用的东西吗?像这样尝试使用列表视图
,我是不是疯了
我已经做了更多的调查,代码正在运行,但是点击事件似乎影响了相反的观点。我的意思是,当您单击顶部列表项时,它会影响底部列表项。单击顶部的第二个按钮时,将影响底部的第二个按钮。如果列表项的数量为奇数,则中间的列表项工作正常。在某种程度上,无论我用什么方式来确定我正在影响的视图的id,都会被翻转。listview是否自下而上进行编号?我刚刚在API演示的List6中实现了类似的功能。我的相机工作得很好(不管怎样,我在使用图像按钮对焦时遇到了麻烦)。我使用了一个简单的游标适配器,但是我想你可以使用游标适配器。我修改了你的代码很多 不知道为什么还要添加View参数,所以我去掉了它
private ArrayList<Boolean> mExpanded;
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
((NotesCursorAdapter) getListAdapter()).toggle(position);
}
这是您的自定义ListAdapter。我不知道你为什么想使用bindView和newView与一个ViewHolder,Android负责bindView和newView。但在这种情况下,您需要使用ViewHolder,因此getView是必要的
private class NotesCursorAdapter extends SimpleCursorAdapter {
private Cursor cursor;
private LayoutInflater inflater;
public NotesCursorAdapter(Context context, int layout, Cursor cursor, String[] from, int[] to) {
super(context, layout, cursor, from, to);
this.cursor = cursor;
inflater = LayoutInflater.from(context);
mExpanded = new ArrayList<Boolean>();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = inflater.inflate(R.layout.row, parent, false);
populateExpanded();
holder = new ViewHolder(convertView, mExpanded.get(position));
convertView.setTag(holder);
}
else {
holder = (ViewHolder) convertView.getTag();
}
holder.setTitle(position);
holder.setBody(position);
holder.setExpanded(mExpanded.get(position));
return rowView;
}
private void populateExpanded() {
// We want our hidden TextView to not be expanded initially
for (int i = 0; i < cursor.getCount(); i++) {
mExpanded.add(false);
}
}
public void toggle(int position) {
if (mExpanded.get(position) == false) {
mExpanded.set(position, true);
}
else {
mExpanded.set(position, false);
}
notifyDataSetChanged();
}
}
K、 我弄明白了。设置未正确显示,因为ListView有两个层:视图层和数据层。android在ListView中回收视图的方式意味着使用哪个视图来显示数据并不重要。因此,要使用CursorAdapter,视图信息进入newView()方法,来自光标的数据信息进入bindView()方法。这里是固定的东西: 这里没有太多变化,只是传递了需要的信息:
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
((NotesCursorAdapter) l.getAdapter()).toggle(position);
}
视图持有者仅获取构造视图所需的信息,而不获取视图中的任何信息,包括可见状态:
static class ViewHolder {
public TextView title;
public TextView body;
public Button button;
}
可见状态作为适配器的属性在数组中进行跟踪。视图信息在newView()方法中,数据信息在bindView()方法中。当NOTIFYDATASETCHANGE()启动时,所有视图都将被回收,数据将重新分层。因为视图信息和数据信息是分开的,所以哪个视图与哪个数据匹配并不重要
class NotesCursorAdapter extends CursorAdapter {
private boolean[] expandedArray;
public NotesCursorAdapter(Context context, Cursor c) {
super(context, c);
expandedArray = new boolean[c.getCount()];
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, parent, false);
ViewHolder holder = new ViewHolder();
holder.title= (TextView) rowView
.findViewById(R.id.title);
holder.body= (TextView) rowView
.findViewById(R.id.body);
holder.button= (Button) rowView
.findViewById(R.id.button);
rowView.setTag(holder);
return rowView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.title.setText(cursor.getString(cursor
.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
holder.body.setText(cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
holder.body
.setVisibility(expandedArray[cursor.getPosition()] ? View.VISIBLE
: View.GONE);
holder.button
.setVisibility(expandedArray[cursor.getPosition()] ? View.VISIBLE
: View.GONE);
holder.button.setTag(cursor.getPosition());
}
public void toggle(int position) {
expandedArray[position] = !expandedArray[position];
notifyDataSetChanged();
}
}
为完整起见,以下是要在onCreate()、onActivityResult()或需要重新加载列表时调用的ListAdapter映射中的映射:
private void fillData() {
notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
NotesCursorAdapter notes = new NotesCursorAdapter(this, notesCursor);
setListAdapter(notes);
}
我正在努力让你的代码正常工作。在哪里调用setExpanded(),当holder为null时,如何设置holder上数组的大小?我把视图作为一个参数,因为我在尝试不同的东西,所以我让构造函数接受我能得到的任何东西。我使用CursorAdapter而不是SimpleCursorAdapter,因为我最终会做一些不简单的事情,我不认为SimpleCursorAdapter的作用不仅仅是将字符串映射到文本视图和图像视图。CursorAdapter需要newView()和bindView()方法的代码。好的,我修复了一些错误。我创建了一个方法来设置布尔数组的初始值。就像他们在列表6中预定义的那样(但这是一种静态的廉价方式,而不是动态的)。SimpleCrsorAdapter可以做任何你想做的事情。在我的应用程序中,我有一个文本视图(就像你的标题)和一个线性布局,它的可见性已经消失。它包含两个ImageButton(带有onclicklisteners)和一个textview(显示数字)。这很不简单。你到底想以后做什么?我知道了。问题是我在适配器和视图保持架中跟踪扩展视图的状态。一旦我在适配器类中添加了一个布尔数组,然后用它来确定视图的状态,应用程序就开始做一些奇怪的事情,当我从视图保持器中删除可见性布尔值时,它工作得非常好。非常感谢你的帮助。让我尝试一个简单的游标适配器,让我真正了解了getView()/newView()/bindView()系统是如何工作的,也让我真正了解了对象的来源。太棒了!没问题!我遇到这个问题是出于良心,因为我是w
class NotesCursorAdapter extends CursorAdapter {
private boolean[] expandedArray;
public NotesCursorAdapter(Context context, Cursor c) {
super(context, c);
expandedArray = new boolean[c.getCount()];
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.row, parent, false);
ViewHolder holder = new ViewHolder();
holder.title= (TextView) rowView
.findViewById(R.id.title);
holder.body= (TextView) rowView
.findViewById(R.id.body);
holder.button= (Button) rowView
.findViewById(R.id.button);
rowView.setTag(holder);
return rowView;
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
holder.title.setText(cursor.getString(cursor
.getColumnIndexOrThrow(NotesDbAdapter.KEY_TITLE)));
holder.body.setText(cursor.getString(cursor.getColumnIndexOrThrow(NotesDbAdapter.KEY_BODY)));
holder.body
.setVisibility(expandedArray[cursor.getPosition()] ? View.VISIBLE
: View.GONE);
holder.button
.setVisibility(expandedArray[cursor.getPosition()] ? View.VISIBLE
: View.GONE);
holder.button.setTag(cursor.getPosition());
}
public void toggle(int position) {
expandedArray[position] = !expandedArray[position];
notifyDataSetChanged();
}
}
private void fillData() {
notesCursor = mDbHelper.fetchAllNotes();
startManagingCursor(notesCursor);
NotesCursorAdapter notes = new NotesCursorAdapter(this, notesCursor);
setListAdapter(notes);
}