基于 ListItem 特定变量对 ListItem 进行膨胀布局

2023-11-22

我正在使用一个SimpleCursorAdapter and a 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 我膨胀布局 _1 和 2-3 我膨胀布局 _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 时,正确处理视图回收非常重要。这BaseAdapter类,超类SimpleCursorAdapter有一些方法可以覆盖,以使用最少的资源实现您想要的效果。我以前从未使用过 SimpleCursorAdatper,因此这是使用普通 CursorAdapter 编写的,但您可以将其与覆盖 BaseAdapter 的任何 Adapter 类一起使用。

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

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

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

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

getItemViewCount()适配器使用它来确定应为列表维护多少个视图池。覆盖它很简单,在你的情况下看起来像这样。

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

getItemViewType(int position)在调用 getView 之前由适配器使用来决定 ConvertView 应该来自哪个池。在这里,您需要一个 switch 或 if/else 语句来检查基础数据源的视图类型并返回它。 (请注意,根据 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,以便您的池中拥有正确的视图。

@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 中遇到的最复杂的事情之一,但是花时间正确地完成它将会极大地提高应用程序的性能和用户体验。祝你好运!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于 ListItem 特定变量对 ListItem 进行膨胀布局 的相关文章

  • 反转 ArrayList 最简单的方法是什么?

    反转这个ArrayList的最简单方法是什么 ArrayList
  • 方法调用 mActionBar=getActionBar() 给出错误[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我正在使用支持库android support v7 app actionbar因为我想要操作栏API 级别 8以上 但是下面的句子给了我
  • Cordova 插件包括 Android 库 (Gradle)

    我想包括这个 Androidlibrary https github com 50ButtonsEach fliclib android在 Cordova 插件中 该库本身由 Gradle 管理 如 Github 链接所示 图书馆的开发者只
  • 当子可滚动部件到达颤振顶部时,如何自动开始滚动父可滚动部件

    这似乎很自然 甚至可能是预料之中的 但我仍然没有找到任何可能有帮助的东西 我在另一个可滚动小部件 父级 中有一个 ScrollablePositionedList 几乎与 ListView 相同 我尝试过 CustomScrollView
  • 按大小、日期、名称等在回收器视图中排序并记住选择

    我正在制作图库应用程序 我想为其添加排序功能 我可以使用以下命令在运行时对项目进行排序Comparator但问题是 每当我退出应用程序时 列表都会再次从数据库中出来 并且所有列表都未排序 我想在我的应用程序中提供按日期 大小 名称等排序的选
  • Android P Beta - AlarmManager 通知不起作用

    我正在 Android P beta 版本 4 上测试我的应用程序 我的应用程序目标SdkVersion是27 据观察 警报管理器通知未按预期工作 我使用下面的代码来设置通知 if android os Build VERSION SDK
  • 使用选项卡式活动中的捆绑包将值从活动传递到片段

    我是一个java文盲 但仍在尝试开发一个供我个人使用的应用程序 我从 android studio 的 Tabbed Activity 开始 除了 MainActivity 中的一个片段和一个包之外 大部分没有改变 这是我的代码 主要活动
  • 更改 Android Spinner 布局/设计

    我正在尝试修改设计Spinner http developer android com intl de reference android widget Spinner html小部件 我可以更改背景 但找不到更改右侧箭头图标的方法 有办法
  • 指标元素之间的空间

    如何增加 减少指标元素之间的空间ViewPagerIndicator 我用过CirclePageIndicator 我能够通过以下步骤在两个指标之间留出更多空间 打开源代码CirclePageIndicator并找到变量mRadius 在第
  • 从 ios 和 android 端连接到 xmpp 时获取所有群组消息

    我在用开放火版本 4 0 1 使用开火Rest Api https github com gidkom php openfire restapi我在服务 servicename xx xx xxx xxx 中创建了群聊室 现在房间已创建 发
  • 在应用程序启动期间更改主题的最快方法

    目前 我确实在我的应用程序中根据用户最后的选择提供了 2 个主题 深色主题和浅色主题 在主要活动启动期间 我将执行以下操作 public class MyFragmentActivity extends FragmentActivity O
  • FragmentTransaction 动画滑入顶部

    我试图使用 FragmentTransaction setCustomAnimations 实现以下效果 片段A正在显示 将片段 A 替换为片段 B 片段 A 在替换过程中应保持可见 片段 B 应从右侧滑入 片段 B 应滑入片段 A 的顶部
  • 使用 Asp.Net 的 GCM 推送通知

    正如您可能已经看到的 Google 正在迁移其推送通知系统 http developer android com guide google gcm c2dm html http developer android com guide goo
  • 将样式应用于警报对话框

    我决定尝试材质警报dialogs https material io develop android components dialog 在安卓上 我遇到的问题是当我尝试应用某些样式时 检查文档 我发现了这个
  • Android Lollipop BLE 扫描 - 获取没有重复的外设

    Android Lollipop 引入了一种扫描 BLE 外设的新方法 通过蓝牙扫描仪 http developer android com reference android bluetooth le BluetoothLeScanner
  • 使用 IntelliJ / Android Studio 调试基于 gradle 的单元测试

    我正在使用robolectric gradle 插件 https github com robolectric robolectric gradle plugin为 Android 编写单元测试 到目前为止 除了能够使用 Android S
  • Android 在通话期间播放音频文件[重复]

    这个问题在这里已经有答案了 对于我的 Android 应用程序 我想在从应用程序接听电话后播放音频文件 应用程序将发起电话呼叫 一旦接收者接听电话 应用程序应开始播放录制的音频文件 通过在谷歌上进行大量搜索 我发现这对于未root的设备来说
  • Android 中的字符串加密

    我正在使用代码进行加密和加密 它没有给出字符串结果 字节数组未转换为字符串 我几乎尝试了所有方法将字节数组转换为字符 但没有给出结果 public class EncryptionTest extends Activity EditText
  • Android同步onSensorChanged?

    这是我的问题的后续 Android线程可运行性能 https stackoverflow com questions 36395440 android thread runnable performance 我在理解应用程序的同步方法时遇到
  • 无法读取解析推送通知包数据

    我尝试使用 Parse 推送通知服务发送自定义数据 但从 Bundle 中提取时总是返回 null 值 自定义广播接收器 Override public void onReceive Context context Intent inten

随机推荐

  • 在 C++ 中搜索并插入具有 3 个元素的映射

    我需要一张这样的地图 typedef std map
  • 在 swagger 中过滤 API 部分

    我有一个 REST API 和 springfox swagger v2 6 1 并正在运行 但现在 我不想总是显示我拥有的所有控制器 因为其中一些控制器技术性很强 不适合普通用户 但我希望能够选择我显示的内容 而无需重新编译代码 页面顶部
  • laravel Livewire 线:单击不触发该功能

    我想用 laravel livewire 做一个 SPA 我想使用wire click 来触发组件中的一个函数 但它不起作用 如果代码混乱 请原谅 这是我第一次在这里发布 我不确定要发布什么这是我的代码来解决这些问题谢谢 main blad
  • 使用 h5py 将光栅图像添加到 HDF5 文件

    如果这是一个新手问题 我很抱歉 但我对 Python 和 HDF5 相当陌生 我正在使用 h5py numpy 和 Python 2 7 我有来自各种文件的数据需要导入到一个 HDF5 文件中 每个文件的数据将存储在不同的组中 每个组都需要
  • SKView 和 SKScene 有什么区别

    来自苹果文档 SK视图 SKView 对象是显示 Sprite Kit 内容的视图 此内容由 SKScene 对象提供 SK场景 SKScene 对象代表 Sprite Kit 中的内容场景 有什么不同 SKScene 类似于视图控制器 S
  • GCM 如何使用 GCM 和第 3 方服务器取消注册设备

    我有一个使用 GCM 推送通知的应用程序 它工作正常 我的设备注册并接收推送消息 如果我从设备上卸载该应用程序 我将不再像您期望的那样收到消息 在我卸载应用程序后 您在服务器上发送消息的文本框仍然存在 这也是我所期望的 我查看了有关取消注册
  • 经典ASP超级菜鸟问题

    好的 在花了几年时间使用一种非常简单的专有语言进行编码之后 我最近进入了 Web 开发领域 我的第一份工作就是为我们的一个客户调整一个旧的经典 ASP 页面 我正在使用 Visual Studio 2008 尝试调试遇到的一些问题 但页面根
  • 如何在 Ag-Grid 中隐藏排序顺序指示器?

    我正在使用 AgGrid 和 ag grid angular 15 0 0 我的所有专栏都是可排序的 Ag grid 在每个标题中打印一个数字 指示排序顺序 如何隐藏这个 我正在使用suppressMultiSort true 因为我只想按
  • Rails 使用 Twitter Bootstrap 设计 I18n Flash 消息

    你好 我是 Ruby on Rails 的新手 我正在努力理解 I18n 的 Flash 消息 我正在使用 devise rails 4 和 twitter bootstrap 我知道 devise 仅使用flash notice and
  • Swift 4 计时器因 NSException 崩溃

    我一直在寻找一种在 Swift 4 中使用计时器的方法 并查看了this文章 我在 xcode 中测试了我的代码 当计时器第一次计时 在本例中是 10 秒后 时 应用程序崩溃并收到错误 尽管构建成功 2017 11 20 19 54 42
  • 扩展设备注册控制器

    我有一个Accounts使用 Devise 设置模型 Devise 使用一些属性 例如电子邮件 密码等 但我还创建了一些其他属性 注册时 我想以某种方式设置它们 如何扩展注册控制器 我知道我需要实际创建一个像这样的新控制器 class Ac
  • Linux 中如何找出哪些进程正在使用交换空间?

    在Linux下 如何找出哪个进程使用交换空间更多 我发现的最好的脚本在此页面上 http northernmost org blog find out what is using your swap 这是脚本的一种变体 不需要 root b
  • 如何将 Python 框架构建与 Anaconda 结合使用

    我无法在 Mac 计算机上显示 matplotlib 动画 我已经多次尝试安装 ffmpeg 但都失败了 我开始怀疑这是否是解决问题的错误方法 I found this page 由于我从 Anaconda 中的 Spyder 应用程序运行
  • 随机数和下取整函数与轮函数

    为什么如果我使用随机数生成器和范围 0 9 我不会得到与下限函数组合相同的均匀分布 Math floor Math random 10 给出相当均匀的分布 同时Math round Math random 10 没有 Math floor
  • 在 Startup.cs 中添加 DbContextOptions 不注册数据存储

    我的问题是下面的代码在启动期间没有注册数据存储 这是我在应用程序响应中得到的特定 错误 语句 An unhandled exception occurred while processing the request InvalidOpera
  • 以真实分辨率将 MKMapView 渲染为 UIImage

    我正在使用此函数将 MKMapView 实例渲染为图像 implementation UIView Ext UIImage renderToImage UIGraphicsBeginImageContext self frame size
  • 如何在核心php中实现mvc

    没有任何框架的php如何使用mvc架构 更新于2020 02 11 重构答案以包含一些最佳实践并更接近 PHP 7 4 最简单的 PHP MVC 方法 数千个单词无法与一个干净的示例竞争 因此这里是一个简单的用例 想象一下 您想要显示一个描
  • 在Flutter中如何使用多图像选择器选择图像后获取图像路径?

    我想从选定的多个图像中获取图像路径 我正在使用这个link选择多个图像但我 获得了资产 我想要所选多个图像的路径 因为我想上传到 API 我在中添加了这个依赖项pubspec yaml如果有什么好的办法请告诉我 multi image pi
  • 处理 Winnt.h 时出现奇怪的编译错误

    当尝试通过 windows h 编译包含 winnt h 的文件时 出现以下错误 MyGl cpp microsoft sdks windows v6 0a include winnt h 964 error C2988 unrecogni
  • 基于 ListItem 特定变量对 ListItem 进行膨胀布局

    我正在使用一个SimpleCursorAdapter and a ListView显示使用 Loader 加载的一些数据 在 的里面cursor我的物品带有int从 0 到 3 我希望此 int 等于 0 1 的项目具有布局 右对齐 一种颜