如何根据设备有效地改变布局

Posted

技术标签:

【中文标题】如何根据设备有效地改变布局【英文标题】:How to efficiently change layout based on device 【发布时间】:2019-02-02 06:30:22 【问题描述】:

对我的活动 lst 项使用相同的点击事件来调整布局的最有效方法是什么?我只见过this 和this,但它们并没有完全解决问题。

当前电话代码 XML (activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<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_
    android:layout_
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/my_listView"
        android:layout_
        android:layout_ />

</RelativeLayout>

Java

public class MainActivity extends Activity implements MyRecyclerViewAdapterGL.ItemClickListener, MyRecyclerViewAdapterLL.ItemClickListener 

    MyRecyclerViewAdapterGL adapterGL;
    MyRecyclerViewAdapterLL adapterLL;

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // data to populate the RecyclerView with
        String[] dataArray = "Item A", "Item B", "Item C", "Item D" ,"Item E" ,"Item F";


        // set up the RecyclerView (phones)
        RecyclerView recyclerViewLL = findViewById(R.id.recyclerView_list);
        recyclerViewLL.setLayoutManager(new LinearLayoutManager(this));
        adapterLL = new MyRecyclerViewAdapterLL(this, dataArray);
        adapterLL.setClickListener(this);
        recyclerViewLL.addItemDecoration(new DividerItemDecoration(this, LinearLayout.VERTICAL));
        recyclerView.setAdapter(adapterLL);


        // set up the RecyclerView (sw600dp)
        RecyclerView recyclerViewGL = findViewById(R.id.recyclerView_list);
        int numberOfColumns = 2;
        recyclerViewGL.setLayoutManager(new GridLayoutManager(this, numberOfColumns));
        adapterGL = new MyRecyclerViewAdapterGL(this, dataArray);
        adapterGL.setClickListener(this);
        recyclerViewGL.setAdapter(adapterGL);
    

    @Override
    public void onItemClick(View view, int position) 
    

当前电话结果

以前使用的平板电脑代码(sw600dp/activity_main.xml)

<?xml version="1.0" encoding="utf-8"?>
<TableLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/listview_main"
    android:layout_
    android:layout_
    android:gravity="center"
    android:stretchColumns="*"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin">
    <TableRow
        android:id="@+id/MainActivity_tableRow0"
        android:layout_
        android:layout_
        android:layout_marginBottom="20dp" >


        <Button
            android:id="@+id/MainActivity_btn0"
            android:layout_column="0"
            android:layout_
            android:layout_
            android:layout_marginEnd="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item A"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />

        <Button
            android:id="@+id/MainActivity_btn1"
            android:layout_column="1"
            android:layout_
            android:layout_
            android:layout_marginStart="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item B"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />
    </TableRow>

    <TableRow
        android:id="@+id/MainActivity_tableRow1"
        android:layout_
        android:layout_
        android:layout_marginBottom="20dp" >

        <Button
            android:id="@+id/MainActivity_btn2"
            android:layout_column="0"
            android:layout_
            android:layout_
            android:layout_marginEnd="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item C"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />

        <Button
            android:id="@+id/MainActivity_btn3"
            android:layout_column="1"
            android:layout_
            android:layout_
            android:layout_marginStart="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item D"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />
    </TableRow>

    <TableRow
        android:id="@+id/MainActivity_tableRow2"
        android:layout_
        android:layout_ >

        <Button
            android:id="@+id/MainActivity_btn4"
            android:layout_column="0"
            android:layout_
            android:layout_
            android:layout_marginEnd="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item E"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />

        <Button
            android:id="@+id/MainActivity_btn5"
            android:layout_column="1"
            android:layout_
            android:layout_
            android:layout_marginStart="10dp"
            android:gravity="start|center_vertical"
            android:padding="30dp"
            android:text="Item G"
            android:textAllCaps="false"
            android:textColor="?android:attr/textColorPrimary"
            style="@style/TextAppearance.AppCompat.Large"
            />
    </TableRow>
</TableLayout>

预期的平板电脑结果

当前平板电脑结果

values/bools.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="my_boolean_value">true</bool>
</resources>

values-sw600dp/bools.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <bool name="my_boolean_value">true</bool>
</resources>

【问题讨论】:

有什么问题? @GeorgeArokiam 根据屏幕宽度更改布局并使用相同的点击事件 如果你使用 RecyclerView,你甚至不需要两个布局文件,但是你可以设置两个不同的 LayoutManagers(LinearLayout 和 GridLayout),这取决于一些(布尔)资源在 res/values 和 res /values-sw600dp @0X0nosugar 有这方面的例子吗? 我找到了这些:https://developer.android.com/guide/topics/resources/more-resources#Bool, https://***.com/a/40587169/5015207 【参考方案1】:

您可以将RecyclerView 与两个不同的LayoutManagers(LinearLayoutGridLayout)一起使用。 为了确定设备的大小,您需要评估一个布尔资源,根据屏幕大小为其提供不同的值。

res/values/bools.xml

<bool name="is_screen_small">true</bool>

res/values-sw600dp/bools.xml

<bool name="is_screen_small">false</bool>

onCreate() 中,您使用boolean 变量来检索值,如下所示:

boolean isScreenSmall = getResources().getBoolean(R.bool.is_screen_small);

由于运行时会将正确的值传递给您,您可以使用它来设置RecyclerView 和正确的LayoutManager

RecyclerView recyclerView = findViewById(R.id.recyclerView_list);
LayoutManager layoutManager;
if(isScreenSmall)
    layoutManager = new LinearLayoutManager(this);
    // maybe use special ItemDecoration for small devices

else
    int numberOfColumns = 2;
    layoutManager = new GridLayoutManager(this, numberOfColumns);
    // maybe use special ItemDecoration for large devices

recyclerView.setLayoutManager(layoutManager);
MyAdapter adapter = new MyAdapter(this, dataArray);
adapter.setClickListener(this);
recyclerView.setAdapter(adapter);

请注意,我对两种屏幕尺寸都使用了相同的 RecyclerViewRecyclerView.Adapter。如果我可以保证列表项不会变得太宽(许多列表都是这种情况),这将起作用。

由于“正常”屏幕可能只有320dp 宽,并且应该为16dp 的左右边距留出空间(“应该”因为material design guidelines),所以列表项不应宽于288dp 无论如何。但是在屏幕宽度为600dp 的设备上,必须使用更宽的边距(24dp),因此应该将列表项的最大宽度设为270dp,然后它们也将适合GridLayout两列

您还可以避免使用大量布局文件,而是通过为不同的屏幕尺寸提供不同的尺寸值(用于边距、填充、宽度、高度等)对布局进行微调。

【讨论】:

以上是关于如何根据设备有效地改变布局的主要内容,如果未能解决你的问题,请参考以下文章

如何在android中为不同的设备和方向创建不同的布局[重复]

如何设置横向模式或纵向模式的应用程序控件?

当项目具有动态高度时,如何根据设备方向创建动态颤动网格布局

如何根据 cellForRowAtIndexPath 中的设备获取单元格宽度。我使用自动布局和 UITableViewAutomaticDimension

如何根据自适应布局和情节提要使 uitableviewcell 中的 uilabel 相对于设备进行包装

在情节提要中,您可以只为一台设备编辑布局吗?