自定义列表适配器和垂直/水平方向的不同布局

发布于 2024-12-05 12:04:59 字数 4111 浏览 0 评论 0原文

自从我第一次使用 Android 以来,令我困惑的是针对不同方向具有不同布局的自定义适配器的优化使用。目前我确实遇到了级联的 NULL 检查,我想知道是否有更好的方法。

考虑垂直方向和水平方向的两种不同布局,它们确实包含不同数量的小部件。

这是位于布局中的一个小部件的垂直布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="horizontal" >

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/name"
        android:layout_weight="1" />
</LinearLayout>

这是位于布局区域中的两个小部件的水平布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="horizontal" >

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/name"
        android:layout_weight="1" />

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/description"
        android:layout_weight="1" />

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/date"
        android:layout_weight="1" />
</LinearLayout>

这是自定义适配器 - 一个扩展的 SimpleCursorAdapter。根据方向,描述和日期对象可以为空或非空。在我的 Android 项目中,我确实有包含十分之一对象的行布局,并且这些空检查在代码中变得非常讨厌。有更好的解决方案吗?你们如何使用自定义适配器和针对不同方向或尺寸的不同布局?

public class TestAdapter extends SimpleCursorAdapter {

    private static class ViewHolder {
        private TextView date;
        private TextView description;
        private TextView name;
    }

    private Context            context;
    private Cursor             cursor;
    private int                layout;
    private SQLiteDatabase     sqliteDatabase;
    private MySQLiteOpenHelper sqliteOpenHelper;

    public Test(final Context context, final int layout, final Cursor cursor, final String[] from, final int[] to) {
        super(context, layout, cursor, from, to);

        this.context = context;
        this.cursor = cursor;
        this.layout = layout;

        if (sqliteOpenHelper == null) {
            sqliteOpenHelper = new MySQLiteOpenHelper(context);
        }

        if (sqliteOpenHelper != null) {
            if (sqliteDatabase == null) {
                sqliteDatabase = sqliteOpenHelper.getWritableDatabase();
            }
        }
    }

    @Override
    public View getView(final int position, final View contentView, final ViewGroup viewGroup) {
        View       view = null;
        ViewHolder viewHolder = null;

        if (contentView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = layoutInflater.inflate(layout, null);

            if (view != null) {
                viewHolder = new ViewHolder();
                viewHolder.date = (TextView) view.findViewById(R.id.date);
                viewHolder.description = (TextView) view.findViewById(R.id.description);
                viewHolder.name = (TextView) view.findViewById(R.id.name);
                view.setTag(viewHolder);
            }
        } else {
            view = contentView;
            viewHolder = (ViewHolder) contentView.getTag();
        }

        if (viewHolder != null) {
            cursor.moveToPosition(position);

            String date = cursor.getString(cursor.getColumnIndex(Test.DATE));
            String description = cursor.getString(cursor.getColumnIndex(Test.DESCRIPTION));
            String name = cursor.getString(cursor.getColumnIndex(Test.NAME));

            if (viewHolder.date != null) {
                if (!StringUtils.isEmpty(date) && date.length() == 10) {
                    viewHolder.date.setText(Tools.formatDate(date.substring(0, 10)));
                } else {
                    viewHolder.date.setText("");
                }
            }

            if (viewHolder.description != null) viewHolder.description.setText(description);
            if (viewHolder.name != null) viewHolder.name.setText(name);
        }

        return view;
    }
}

Something that puzzles me since my first steps with Android is the optimized use of a custom adapter with different layouts for different orientations. Currently I do end up in cascades of NULL checks and I would like to know if there's a better way.

Consider two different layouts for vertical orientation and horizontal orientation that do contain a different count of widgets.

Here's the vertical layout with one widget located in layout:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="horizontal" >

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/name"
        android:layout_weight="1" />
</LinearLayout>

Here's the horizontal layout with two widgets located in layout-land:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:orientation="horizontal" >

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/name"
        android:layout_weight="1" />

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/description"
        android:layout_weight="1" />

    <TextView
        style="@style/TextViewDefault"
        android:id="@+id/date"
        android:layout_weight="1" />
</LinearLayout>

And here's the custom adapter - an extended SimpleCursorAdapter. Depending on the orientation the description and date objects are null or non-null. In my Android projetcs I do have row layouts with 10ths of objects and these null-checks become really nasty in the code. Is there a better solution? How do you guys work with custom adapters and different layouts for different orientations or sizes?

public class TestAdapter extends SimpleCursorAdapter {

    private static class ViewHolder {
        private TextView date;
        private TextView description;
        private TextView name;
    }

    private Context            context;
    private Cursor             cursor;
    private int                layout;
    private SQLiteDatabase     sqliteDatabase;
    private MySQLiteOpenHelper sqliteOpenHelper;

    public Test(final Context context, final int layout, final Cursor cursor, final String[] from, final int[] to) {
        super(context, layout, cursor, from, to);

        this.context = context;
        this.cursor = cursor;
        this.layout = layout;

        if (sqliteOpenHelper == null) {
            sqliteOpenHelper = new MySQLiteOpenHelper(context);
        }

        if (sqliteOpenHelper != null) {
            if (sqliteDatabase == null) {
                sqliteDatabase = sqliteOpenHelper.getWritableDatabase();
            }
        }
    }

    @Override
    public View getView(final int position, final View contentView, final ViewGroup viewGroup) {
        View       view = null;
        ViewHolder viewHolder = null;

        if (contentView == null) {
            LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = layoutInflater.inflate(layout, null);

            if (view != null) {
                viewHolder = new ViewHolder();
                viewHolder.date = (TextView) view.findViewById(R.id.date);
                viewHolder.description = (TextView) view.findViewById(R.id.description);
                viewHolder.name = (TextView) view.findViewById(R.id.name);
                view.setTag(viewHolder);
            }
        } else {
            view = contentView;
            viewHolder = (ViewHolder) contentView.getTag();
        }

        if (viewHolder != null) {
            cursor.moveToPosition(position);

            String date = cursor.getString(cursor.getColumnIndex(Test.DATE));
            String description = cursor.getString(cursor.getColumnIndex(Test.DESCRIPTION));
            String name = cursor.getString(cursor.getColumnIndex(Test.NAME));

            if (viewHolder.date != null) {
                if (!StringUtils.isEmpty(date) && date.length() == 10) {
                    viewHolder.date.setText(Tools.formatDate(date.substring(0, 10)));
                } else {
                    viewHolder.date.setText("");
                }
            }

            if (viewHolder.description != null) viewHolder.description.setText(description);
            if (viewHolder.name != null) viewHolder.name.setText(name);
        }

        return view;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

聊慰 2024-12-12 12:04:59

由于您有不同的小部件数量,因此您必须处理设置不同数据的事实。
但您可以摆脱以下空检查:

// wouldn't you expect to have a working layout here?
View != null        

// when view != null removed this is obsolete           
viewHolder != null

// the same thing here, you would expect a name here
viewHolder.name != null

// put that under viewHolder.date != null since both are available when one of them is
viewHolder.description.setText(description);

Since you have different widget count you have to deal with the fact setting different data.
But you can get rid of following null checks:

// wouldn't you expect to have a working layout here?
View != null        

// when view != null removed this is obsolete           
viewHolder != null

// the same thing here, you would expect a name here
viewHolder.name != null

// put that under viewHolder.date != null since both are available when one of them is
viewHolder.description.setText(description);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文