【问题标题】:Custom ArrayAdapter for binding to ListView recursively用于递归绑定到 ListView 的自定义 ArrayAdapter
【发布时间】:2019-06-18 17:59:51
【问题描述】:

我有一个层次结构的类别列表,我想使用自定义数组适配器在具有递归 ListView 的布局中呈现这些列表。每个类别都可以有任何深度的子类别。

为了简单起见,现在假设类别只有标题和子类别数组(同样只有标题)。在下面的示例中,有 3 个顶级类别。第一个顶级类别有 3 个子类别。第一个子类别又具有 3 个子类别。


    public class MyListActivity : Activity
    {
        protected override void OnCreate(Bundle savedInstanceState)
        {
            base.OnCreate(savedInstanceState);

            SetContentView(Resource.Layout.my_list);


            List<CategoryItem> categories = new List<CategoryItem>();


            categories.Add(new CategoryItem("Category 1"));
            categories.Add(new CategoryItem("Category 2"));
            categories.Add(new CategoryItem("Category 3"));

            categories[0].Children.Add(new CategoryItem("Sub 11"));
            categories[0].Children.Add(new CategoryItem("Sub 12"));
            categories[0].Children.Add(new CategoryItem("Sub 13"));


            categories[0].Children[0].Children.Add(new CategoryItem("Sub Sub 111"));
            categories[0].Children[0].Children.Add(new CategoryItem("Sub Sub 112"));
            categories[0].Children[0].Children.Add(new CategoryItem("Sub Sub 113"));

            ListView listView = FindViewById<ListView>(Resource.Id.listView1);

            CategoryAdaptor adaptor = new CategoryAdaptor(Android.App.Application.Context, categories);

            listView.Adapter = adaptor;

            // Create your application here
        }
    }

这是 listView 的自定义适配器。请注意,它是在 GetView 中递归调用另一个列表视图


    public class CategoryAdaptor : ArrayAdapter<CategoryItem>
    {

        string TAG = "CategoryAdaptor";

        List<CategoryItem> categories;
        Context context;

        public CategoryAdaptor(Context context, List<CategoryItem> categories) : base(context, 0, categories)
        {
            this.context = context;
            this.categories = categories;
        }

        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            Log.Debug(TAG, "GetView called for position - " + position);

            //For now ignore convertView...which is perfectly legal
            var listItem = LayoutInflater.From(context).Inflate(Resource.Layout.category_list_item, parent, false);

            Log.Debug(TAG, "Binding - " + categories[position].Title);

            listItem.FindViewById<TextView>(Resource.Id.textView1).Text = categories[position].Title;


            if (categories[position].Children.Count > 0)
            {
                var childView = listItem.FindViewById<ListView>(Resource.Id.childItems);
                var childAdaptor = new CategoryAdaptor(context, categories[position].Children);
                childView.Adapter = childAdaptor;
            }


            return listItem;

        }

    }

主布局包含一个列表视图。我还删除了布局文件上的所有格式,以减少代码噪音。

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



</LinearLayout>

列表视图中的项目具有自定义适配器设置的以下模板。请注意,这有另一个列表视图,以便可以递归地显示每个类别的子视图。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:text="Small Text"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:minWidth="25px"
        android:minHeight="25px"
        android:id="@+id/textView1" />
    <ListView
        android:minWidth="25px"
        android:minHeight="250px"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/childItems" />
</LinearLayout>

但是,代码似乎没有输出预期的结果。只有子类别中的第一项被渲染,如下图所示。看到它缺少第 2 和第 3 子类别。任何指针将不胜感激。

【问题讨论】:

    标签: android listview xamarin.android


    【解决方案1】:

    设置ListView的Adapter后,ListView的高度是根据ListView的子项重新计算的,所以我们需要将ListView的高度设置为LayoutParams。

    你可以试试下面的代码:

    类实用程序

    public class Utility
    {
        public static void setListViewHeightBasedOnChildren(ListView listView)
        {
            {
                if (listView.Adapter == null)
                {
                    // pre-condition
                    return;
                }
    
                int totalHeight = listView.PaddingTop + listView.PaddingBottom;
                for (int i = 0; i < listView.Count; i++)
                {
                    View listItem = listView.Adapter.GetView(i, null, listView);
                    if (listItem.GetType() == typeof(ViewGroup))
                    {
                        listItem.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
                    }
                    listItem.Measure(0, 0);
                    totalHeight += listItem.MeasuredHeight;
                }
    
                listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1));
            }
        }
    }
    

    并像这样在CategoryAdaptor 中使用它:

    public class CategoryAdaptor: ArrayAdapter<CategoryItem>
    {
        string TAG = "CategoryAdaptor";
    
        List<CategoryItem> categories;
        Context context;
    
        public CategoryAdaptor(Context context, List<CategoryItem> categories) : base(context, 0, categories)
        {
            this.context = context;
            this.categories = categories;
        }
    
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            Log.Debug(TAG, "GetView called for position - " + position);
    
            //For now ignore convertView...which is perfectly legal
            var listItem = LayoutInflater.From(context).Inflate(Resource.Layout.category_list_item, parent, false);
    
            Log.Debug(TAG, "Binding - " + categories[position].Title);
    
            listItem.FindViewById<TextView>(Resource.Id.textView1).Text = categories[position].Title;
    
    
            if (categories[position].Children.Count > 0)
            {
                Log.Info("123456","");
    
                var childView = listItem.FindViewById<ListView>(Resource.Id.childItems);
                var childAdaptor = new CategoryAdaptor(context, categories[position].Children);
                childView.Adapter = childAdaptor;
                 // call method : setListViewHeightBasedOnChildren after you set Adapter
                Utility.setListViewHeightBasedOnChildren(childView);
            }
    
    
            return listItem;
    
        }
    }
    

    效果是:

    【讨论】:

    • 很高兴为您提供帮助。祝您编码愉快。
    猜你喜欢
    • 1970-01-01
    • 2011-12-05
    • 1970-01-01
    • 2013-06-18
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多