java - 更改 ListView 的高度会破坏对齐方式

标签 java android listview android-fragments

我在 ViewPager 中有一个 fragment ,并尝试根据屏幕的大小动态更改 ListView 的高度。

这是我的 fragment 的 xml 代码:

fragment .xml

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <RelativeLayout
        android:id="@+id/rlDiscoveredDevice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@+id/tvSuggestBTOn">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvDiscoveredDevices"
            android:layout_alignParentTop="true"
            android:layout_alignParentStart="true"
            android:text="@string/text_list_discovered_devices"
            />

        <ProgressBar
            android:id="@+id/pbDiscoveredDevices"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toEndOf="@+id/tvDiscoveredDevices"
            android:layout_marginStart="16dp"
            />

        <ListView
            android:id="@+id/lstDiscoveredBTDevices"
            android:layout_height="250dp"
            android:layout_width="wrap_content"
            android:divider="@android:color/transparent"
            android:dividerHeight="@dimen/list_view_divider_height"
            android:choiceMode="singleChoice"
            android:listSelector="@color/list_item_selected"
            android:layout_below="@+id/tvDiscoveredDevices"
            android:layout_marginTop="@dimen/list_view_margin_top"
            />

    </RelativeLayout>

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/pairBT"
        android:background="@drawable/ic_action_down"
        android:layout_marginStart="134dp"
        android:layout_below="@+id/rlDiscoveredDevice"
        android:layout_alignParentStart="true"
        />

    <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/unpairBT"
        android:background="@drawable/ic_action_up"
        android:layout_below="@+id/rlDiscoveredDevice"
        android:layout_toEndOf="@+id/pairBT"
        android:layout_marginStart="73dp"
         />

    <RelativeLayout
        android:id="@+id/rlPairedDevice"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/pairBT">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvPairedDevices"
            android:text="@string/text_list_paired_devices"
            android:layout_alignParentStart="true"
            />

        <ListView
            android:id="@+id/lstPairedBTDevices"
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            android:divider="@android:color/transparent"
            android:dividerHeight="@dimen/list_view_divider_height"
            android:choiceMode="singleChoice"
            android:listSelector="@color/list_item_selected"
            android:layout_below="@+id/tvPairedDevices"
            android:layout_alignParentStart="true"
            android:layout_marginTop="@dimen/list_view_margin_top"
            />

    </RelativeLayout>

</RelativeLayout>

这是我用来动态更改高度的 java 代码:

DiscoveredDevice.java

public class DiscoveredDevice extends Fragment{
    final String TAG = "DiscoverDevice Fragment";
    private SharedPreferences appPrefs;
    private BTActions btActions;
    private ArrayList<BluetoothDevice> arrDiscoveredDevicesList;
    private Set<BluetoothDevice> arrPairedDevicesList;
    private ArrayAdapter<String> btDiscListArrayAdapter;
    private ArrayAdapter<String> btPairedListArrayAdapter;
    private String strDiscoveredListItemSelected = "";
    private String strPairedListItemSelected = "";
    private CommonFunctions cf;
    private boolean blnIsFragmentLoaded = false;

    // UI Objects
    private TextView tvDiscoveredDevices;
    private TextView tvPairedDevices;
    private ListView lvDiscoveredList;
    private ListView lvPairedDevicesList;
    private ImageButton ibtnPair;
    private ImageButton ibtnUnPair;
    private ProgressBar pbDiscDevicesSpinner;
    private TextView tvSuggestBTOn;
    private ProgressBar pbLoading;

    public DiscoveredDevice() {
        btActions = new BTActions();
        cf = new CommonFunctions();
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "Begin render of Discovered Device fragment...");
        super.onCreate(savedInstanceState);

        // Define variables
        appPrefs = this.getActivity().getPreferences(Context.MODE_PRIVATE);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_discovered_device, container, false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        // Define the lists on DiscoveredDevice fragment
        btDiscListArrayAdapter = new ArrayAdapter<>(getContext(), R.layout.simple_row, R.id.simple_row_Txt);
        btPairedListArrayAdapter = new ArrayAdapter<>(getContext(), R.layout.simple_row, R.id.simple_row_Txt);

        // Define UI Objects
        defineUIObjects();

        // Position UI objects
        positionUIObjects();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
    }

    private void defineUIObjects() {
        tvDiscoveredDevices = (TextView) getView().findViewById(R.id.tvDiscoveredDevices);
        tvPairedDevices = (TextView) getView().findViewById(R.id.tvPairedDevices);
        lvDiscoveredList = (ListView) getView().findViewById(R.id.lstDiscoveredBTDevices);
        lvPairedDevicesList = (ListView) getView().findViewById(R.id.lstPairedBTDevices);
        ibtnPair = (ImageButton) getView().findViewById(R.id.pairBT);
        ibtnUnPair = (ImageButton) getView().findViewById(R.id.unpairBT);
        tvSuggestBTOn = (TextView) getView().findViewById(R.id.tvSuggestBTOn);
        pbDiscDevicesSpinner = (ProgressBar) getView().findViewById(R.id.pbDiscoveredDevices);

        pbLoading = (ProgressBar) getView().findViewById(R.id.spin_kit_progress);
        pbLoading.setIndeterminateDrawable(new DoubleBounce());
    }

    private void positionUIObjects() {
        final ViewGroup vgDiscDevice = (ViewGroup) getView().findViewById(R.id.rlDiscoveredDevice);
        final AtomicInteger aiLayoutHeight = new AtomicInteger();

        Rect rect = new Rect();

        // Get the window
        Window win = getActivity().getWindow();
        win.getDecorView().getWindowVisibleDisplayFrame(rect);

        // Find height of AppBarLayout
        AppBarLayout ablTabs = (AppBarLayout) getActivity().findViewById(R.id.ablTabs);

        // Obtain the screen height & width
        DisplayMetrics metrics = new DisplayMetrics();
        getActivity().getWindowManager().getDefaultDisplay().getMetrics(metrics);
        int intScreenHeight = metrics.heightPixels;
        int intScreenWidth = metrics.widthPixels;
        Log.i(TAG, "Actual Screen Height = " + intScreenHeight + " Width = " + intScreenWidth);

        // Set the height for Discovered Devices list
        RelativeLayout.LayoutParams rlParams = (RelativeLayout.LayoutParams) getView().findViewById(R.id.rlDiscoveredDevice).getLayoutParams();

        // Get height of Discovered Devices relative layout
        int intDiscoveredDevicesRLHeight = (int)(Math.round((intScreenHeight - rect.top - ablTabs.getMeasuredHeight()) * 0.45));
        Log.i(TAG, "Setting the height of Discovered Devices Relative layout as '" + intDiscoveredDevicesRLHeight + "'");
        rlParams.topMargin = ablTabs.getMeasuredHeight();
        rlParams.leftMargin = 50; // I DID THIS JUST TO CHECK IF THE LEFT MARGIN GETS MOVED TO THE RIGHT. THIS IS WHERE I NEED A BETTER WAY TO PROPERLY ALIGN THE LIST
        rlParams.height = intDiscoveredDevicesRLHeight;

        lvDiscoveredList.setLayoutParams(rlParams);

    }

我希望每个列表占据屏幕的 45%(不包括 AppBarLayout)。如果您看到下面的屏幕截图,当我设置新高度时,ListView 会失去对齐状态,并且它的一部分会被剪切到屏幕左侧。我已将左边距设置为 50 以使其可见。

[截图]

enter image description here

我在RelativeLayouts中放置了2个ListView,这样它们就可以作为一个整体单独控制。我在这里做错了什么吗?

最佳答案

我认为您只需使用 xml 即可实现此目的,无需动态调整大小!

在您的帖子中,您提到您希望每个 ListView 占据可用高度的 45%。因此,我假设 ImageView 的中心内容将占据高度的 10%(尽管如果它们具有固定高度,这种方法也适用,我也会在底部包含该答案。

您需要做的就是将顶级布局更改为 LinearLayout (具有垂直方向),将 ImageView 放入 LinearLayout (具有水平方向),更改 View 的一些高度并添加 layout_weight您将创建的两个RelativeLayouts 和内部LinearLayout 的属性。以下是 xml 的示例:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">

    <RelativeLayout
        android:id="@+id/rlDiscoveredDevice"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_above="@+id/tvSuggestBTOn"
        android:layout_weight="9">

        <TextView
            android:id="@+id/tvDiscoveredDevices"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:text="@string/text_list_discovered_devices"
            />

        <ProgressBar
            android:id="@+id/pbDiscoveredDevices"
            style="?android:attr/progressBarStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_toEndOf="@+id/tvDiscoveredDevices"
            />

        <ListView
            android:id="@+id/lstDiscoveredBTDevices"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/tvDiscoveredDevices"
            android:divider="@android:color/transparent"
            android:dividerHeight="@dimen/list_view_divider_height"
            android:choiceMode="singleChoice"
            android:listSelector="@color/list_item_selected"
            android:background="@drawable/abc_list_selector_disabled_holo_dark"
            />

    </RelativeLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:gravity="center"
        android:layout_weight="2">

        <ImageButton
            android:id="@+id/pairBT"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/ic_action_down"
            />

        <ImageButton
            android:id="@+id/unpairBT"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/ic_action_up"/>
    </LinearLayout>

    <RelativeLayout
        android:id="@+id/rlPairedDevice"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="9">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/tvPairedDevices"
            android:text="@string/text_list_paired_devices"
            android:layout_alignParentStart="true"
            />

        <ListView
            android:id="@+id/lstPairedBTDevices"
            android:layout_height="match_parent"
            android:layout_width="match_parent"
            android:divider="@android:color/transparent"
            android:dividerHeight="@dimen/list_view_divider_height"
            android:choiceMode="singleChoice"
            android:listSelector="@color/list_item_selected"
            android:layout_below="@+id/tvPairedDevices"
            android:layout_alignParentStart="true"
            android:background="@drawable/abc_list_selector_disabled_holo_dark"
            />

    </RelativeLayout>

</LinearLayout>

这里需要注意的重要一点是,RelativeLayouts 现在的权重均为 9,中心线性布局的权重为 2。因此,顶级线性布局中的空间将按该比例划分,RelativeLayouts 将分别获得 45%,LinearLayout 将获得 10%。

如果您希望中心的线性布局成为换行内容,而不是占据屏幕的 10%(我建议这样做),那么您可以继续为它分配一个 wrap_content 的高度,并从中删除 layout_weight 属性。然后,顶层 LinearLayout 将在为中心 LinearLayout 分配空间后获取剩余高度,并将其平均分配在两个相对布局之间。

PS:(注意,您可以使用我在此处发布的 xml。我在 ListView 上设置了背景,以便我可以轻松地在没有数据的情况下查看它们的大小,请确保删除这些)。

PPS:请注意,这种方法允许您删除顶级相对布局中的许多布局定位属性!这不仅可以提高代码的简洁性,还可以提高 UI 的性能 ( Relative Layouts are less performant than other view groups, especially when nested )。

关于java - 更改 ListView 的高度会破坏对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38100899/

相关文章:

android - Android 中的警报管理器

c# - Winforms 应用程序在以毫秒为单位接收数据时挂起

android - 更新 CheckBox 项的 ListView 时,是更新单个 View 更好,还是更新 notifyDataSetChanged() 和 invalidateViews()?

android - 如何在同一个 Activity onCreate() 中执行 WebView 和 ListView?

java - 为什么 SQLException 不捕获 SQLiteExcpetion?

java - 在 ExtJS 中显示

android - 低于 Lollipop 的 Android 版本上的 java.lang.NoClassDefFoundError

android - RTSP 播放器性能

java - 为什么 Java 7 为已签名的应用程序请求网络权限?

java - 我可以将来自 Maven 的属性(在 settings.xml 中定义的密码)注入(inject)到我的 Spring 容器中吗?