首页 > 解决方案 > 将视图动态添加到自定义 ListView 项目布局不起作用

问题描述

我希望为每个 ListView 项目添加一个定制的布局。我在 ListView 项目布局的 xml 布局文件中有一个空的线性布局。它具有水平方向。

我希望将三个 FrameLayout 动态添加到上述 LinearLayout 并为每个 FrameLayout 设置自定义权重。

我找到了解决方案的一部分,如下面的代码所示。必须更新 ListView 时会出现问题。ListView 最初是隐藏的。当按下某个按钮时,ListView 得到更新(散列图被清除,然后用新的数据集填充)并且它的可见性设置从 GONE 到 VISIBLE。接下来是遍历所有项目并以编程方式添加设计视图。

如果我在更新 ListView 项目后立即调用该方法add_designed_views(null);,则应用程序会遍历项目,创建所有新视图并将它们添加到正确的项目中。但是,它们没有被添加。我知道这一点是因为检查该项目是否已添加,如果我连续多次调用此方法,它每次都会执行相同的操作,就好像它根本没有添加任何东西一样。

我尝试的下一件事是通过调用虚拟按钮的方法add_designed_views来推迟动态添加视图。onClick当我看到列表已加载(没有自定义视图)时,我按下虚拟按钮并出现自定义视图。但是每 6 个都不见了。如果我再次按下它,就会出现丢失的那些。这让我更加困惑。

很明显,更改ListView的可见性后不能立即添加视图。可能是因为系统需要一些时间来填充 ListView,或者它执行了一些后台任务,但我找不到任何侦听器或某些函数告诉我它已完成加载,以便我可以添加我的视图。

自定义 ListView 项目布局(xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:minHeight="110dp"
    android:background="@drawable/textview_border_dark_line"
    android:orientation="horizontal">

    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="21"
        android:minHeight="40dp">
        <TextView
            android:id="@+id/text1"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="#000000"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:paddingTop="15dp"
            />
    </RelativeLayout>
    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="70"
        android:minHeight="90dp"
        android:orientation="vertical">
        <LinearLayout
            android:id="@+id/path_model"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="50"
            android:orientation="horizontal"
            android:onClick="onClick_listItem"
            >
        <!-- Path Model. -->
        <!-- This is where I add view dynamically. -->

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="40"
            android:orientation="vertical">
            <TextView
                android:id="@+id/text2"
                android:textSize="12dp"
                android:textColor="#454545"
                android:layout_width="wrap_content"
                android:layout_height="0dp"
                android:layout_weight="50"
                android:layout_centerInParent="true"
                android:layout_centerHorizontal="true" />
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="50"
                android:orientation="horizontal">
                <RelativeLayout
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_weight="10">
                    <ImageView
                        android:id="@+id/ic_time"
                        android:layout_width="16dp"
                        android:layout_height="16dp"
                        android:src="@drawable/clock"
                        android:layout_centerVertical="true" />
                    <TextView
                        android:id="@+id/text4_1"
                        android:textSize="14dp"
                        android:textColor="#454545"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_weight="50"
                        android:layout_centerVertical="true"
                        android:layout_toRightOf="@id/ic_time" />
                </RelativeLayout>

                <RelativeLayout
                    android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="10">
                <ImageView
                    android:id="@+id/ic_changes"
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:src="@drawable/change"
                    android:layout_centerVertical="true"/>
                <TextView
                    android:id="@+id/text4_2"
                    android:textSize="14dp"
                    android:textColor="#454545"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="50"
                    android:layout_centerVertical="true"
                    android:layout_toRightOf="@id/ic_changes"
                    />
            </RelativeLayout>
            <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="10">
                <ImageView
                    android:id="@+id/ic_cost"
                    android:layout_width="16dp"
                    android:layout_height="16dp"
                    android:src="@drawable/coins"
                    android:layout_centerVertical="true"/>
                <TextView
                    android:id="@+id/text4_3"
                    android:textSize="14dp"
                    android:textColor="#454545"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_weight="50"
                    android:layout_centerVertical="true"
                    android:layout_toRightOf="@id/ic_cost"
                    />
            </RelativeLayout>
            <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_weight="10">
            </RelativeLayout>

        </LinearLayout>
    </LinearLayout>

    </LinearLayout>
    <RelativeLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="21"
        android:minHeight="38dp">
        <TextView
            android:id="@+id/text3"
            android:textSize="16sp"
            android:textStyle="bold"
            android:textColor="#000000"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="10dp"
            android:paddingTop="15dp"
            />
    </RelativeLayout>

</LinearLayout>

add_design_views 方法(Java):

public void add_designed_views(View view)
{
    for(int i=0; i<hashmap_search_results_list.size(); i++)
    {
        /* Check if it is already added. We have to check,
           because we run it twice in consecutive order. */
        LinearLayout listView_item = (LinearLayout)getViewByPosition(i, listView_search_results);
        View middle_ground = ((ViewGroup) listView_item).getChildAt(1);

        LinearLayout path_model = (LinearLayout) ((ViewGroup) middle_ground).getChildAt(0);
        LinearLayout already_added_ll_path = (LinearLayout)((ViewGroup)path_model).getChildAt(0);
        if(already_added_ll_path != null)
        {
            Log.d(TAG, "Already has linear layout: " + hashmap_search_results_list.get(i).get("latest_departure_time"));
            continue;
        }

        Log.d(TAG, "Doing: " + hashmap_search_results_list.get(i).get("latest_departure_time"));

        Search_Result_Item result_item = (Search_Result_Item)search_results_list.get(i);

        /* How to access each view at each item position in list view. */
        //LinearLayout listView_item = (LinearLayout) getViewByPosition(i, listView_search_results);
        //View middle_ground = ((ViewGroup) listView_item).getChildAt(1);
        //LinearLayout path_model = (LinearLayout) ((ViewGroup) middle_ground).getChildAt(0);

        /* Setting the proportions of lines regarding walking time and riding time. */
        HrMin hrmin_walking_to_entrance_time = result_item.walking_to_entrance_time();
        HrMin hrmin_riding_time = result_item.travel_time();
        HrMin hrmin_walking_from_exit_time = result_item.walking_from_exit_time();

        int int_walking_to_entrance_time = hrmin_get_minutes(hrmin_walking_to_entrance_time);
        int int_riding_time = hrmin_get_minutes(hrmin_riding_time);
        int int_walking_from_exit_time = hrmin_get_minutes(hrmin_walking_from_exit_time);
        int total = int_walking_to_entrance_time +
                int_riding_time +
                int_walking_from_exit_time;

        float weight_walking_to_entrance = (float)int_walking_to_entrance_time/total;
        float weight_bus_ride = (float)int_riding_time/total;
        float weight_walking_from_exit = (float)int_walking_from_exit_time/total;

        /* How to add a new layout, view to existing layout. */
        LinearLayout ll_path = new LinearLayout(this);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
                (LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);

        /* Pedestrian image. */
        ImageView pedestrian = new ImageView(this);
        pedestrian.setBackground(getResources().getDrawable(R.drawable.runner_rnd));

        int dimensionInPixel = 16;
        int dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams pedestrian_params = new FrameLayout.LayoutParams(
                dimensionInDp,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        pedestrian.setLayoutParams(pedestrian_params);

        /* Gray Line. */
        FrameLayout frameLayout_pedestrian_container = new FrameLayout(this);
        LinearLayout.LayoutParams frame_layout_params = new LinearLayout.LayoutParams(
                0,
                LinearLayout.LayoutParams.MATCH_PARENT,
                weight_walking_to_entrance);

        View gray_line = new View(this);
        gray_line.setBackground(getResources().getDrawable(R.drawable.horizontal_gray_line));

        dimensionInPixel = 4;
        dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams gray_line_params = new FrameLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        gray_line.setLayoutParams(gray_line_params);

        frameLayout_pedestrian_container.addView(gray_line);
        frameLayout_pedestrian_container.addView(pedestrian);
        frameLayout_pedestrian_container.setLayoutParams(frame_layout_params);
        ll_path.addView(frameLayout_pedestrian_container);

        /* Bus image. */
        FrameLayout frameLayout_bus_container = new FrameLayout(this);
        LinearLayout.LayoutParams frame_layout_bus_params = new LinearLayout.LayoutParams(
                0,
                LinearLayout.LayoutParams.MATCH_PARENT,
                weight_bus_ride);

        ImageView bus = new ImageView(this);
        bus.setBackground(getResources().getDrawable(R.drawable.bus_rnd));

        dimensionInPixel = 17;
        dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams bus_params = new FrameLayout.LayoutParams(
                dimensionInDp,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        bus.setLayoutParams(bus_params);

        /* Green line. */
        View green_line = new View(this);
        green_line.setBackground(getResources().getDrawable(R.drawable.horizontal_green_line));

        dimensionInPixel = 4;
        dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams green_line_params = new FrameLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        green_line.setLayoutParams(green_line_params);

        frameLayout_bus_container.addView(green_line);
        frameLayout_bus_container.addView(bus);
        frameLayout_bus_container.setLayoutParams(frame_layout_bus_params);
        ll_path.addView(frameLayout_bus_container);

        /* Walking from exit path. */
        ImageView pedestrian2 = new ImageView(this);
        pedestrian2.setBackground(getResources().getDrawable(R.drawable.runner_rnd));

        dimensionInPixel = 16;
        dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams pedestrian_params2 = new FrameLayout.LayoutParams(
                dimensionInDp,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        pedestrian2.setLayoutParams(pedestrian_params2);

        /* Gray Line. */
        FrameLayout frameLayout_pedestrian_container2 = new FrameLayout(this);
        LinearLayout.LayoutParams frame_layout_params2 = new LinearLayout.LayoutParams(
                0,
                LinearLayout.LayoutParams.MATCH_PARENT,
                weight_walking_from_exit);

        View gray_line2 = new View(this);
        gray_line2.setBackground(getResources().getDrawable(R.drawable.horizontal_gray_line));

        dimensionInPixel = 4;
        dimensionInDp = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dimensionInPixel, getResources().getDisplayMetrics());
        FrameLayout.LayoutParams gray_line_params2 = new FrameLayout.LayoutParams(
                LinearLayout.LayoutParams.MATCH_PARENT,
                dimensionInDp,
                Gravity.CENTER_VERTICAL);
        gray_line2.setLayoutParams(gray_line_params2);

        frameLayout_pedestrian_container2.addView(gray_line2);
        frameLayout_pedestrian_container2.addView(pedestrian2);
        frameLayout_pedestrian_container2.setLayoutParams(frame_layout_params2);
        ll_path.addView(frameLayout_pedestrian_container2);


        ll_path.setLayoutParams(params);
        ll_path.setOrientation(LinearLayout.HORIZONTAL);
        path_model.addView(ll_path);
    }
}

我更新 ListView 并显示它的部分:

search_results.setVisibility(View.VISIBLE);

ListView 是两种布局的子视图:

<LinearLayout
    android:id="@+id/search_results"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white"
    android:visibility="gone"
    android:paddingTop="140dp"
    android:orientation="vertical"
    android:onClick="onClick_nothing">
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/search_options_list"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="@+id/mapView"
        app:layout_constraintTop_toTopOf="@+id/mapView"
        android:background="@android:color/white"
        android:orientation="vertical"
        >
        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbarAlwaysDrawVerticalTrack="true"
            android:scrollbarThumbVertical="@android:color/darker_gray"
            />
    </RelativeLayout>

</LinearLayout>

标签: javaandroidandroid-listview

解决方案


有帮助的一件事是Handler.postDelayed()

final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            add_designed_views (null);
        }
    }, 300);

此函数将方法调用延迟 300 毫秒。以编程方式添加的布局是可见的。但是,仍然每 6 次丢失。在我触摸任何项目后,它们也会出现。


推荐阅读