Sunday, April 21, 2013

Handle different layout for phone and tablet, load fragment in Java code vs XML

Last exercise demonstrate to create /res/layout/activity_main.xml for phone, and /res/layout-sw600dp/activity_main.xml for tablet. We are going to handle the layout separately.

In single pane mode run on phone, We have one pane displayed only. We have to switch fragment using Java code programm programmatically; if define in XML we cannot switch fragment later. We have a FrameLayout with id "phone_container" in layout xml. It will be used to determine if it's run on phone or tablet. We will load MyListFragment in onCreate() programmatically.

/res/layout/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Normal" />

<FrameLayout
android:id="@+id/phone_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</FrameLayout>

</LinearLayout>

Run on phone with a ListFragment


In two pane mode, run on tablet. There are two fragments in layout. The fragments are loaded in XML.

/res/layout-sw600dp/activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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"
android:orientation="vertical"
tools:context=".MainActivity" >

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="sw600dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<fragment
android:name="com.example.androiddualmode.MainActivity$MyListFragment"
android:id="@+id/list_fragment"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="1" />
<fragment
android:name="com.example.androiddualmode.MainActivity$MyDetailFragment"
android:id="@+id/detail_fragment"
android:layout_height="match_parent"
android:layout_width="0dp"
android:layout_weight="2" />

</LinearLayout>

</LinearLayout>

Run on tablet with two panes


Create /res/layout/layout_detailfragment.xml, it's a simple layout in the MyDetailFragment.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:id="@+id/title_detailfragment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Detail Fragment"/>

</LinearLayout>


Modify MainActivity.java. Implement inner class of MyListFragment and MyDetailFragment.
package com.example.androiddualmode;

import android.os.Bundle;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;

public class MainActivity extends Activity {

// if run on phone, isSinglePane = true
// if run on tablet, isSinglePane = false
boolean isSinglePane;

static String[] month ={
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December"};

public static class MyListFragment extends ListFragment {

@Override
public void onActivityCreated(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onActivityCreated(savedInstanceState);

ListAdapter myArrayAdapter =
new ArrayAdapter<String>(
getActivity(), android.R.layout.simple_list_item_1, month);
setListAdapter(myArrayAdapter);

}

}

public static class MyDetailFragment extends Fragment {

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
View view = inflater.inflate(R.layout.layout_detailfragment, null);
return view;
}

}

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

View v = findViewById(R.id.phone_container);
if(v == null){
//it's run on tablet
isSinglePane = false;
/*
* MyListFragment and MyDetailFragment have been loaded in XML,
* no need load.
*/

}else{
//it's run on phone
//Load MyListFragment programmatically
isSinglePane = true;

if(savedInstanceState == null){
//if's the first time created
MyListFragment myListFragment = new MyListFragment();
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.add(R.id.phone_container, myListFragment);
fragmentTransaction.commit();
}
}
}

}


download filesDownload the files.

Next:
- Handle onListItemClick() of ListFragment, to pass data between fragment


No comments:

Post a Comment