更改ListView的高度会破坏对齐

时间:2016-06-29 13:22:45

标签: java android listview android-fragments

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

这是我的片段的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个ListViews,以便它们可以作为一个整体单独控制。我在这里做错了吗?

1 个答案:

答案 0 :(得分:0)

我认为你可以用xml实现这一点,没有动态调整大小!

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

您需要做的就是将顶级布局更改为LinearLayout(垂直方向),将图像视图放在LinearLayout(水平方向)内,更改视图的某些高度并添加{{ 3}}属性到你将创建的两个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。我在列表视图中设置了背景,以便我可以轻松查看没有数据的大小,确保删除它们)。

PPS:请注意,此方法允许您删除许多具有顶级相对布局的布局定位属性!这不仅可以提高代码的清洁度,还可以提高用户界面的效率(layout_weight)。