首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基于ListItem专用变量的ListItem充气布局

基于ListItem专用变量的ListItem充气布局
EN

Stack Overflow用户
提问于 2012-08-29 22:50:15
回答 2查看 3.9K关注 0票数 7

我使用一个SimpleCursorAdapter和一个ListView来显示用Loader加载的一些数据。在cursor中,我有一个int从0到3的项目。

我希望这个int等于0-1的项目有一个布局(右对齐,一种颜色),2-3的项目有另一个布局(左对齐,另一种颜色)。much like a chat app, where sent messages are on the right and received ones are on the left.

有没有一种简单的方法呢?这就像一个开关,0-1我膨胀layout_1,2-3我膨胀layout_2。

编辑:我已经添加了我试图填充的ListFragment的代码。用作开关的int是MyContentProvider.Data.E_TYPE。我不能理解它的诀窍,但也许有人能解释清楚我要写的东西!

代码语言:javascript
复制
   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)应该如下所示:

代码语言:javascript
复制
    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;
}

    }
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-29 23:55:05

在使用ListViews时,特别是像您所描述的那样复杂的应用程序,正确处理视图回收是很重要的。SimpleCursorAdapter的超类BaseAdapter类有几个方法,您可以覆盖这些方法,以便在使用最少资源的情况下达到所需的效果。我以前从未使用过SimpleCursorAdatper,所以在编写本文时考虑到了一个普通的CursorAdapter,但是您可以将其用于任何覆盖BaseAdapter的Adapter类。

Android中的ListViews以一种非常特殊的方式来降低内存成本。当您在ListView中滚动时,移出屏幕的项目的视图被放置在一个小的视图池中。convertView参数取自此池。之所以这样做,是因为将每个列表项视图保留在内存中不能很好地扩展,并且可能很快导致OutOfMemory异常。getView()方法是获取这些视图并为当前列表项配置它们的位置。通常你会有一行代码,看起来像这样:

代码语言:javascript
复制
if(convertView == null)
    convertView = layoutInflator.inflate(R.layout.list_item, null);

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

现在,在您的案例中,convertView有两个潜在的通货膨胀。我们可以覆盖基类中的两个方法,以确保convertView始终是正确的类型,而不是每次都重新膨胀视图(非常糟糕),或者使用某种技巧为每个视图使用唯一的资源is (更好,但不理想)。这两种方法是getItemViewCount()getItemViewType(int position)

适配器使用getItemViewCount()来确定它应该为列表维护多少视图池。覆盖它很简单,在您的例子中应该是这样的。

代码语言:javascript
复制
@Override
public int getViewTypeCount()
{
    return 2; //Even though you have four cases, there are only 2 view types.
}

在调用getView之前,适配器使用getItemViewType(int position)来决定convertView应该来自哪个池。在这里,您需要一个switch或if/else语句来检查底层数据源是哪种视图类型并返回它。(请注意,根据安卓文档,此处的返回值必须介于0和getViewTypeCount() -1之间,因此在本例中为0或1。)

代码语言:javascript
复制
@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,以便您在池中拥有正确的视图。

代码语言:javascript
复制
@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;
}

ListViews和他们的适配器是我在Android中遇到的最复杂的东西之一,但花点时间做好它会极大地提高你的应用程序的性能和用户体验。祝好运!

票数 10
EN

Stack Overflow用户

发布于 2012-08-29 23:12:25

我认为你只需要在你的getView(int position, View convertView, ViewGroup parent)方法上膨胀正确的布局:

代码语言:javascript
复制
MyItem item = getItem(position);
View vi = convertView;
if(vi == null){
    switch(item.getStatus())
    {
        case 0:
            vi = mInflater.inflate(R.layout.item1, null);
            break;
        case 1:
            vi = mInflater.inflate(R.layout.item2, null);
            break;
        case 2:
            vi = mInflater.inflate(R.layout.item3, null);
            break;
    }
    //set viewholder ...
}else{
    //get viewholder ...
}
// set values to views ...

这是你需要的吗?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12180724

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档