wbk727
wbk727

Reputation: 8408

How to efficiently change layout based on device

What's the most efficient way to adapt a layout use the same click events for my activity lst items? I have only seen this and this but they don't fully resolve the issue.

Current phone code 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_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ListView
        android:id="@+id/my_listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</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) {
    }
}

Current phone result

enter image description here

Previously used tablet code (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_width="match_parent"
    android:layout_height="match_parent"
    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_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp" >


        <Button
            android:id="@+id/MainActivity_btn0"
            android:layout_column="0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            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_width="0dp"
            android:layout_height="match_parent"
            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_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp" >

        <Button
            android:id="@+id/MainActivity_btn2"
            android:layout_column="0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            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_width="0dp"
            android:layout_height="match_parent"
            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_width="match_parent"
        android:layout_height="wrap_content" >

        <Button
            android:id="@+id/MainActivity_btn4"
            android:layout_column="0"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            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_width="0dp"
            android:layout_height="match_parent"
            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>

Expected tablet result

enter image description here

Current tablet result

enter image description here

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>

Upvotes: 1

Views: 188

Answers (1)

B&#246; macht Blau
B&#246; macht Blau

Reputation: 13019

You can use a RecyclerView with two different LayoutManagers (LinearLayout and GridLayout). In order to determine the size of the device, you will need to evaluate a boolean resource for which you provide different values depending on the screen size.

In res/values/bools.xml

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

In res/values-sw600dp/bools.xml

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

In onCreate(), you use a boolean variable to retrieve the value like this:

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

Since the correct value will be handed to you by the runtime, you can use it to set up the RecyclerView with the correct 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);

Note that I'm using the same RecyclerView and RecyclerView.Adapter for both screen sizes. This will work if I can guarantee that the list items don't get too wide, which is the case for many lists.

Since a "normal" screen may be only 320dp wide and one should leave room for left and right margins of 16dp ("should" because of the material design guidelines), the list items should not be wider than 288dp anyway. But on a device with screen width 600dp, one has to use wider margins (24dp) so one should aim at having list items with a max width of 270dp, then they will also fit into a GridLayout with two columns

You can also avoid having lots of layout files and instead do some fine tuning on your layouts by providing different dimension values (for margins, padding, width, height, etc.) for different screen sizes.

Upvotes: 1

Related Questions