Android 多列列表视图

发布于 2024-12-11 08:06:52 字数 176 浏览 0 评论 0原文

我正在为我的应用程序创建一个排行榜、高分列表。我想以 4 列显示数据:排名、名称、创建者、得分,并通过对象列表相应地填充它们。我想在列表中一次显示 5 个项目,总共 20 个项目,使列表可滚动。我找不到合适的方法来做到这一点。由于我的工作截止日期即将到来,如果我能获得有关“如何做”的快速指南,那就太好了。

一百万谢谢:)

i am creating a leaderboard, highscore list for my application. I want to display the data in 4 columns, Rank, Name, Creator, Score and populate them accordingly by a list of objects. I want to display 5 items at once on the list with a total of 20 items on the list making the list scrollable. I cannot find a suitable way to go this. It would be great if i can get a quick guide on 'how to' since the deadline of my work is approaching.

thanks a million :)

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

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

发布评论

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

评论(3

絕版丫頭 2024-12-18 08:06:52

您可以通过定义自定义 ListView 轻松完成此操作。

要定义自定义列表视图,只需定义一个具有 4 个水平文本视图的自定义行布局文件即可。现在在 listview 的自定义适配器内膨胀此布局文件,为此您需要重写 getView() 方法并膨胀该行布局文件。

更新:
只需检查此 教程 来定义自定义列表视图,但使确保您通过定义具有 4 个水平文本视图的自定义行布局文件来使用本教程。

这是 row_layout.xml 文件:

<LinearLayout 
    android:id="@+id/relativeLayout1" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/FirstText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="First"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/SecondText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Second"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/ThirdText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Third"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/FourthText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Fourth"
        android:layout_weight="1">
    </TextView>
</LinearLayout>

You can easily done it with defining Custom ListView.

For defining custom listview, just define a custom row layout file with 4 textview in horizontal manner. Now inflating this layout file inside the custom adapter of listview, for that you need to override getView() method and inflate that row layout file.

Update:
Just check this tutorial to define custom listview, but make sure you use this tutorial by defining a custom row layout file with 4 horizontal textview.

Here is the row_layout.xml file:

<LinearLayout 
    android:id="@+id/relativeLayout1" 
    android:layout_height="fill_parent" 
    android:layout_width="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">

    <TextView
        android:id="@+id/FirstText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="First"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/SecondText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Second"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/ThirdText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Third"
        android:layout_weight="1">
    </TextView>

    <TextView
        android:id="@+id/FourthText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Fourth"
        android:layout_weight="1">
    </TextView>
</LinearLayout>
棒棒糖 2024-12-18 08:06:52

终于找到解决办法了。我和 Android 以及 Xamarin for Android 新手有同样的问题。需要明确的是 - 我正在使用 Xamarin Studio 和用 C# 编写的 Xamarin for Android。

尽管 SimpleCursorAdapter 看起来可以容纳多个字段,但当绑定到 SimpleListItem 等内容时,仅使用一个字段。

我第一次尝试这个:

        string[] fromColumns = new string[]{ "checkListName","checkListDesc" };
        int[] toControlIDs = new int[] {Android.Resource.Id.Text1, Android.Resource.id.Text1};

        try{
            listView.Adapter = new SimpleCursorAdapter(this,Android.Resource.Layout.SimpleListItem1 , c, fromColumns, toControlIDs, 0);         
        }
        catch(SQLiteException e){
            Console.WriteLine ("whoops, " + e.Message.ToString ());
        }

但我得到的只是光标行中的最后一个字段。

我了解到需要一个自定义列表视图。以下是四个文件的代码文件:

  1. MainActivity.cs
  2. myList.xml
  3. Main.axml
  4. PreFloat.cs(这是数据库部分)

我已包含所有这些内容,以提供尽可能接近现实生活的完整工作示例尽可能。

这是 MainActivity.cs,它设置内容视图,使用游标从 SQLite 数据库获取数据,并定义

using System;

using Android.App;
using Android.Content;
using Android.Database;
using Android.Database.Sqlite;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace Darjeeling
{
[Activity (Label = "Darjeeling", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{       

    ListView listView;
    Darjeeling.PreFloatDatabase pdb;
    ICursor c;
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);
        listView = FindViewById<ListView> (Resource.Id.listView1);
        pdb = new PreFloatDatabase (this);
        //  Assign the cursor to a query
        c = pdb.ReadableDatabase.RawQuery ("select * from checkLists", null);
        StartManagingCursor (c);
        // A ListView needs an adapter -- so we'll assign our instantiated listView's adapter to our customized adapter called HomeScreenCursorAdapter.
        listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter (this,c);
    }
    //  End onCreate method

    // This handles the cursor when the user is done with the activity
    protected override void OnDestroy()
    {
        StopManagingCursor(c);
        c.Close ();
        base.OnDestroy();
    }
    //  Here's the magic -- 
    public class HomeScreenCursorAdapter : CursorAdapter {
        Activity context;
        public HomeScreenCursorAdapter(Activity context, ICursor c)
            : base (context, c)
        {
            this.context = context;
        }
        //  This overridden BindView method is going to let me assign TextView controls that I've set up in an XML file, to specific fields in the cursor.  
        public override void BindView(View view, Context context, ICursor cursor)
        {
            var txtCheckListName = view.FindViewById<TextView> (Resource.Id.txtCheckListName); //(Android.Resource.Id.Text1);
            var txtCheckListDesc = view.FindViewById<TextView> (Resource.Id.txtCheckListDesc); //(Android.Resource.Id.Text2); 
//  For testing purposes, I first assigned static values to txtCheckListName and txtCheckListDesc, for instance, txtCheckListName.Text = "Hello";  and txtCheckListDesc.Text = "World"; 
            txtCheckListName.Text = cursor.GetString (3);
            txtCheckListDesc.Text = cursor.GetString (4);
        }
        //  This overridden View inflates each row (I think).  This could inflate a built-in ListView control like SimpleListItem, OR, in this case, it references a custom written XML file called myList.
        public override View NewView(Context context, ICursor cursor, ViewGroup parent)
        {
            return this.context.LayoutInflater.Inflate (Resource.Layout.myList, parent, false);
        }
    }
}

}

这是 Main.axml 文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<ListView
    android:minWidth="25px"
    android:minHeight="25px"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/listView1" />
</LinearLayout>

最后是 myList.xml 文件,它本质上是 ListView 行的定义:

<?xml version="1.0" encoding="utf-8"?>
<!---<FrameLayout   xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:background="#FF0000FF">
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<TextView
    android:id="@+id/txtCheckListName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="" />
<TextView
    android:id="@+id/txtCheckListDesc"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0"
    android:text="" />
</LinearLayout>
<!---</FrameLayout>-->

这是数据库文件:

using System;
using Android.Database.Sqlite;
using Android.Content;

namespace Darjeeling {
class PreFloatDatabase : SQLiteOpenHelper {
    public static readonly string create_checkLists_table = "create table if   not exists checkLists([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,  checkListID INTEGER, checkListType INTEGER, checkListName TEXT, checkListDesc TEXT);";
    public static readonly string DatabaseName = "prefloat.db";
    public static readonly int DatabaseVersion = 1;
    public PreFloatDatabase (Context context) : base (context, DatabaseName, null, DatabaseVersion){        }

    public override void OnCreate(SQLiteDatabase db){
        //  fire the statement that creates the checkLists table
        try{
        db.ExecSQL (create_checkLists_table);           
        //  Now pre-fill the checkLists table
            db.ExecSQL ("insert into checkLists (checkListID, checkListType,  checkListName, checkListDesc) values (0, 0, 'Widgeon','Widgeon Daysailer');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (1, 1, 'Widgeon','Widgeon Daysailer');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (2, 0, 'Bowrider', 'Mo Motor, Mo Fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (3, 1, 'Bowrider', 'Mo Motor, Mo Fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (4, 0, 'HobieCat','Hang yer ass out fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (5, 1, 'HobieCat','Hang yer ass out fun');");
        }
        catch(SQLiteException e){
            Console.WriteLine ("Problem with the database " + e.Message.ToString ());
        }

    }
    public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        throw new NotImplementedException ();
    }

} // matches with class PreFloatDatabase
} // matches with namespace Darjeeling

问题:
SimpleListItem 控件应该拥有多个字段或至多一个复选框控件和标签吗?
应该使用网格控件吗?

替代方案:
与其做所有这些恶作剧,使用 SQL 简单地连接所需的值不是更容易吗?特别是因为协调两个文本控件的位置可能过于复杂。

全面披露:
该代码是我在其他帖子和论坛中阅读的代码的混合体,并根据我自己的特定要求进行了定制。

Finally found a solution. I Had the same question as someone new to Android and Xamarin for Android. To be clear - I'm using Xamarin Studio, and Xamarin for Android written in C#.

Although it seems like the SimpleCursorAdapter can accommodate multiple fields, when binding to something like the SimpleListItem only one field gets used.

I first tried this:

        string[] fromColumns = new string[]{ "checkListName","checkListDesc" };
        int[] toControlIDs = new int[] {Android.Resource.Id.Text1, Android.Resource.id.Text1};

        try{
            listView.Adapter = new SimpleCursorAdapter(this,Android.Resource.Layout.SimpleListItem1 , c, fromColumns, toControlIDs, 0);         
        }
        catch(SQLiteException e){
            Console.WriteLine ("whoops, " + e.Message.ToString ());
        }

But all I ever got was the last field in the cursor row.

I learned that a CUSTOM LISTVIEW was needed. Following are code files for four files:

  1. MainActivity.cs
  2. myList.xml
  3. Main.axml
  4. PreFloat.cs (this is the database part)

I have included all of this to provide as much as possible a completely working sample that is as close to real life as possible.

Here is MainActivity.cs which sets a content view, uses a cursor to get data from a SQLite database, and defines a

using System;

using Android.App;
using Android.Content;
using Android.Database;
using Android.Database.Sqlite;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;

namespace Darjeeling
{
[Activity (Label = "Darjeeling", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{       

    ListView listView;
    Darjeeling.PreFloatDatabase pdb;
    ICursor c;
    protected override void OnCreate (Bundle bundle)
    {
        base.OnCreate (bundle);

        // Set our view from the "main" layout resource
        SetContentView (Resource.Layout.Main);
        listView = FindViewById<ListView> (Resource.Id.listView1);
        pdb = new PreFloatDatabase (this);
        //  Assign the cursor to a query
        c = pdb.ReadableDatabase.RawQuery ("select * from checkLists", null);
        StartManagingCursor (c);
        // A ListView needs an adapter -- so we'll assign our instantiated listView's adapter to our customized adapter called HomeScreenCursorAdapter.
        listView.Adapter = (IListAdapter)new HomeScreenCursorAdapter (this,c);
    }
    //  End onCreate method

    // This handles the cursor when the user is done with the activity
    protected override void OnDestroy()
    {
        StopManagingCursor(c);
        c.Close ();
        base.OnDestroy();
    }
    //  Here's the magic -- 
    public class HomeScreenCursorAdapter : CursorAdapter {
        Activity context;
        public HomeScreenCursorAdapter(Activity context, ICursor c)
            : base (context, c)
        {
            this.context = context;
        }
        //  This overridden BindView method is going to let me assign TextView controls that I've set up in an XML file, to specific fields in the cursor.  
        public override void BindView(View view, Context context, ICursor cursor)
        {
            var txtCheckListName = view.FindViewById<TextView> (Resource.Id.txtCheckListName); //(Android.Resource.Id.Text1);
            var txtCheckListDesc = view.FindViewById<TextView> (Resource.Id.txtCheckListDesc); //(Android.Resource.Id.Text2); 
//  For testing purposes, I first assigned static values to txtCheckListName and txtCheckListDesc, for instance, txtCheckListName.Text = "Hello";  and txtCheckListDesc.Text = "World"; 
            txtCheckListName.Text = cursor.GetString (3);
            txtCheckListDesc.Text = cursor.GetString (4);
        }
        //  This overridden View inflates each row (I think).  This could inflate a built-in ListView control like SimpleListItem, OR, in this case, it references a custom written XML file called myList.
        public override View NewView(Context context, ICursor cursor, ViewGroup parent)
        {
            return this.context.LayoutInflater.Inflate (Resource.Layout.myList, parent, false);
        }
    }
}

}

Here's the Main.axml file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<ListView
    android:minWidth="25px"
    android:minHeight="25px"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/listView1" />
</LinearLayout>

And finally, the myList.xml file which is essentially the definition of the ListView row:

<?xml version="1.0" encoding="utf-8"?>
<!---<FrameLayout   xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:background="#FF0000FF">
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/linearLayout1"
android:minWidth="25px"
android:minHeight="25px">
<TextView
    android:id="@+id/txtCheckListName"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="1"
    android:text="" />
<TextView
    android:id="@+id/txtCheckListDesc"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_weight="0"
    android:text="" />
</LinearLayout>
<!---</FrameLayout>-->

And here's the database file:

using System;
using Android.Database.Sqlite;
using Android.Content;

namespace Darjeeling {
class PreFloatDatabase : SQLiteOpenHelper {
    public static readonly string create_checkLists_table = "create table if   not exists checkLists([_id] INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL UNIQUE,  checkListID INTEGER, checkListType INTEGER, checkListName TEXT, checkListDesc TEXT);";
    public static readonly string DatabaseName = "prefloat.db";
    public static readonly int DatabaseVersion = 1;
    public PreFloatDatabase (Context context) : base (context, DatabaseName, null, DatabaseVersion){        }

    public override void OnCreate(SQLiteDatabase db){
        //  fire the statement that creates the checkLists table
        try{
        db.ExecSQL (create_checkLists_table);           
        //  Now pre-fill the checkLists table
            db.ExecSQL ("insert into checkLists (checkListID, checkListType,  checkListName, checkListDesc) values (0, 0, 'Widgeon','Widgeon Daysailer');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (1, 1, 'Widgeon','Widgeon Daysailer');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (2, 0, 'Bowrider', 'Mo Motor, Mo Fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (3, 1, 'Bowrider', 'Mo Motor, Mo Fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (4, 0, 'HobieCat','Hang yer ass out fun');");
            db.ExecSQL ("insert into checkLists (checkListID, checkListType, checkListName, checkListDesc) values (5, 1, 'HobieCat','Hang yer ass out fun');");
        }
        catch(SQLiteException e){
            Console.WriteLine ("Problem with the database " + e.Message.ToString ());
        }

    }
    public override void OnUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){
        throw new NotImplementedException ();
    }

} // matches with class PreFloatDatabase
} // matches with namespace Darjeeling

Questions:
SHOULD a SimpleListItem control have more than a single field or at most a checkbox control and label?
Should a grid control be used instead?

Alternatives:
Instead of doing all these shenanigans, wouldn't it be easier to simple concatenate the needed values using SQL? Especially since coordinating the positioning of two text controls might be too complicated.

Full Disclosure:
This code is an amalgam of code I read in other posts and forums, and customized to fit my own particular requirements.

乖乖兔^ω^ 2024-12-18 08:06:52

列表视图中的每个项目都是从布局文件中扩充的。在布局文件中,您可以添加四个相互水平对齐的textview。有关更多信息,您需要关注 EfficientAdapter,它会导致自定义 ListView。

Each item in the listview is inflated from a layout file. In the layout file, you can add four textview horizontally align to each other. For more information you need to focus on EfficientAdapter which leads to custom ListView.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文