gpt4 book ai didi

android - 基于 ListItem 特定变量在 ListItem 上膨胀布局

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:23:49 26 4
gpt4 key购买 nike

我正在使用 SimpleCursorAdapterListView 来显示加载器加载的一些数据。在 cursor 中,我有一个 int 从 0 到 3 的项目。

我希望此 int 等于 0-1 的项目具有布局(右对齐,一种颜色),而 2-3 的项目具有另一种布局(左对齐,另一种颜色)。很像聊天应用,发送的消息在右边,接收的消息在左边。

有什么简单的方法吗?就像一个开关,其中 0-1 我膨胀 layout_1 和 2-3 我膨胀 layout_2。

编辑:我添加了我要填充的 ListFragment 的代码。用作开关的 int 是 MyContentProvider.Data.E_TYPE。我无法掌握它,但也许有人可以清楚地解释我要写的内容!

   import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.corsalini.survcontr.MyContentProvider.Data;

import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.support.v4.content.CursorLoader;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v4.widget.CursorAdapter;
import android.support.v4.widget.SimpleCursorAdapter;
import android.util.Log;
import android.view.View;
import android.widget.ListView;



public class FragEvents extends ListFragment implements LoaderManager.LoaderCallbacks<Cursor>{
@Override
public void onPause() {
allRead();
super.onPause();

}

private static final int EVENTS_LOADER = 0x02;

// This is the Adapter being used to display the list's data.
SimpleCursorAdapter mAdapter;

// If non-null, this is the current filter the user has provided.
String mCurFilter;

@Override public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);

// Give some text to display if there is no data. In a real
// application this would come from a resource.
setEmptyText(this.getString(R.string.perform_event));

// We have a menu item to show in action bar.
setHasOptionsMenu(true);

// Create an empty adapter we will use to display the loaded data.
mAdapter = new SimpleCursorAdapter(getActivity(),
android.R.layout.simple_list_item_2, null,
new String[] { MyContentProvider.Data.E_TEXT, MyContentProvider.Data.E_DATE,
MyContentProvider.Data.E_NUMBER, MyContentProvider.Data.E_TYPE },
new int[] { android.R.id.text1, android.R.id.text2 },
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setListAdapter(mAdapter);

// Start out with a progress indicator.
setListShown(false);

// Prepare the loader. Either re-connect with an existing one,
// or start a new one.
getActivity().getSupportLoaderManager().initLoader(EVENTS_LOADER, null, this);


}

public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_events, menu);
}



@Override public void onListItemClick(ListView l, View v, int position, long id) {
//TODO Insert desired behavior here.
Log.i("FragmentComplexList", "Item clicked: " + id);
}

// These are the Contacts rows that we will retrieve.
static final String[] SUMMARY_PROJECTION = new String[] {
MyContentProvider.Data.E_ID,
MyContentProvider.Data.E_DATE,
MyContentProvider.Data.E_NUMBER,
MyContentProvider.Data.E_TEXT,
MyContentProvider.Data.E_TYPE,

};

public Loader<Cursor> onCreateLoader(int id, Bundle args) {


return new CursorLoader(getActivity(), MyContentProvider.Data.CONTENT_URI_EVENTS,
SUMMARY_PROJECTION, null, null,
Data.E_ID + " DESC");
}

public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
// Swap the new cursor in. (The framework will take care of closing the
// old cursor once we return.)
mAdapter.swapCursor(data);

// The list should now be shown.
if (isResumed()) {
setListShown(true);
} else {
setListShownNoAnimation(true);
}
}

public void onLoaderReset(Loader<Cursor> loader) {
// This is called when the last Cursor provided to onLoadFinished()
// above is about to be closed. We need to make sure we are no
// longer using it.
mAdapter.swapCursor(null);
}

public void deleteEvent(ContentResolver contentResolver,
long id){
String selection = Data.E_ID + "=";
String[] args = {String.valueOf(id)};
contentResolver.delete(Data.CONTENT_URI_EVENTS, selection, args);
}

public void allRead(){
ContentResolver contentResolver = getActivity().getContentResolver();
ContentValues contentValue = new ContentValues();
contentValue.put(Data.E_NUMBER, Data.RECEIVED_READ);
String selection= Data.E_TYPE+"=";
String[] args= {String.valueOf(Data.RECEIVED_UNREAD)};
contentResolver.update(Data.CONTENT_URI_EVENTS, contentValue, selection, args);
}



}

编辑:如果我做对了,我最终的 EventsAdapter(扩展了 SimpleCursorAdapter)应该如下所示:

    import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.SimpleCursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class EventsAdapter extends SimpleCursorAdapter {

private Context localContext;

public EventsAdapter(Context context, int layout, Cursor c, String[] from,
int[] to, int flags) {
super(context, layout, c, from, to, flags);

localContext = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {

Cursor c= getCursor();
c.moveToPosition(position);
if(convertView == null)
{
LayoutInflater layoutInflator = (LayoutInflater)localContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

switch (getItemViewType(position)){
case 0:
convertView = layoutInflator.inflate(R.layout.item_event_0, null);
break;
case 1:
convertView = layoutInflator.inflate(R.layout.item_event_1, null);
break;
case 2:
convertView = layoutInflator.inflate(R.layout.item_event_2, null);
break;
case 3:
convertView = layoutInflator.inflate(R.layout.item_event_3, null);
break;
}

}
switch (getItemViewType(position)){
case 0:
TextView date0=(TextView)convertView.findViewById(R.id.date0);
TextView text0=(TextView)convertView.findViewById(R.id.text0);
date0.setText(""+c.getString(c.getColumnIndex(Data.E_DATE)));
text0.setText(""+c.getString(c.getColumnIndex(Data.E_TEXT)));
break;
case 1:
TextView date1=(TextView)convertView.findViewById(R.id.date1);
TextView text1=(TextView)convertView.findViewById(R.id.text1);
date1.setText(""+c.getString(c.getColumnIndex(Data.E_DATE)));
text1.setText(""+c.getString(c.getColumnIndex(Data.E_TEXT)));
case 2:
TextView date2=(TextView)convertView.findViewById(R.id.date2);
TextView text2=(TextView)convertView.findViewById(R.id.text2);
date2.setText(""+c.getString(c.getColumnIndex(Data.E_DATE)));
text2.setText(""+c.getString(c.getColumnIndex(Data.E_TEXT)));
case 3:
TextView date3=(TextView)convertView.findViewById(R.id.date3);
TextView text3=(TextView)convertView.findViewById(R.id.text3);
date3.setText(""+c.getString(c.getColumnIndex(Data.E_DATE)));
text3.setText(""+c.getString(c.getColumnIndex(Data.E_TEXT)));
}
return convertView;
}

@Override
public int getItemViewType(int position) {
int type = 0;
int returnInt = 0;
Cursor c= getCursor();
c.moveToPosition(position);
type= c.getInt(c.getColumnIndex(Data.E_TYPE));
switch (type){
case Data.RECEIVED_READ:
returnInt=3;
case Data.RECEIVED_UNREAD:
returnInt= 2;
case Data.SENT_COMPLETED:
returnInt= 1;
case Data.SENT_PROGRESS:
returnInt= 0;
default:
returnInt=0;
}
return returnInt;
}

@Override
public int getViewTypeCount() {
return 4;
}

}

最佳答案

在使用 ListView 时,尤其是像您描述的那样复杂的 ListView,正确处理 View 回收非常重要。 BaseAdapter 类是 SimpleCursorAdapter 的父类(super class),您可以重写一些方法,以使用最少的资源实现所需的效果。我以前从未使用过 SimpleCursorAdatper,因此在编写本文时考虑了普通的 CursorAdapter,但您可以将其与任何覆盖 BaseAdapter 的适配器类一起使用。

Android 中的 ListView 以一种非常特殊的方式运行以降低内存成本。当您滚动浏览 ListView 时,移出屏幕的项目的 View 将放置在一个小的 View 池中。 convertView 参数取自该池。他们这样做是因为将每个列表项 View 保存在内存中并不能很好地扩展,并且会很快导致 OutOfMemory 异常。 getView() 方法是获取这些 View 并为当前列表项配置它们的地方。通常你会有这样一行:

if(convertView == null)
convertView = layoutInflator.inflate(R.layout.list_item, null);

在这种情况下,如果 convertView 不为 null,我们就知道它之前被膨胀了。我们不想重新膨胀它,因为这是一个代价高昂的操作,getView 应该只是在显示之前用数据快速填充 View 。

现在,在您的情况下,convertView 有两种潜在的膨胀。不是每次都重新膨胀 View (非常糟糕)或使用某种 hack 为每个 View 提供唯一的资源 ID(更好,但不理想),我们可以重写基类中的两个方法以确保 convertView 始终是正确的类型。这两个方法是 getItemViewCount()getItemViewType(int position)

适配器使用

getItemViewCount() 来确定它应该为列表维护多少个 View 池。覆盖它很简单,在您的情况下看起来像这样。

@Override
public int getViewTypeCount()
{
return 2; //Even though you have four cases, there are only 2 view types.
}

getItemViewType(int position) 由 Adapter 在调用 getView 之前使用,以决定 convertView 应该来自哪个池。在这里,您需要一个 switch 或 if/else 语句来检查底层数据源的 View 类型并返回它。 (请注意,根据 Android 文档,此处的返回值必须介于 0 和 getViewTypeCount() -1 之间,因此在您的情况下为 0 或 1。)

@Override
public int getItemViewType(int position)
{
Item item = getItem(position) //Or however you're getting the data associated with a particular list position
switch(item.myInt)
{
//I simplified this a bit, basically, check your int, if it's the first type, return 0 for your first layout type, else return 1 for your second.
case(0):
case(1):
return 0;
case(2):
case(3):
return 1;
}
}

现在,最后,我们将修改 getView 以执行初始 layoutInflation,以便您在池中拥有正确的 View 。

@Override
public View getView(int position, View convertView, ViewGroup viewParent)
{
//if convertView is not null, we got a view from the pool, just go on
if(convertView == null)
{
//This means we didn't have a view in the pool to match this view type. Inflate it and it will be placed in the proper pool when this list item is scrolled off the screen
if(getItemViewType(position) == 0)
convertView = layoutInflator.inflate(R.layout.list_item_type1, null);
else if(getItemViewType(position) == 1)
convertView = layoutInflator.inflate(R.layout.list_item_type2, null);
}

//Populate the view with whatever data you need here

//And finally....
return convertView;
}

ListView 及其适配器是我在 Android 中遇到的最复杂的事情之一,但花时间正确地完成它会大大提高应用程序的性能和用户体验。祝你好运!

关于android - 基于 ListItem 特定变量在 ListItem 上膨胀布局,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12180724/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com