How to create layouts that change according to the phone and Tablet in Android Using Fragments in SDK Less than HoneyComb?

Hello all…..

This is a simple tutorial to show how to create a FLEXIBLE UI for both Phone and Tablets in Android.
In the figure below you can see the result after running this tutorial.

Tablet in LANDSCAPE MODE

Fragments

TABLET IN PORTRAIT MODE

Fragments

TABLET IN PORTRAIT MODE – AFTER CLICKING THE LIST.

Fragments

PHONE IN PORTRAIT MODE

Fragments

PHONE IN LANDSCAPE MODE.

Fragments

This can be achieved through Fragments.
This tutorial will have two parts.
1. In the first part I will show you how to use Fragments from API 11 (Honeycomb) and greater.
2. In the second I will show how to change it to adapt to lower versions from 1.6(Donut) using Google’s supporting Library.

I have already covered the first tutorial here..

http://www.coderzheaven.com/2013/02/17/create-layouts-change-phone-tablet-android-fragments/

Please check it before continue reading this post, because there are only small changes in the first post to make it compatible with the older version of Android.

These are the main changes you have to make.
1. Change all Activity to FragmentActivity and change the import statements like below

import android.app.Activity;
to
import android.support.v4.app.FragmentActivity;

2. Change the imports of Fragment from

import android.app.Fragment;
to
import android.support.v4.app.Fragment;

3. Now in the DetailsActivity.java change this line

getFragmentManager().beginTransaction()
.add(android.R.id.content, details).commit();

To

getSupportFragmentManager().beginTransaction()
.add(android.R.id.content, details).commit();

4. match_parent is not supported in old versions so change all “match_parent” in all layouts to “fill_parent”

5. Optionally You can change the min-sdkversion in Manifest to 5.

Done.

Now you have successfully adapted Fragments to the Older version of Android.

How to create layouts that change according to the phone and Tablet in Android Using Fragments?

Hello all…..

This is a simple tutorial to show how to create a FLEXIBLE UI for both Phone and Tablets in Android.
In the figure below you can see the result after running this tutorial.

Tablet in LANDSCAPE MODE

Fragments

TABLET IN PORTRAIT MODE

Fragments

TABLET IN PORTRAIT MODE – AFTER CLICKING THE LIST.

Fragments

PHONE IN PORTRAIT MODE

Fragments

PHONE IN LANDSCAPE MODE.

Fragments

This can be achieved through Fragments.
This tutorial will have two parts.
1. In the first part I will show you how to use Fragments from API 11 (Honeycomb) and greater.
2. In the second I will show how to change it to adapt to lower versions from 1.6(Donut) using Google’s supporting Library.

First Part ( ONLY for HONEYCOMB and GREATER).
(How to use Fragments from API 11 (Honeycomb) and greater)

First we will start with the layout XML Files.
This layout is for the first left part.

left_panel.xml. (Create this XML inside the res/layout folder)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >


    <fragment
        android:id="@+id/titles"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1"
        class="com.coderzheaven.googlefragment.TitlesFragment" />

</LinearLayout>

Now create the same copy of this XML inside the res/layout-land folder and change it’s contents slightly to this.
Here we have two fragments because this is used for the landscape mode in the tablets.
So Two fragments will be there at the same time in a single activity.
In the above XML this is not the case since there is only one fragment.

left_panel.xml (inside layout-land folder)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal" >

    <fragment
        android:id="@+id/titles"
        android:layout_width="0px"
        android:layout_height="fill_parent"
        android:layout_weight="1"
        class="com.coderzheaven.googlefragment.TitlesFragment" />

    <LinearLayout
        android:id="@+id/details"
        android:layout_width="0px"
        android:layout_height="fill_parent"
        android:layout_weight="2"
        android:background="?android:attr/detailsElementBackground" >
        
        
    </LinearLayout>

</LinearLayout>

The above XML will contain the two layout(fragments) for showing the details while clicking or selecting from the Left Panel for the TABLETS not the PHONES.

So we have to create another XML for showing details in the PHONES.

For that Create a new XML named “details_lay.xml” inside res/layout folder.

details_lay.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >


    <LinearLayout
        android:id="@+id/details"
        android:layout_width="0px"
        android:layout_height="match_parent"
        android:layout_weight="1"
        class="com.coderzheaven.googlefragment.DetailsFragment" />

</LinearLayout>

NOTE the class attribute inside the Fragments. It will be pointing to the Class for corresponding Fragments This is the important part in Fragments.
Make sure you change this to your package name before running your project.

Now we will create another layout for content inside the Details (right Panel).
I am naming it “layout_details_content.xml”.

layout_details_content.xml ( this is simply for showing a textview inside the Right Panel, However you can create this dynamically also)
layout_details_content.xml.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:layout_gravity="center" >

    <TextView
        android:id="@+id/tv1"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:text="test"
        android:gravity="center" />

</LinearLayout>

OK Now all layouts are complete. Now we will go to the JAVA coding Part.

Remember all Fragments are associated with a java class that extends the Fragment Class.
That’s why we can use Fragments anywhere.

Now the MainActivity that launches First.

MainActivity.java

package com.coderzheaven.googlefragment;

import android.app.Activity;
import android.os.Bundle;

public class MainActivity extends Activity {

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

}

The MainActivity has left_panel.xml as layout which will be layout/left_panel.xml in the phones and layout-land/ left_panel.xml in the tablets.
One thing to remember is Tablets will take layout/left_panel.xml while in it’s PORTRAIT mode.

Now we will write the classes for the Fragments.

First we will write class for the List Fragment on the Left.
TitlesFragment.java

package com.coderzheaven.googlefragment;

import android.app.FragmentTransaction;
import android.app.ListFragment;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class TitlesFragment extends ListFragment {
	boolean mDualPane;
	int mCurCheckPosition = 0;

	static String titles[] = { "CoderzHeaven", "Google", "Apple","Android","Microsoft","Samsung" };
 
	@Override 
	public void onActivityCreated(Bundle savedInstanceState) {
		super.onActivityCreated(savedInstanceState);

		// Populate list with our static array of titles.
		setListAdapter(new ArrayAdapter<String>(getActivity(),
				android.R.layout.simple_dropdown_item_1line, titles));

		// Check to see if we have a frame in which to embed the details
		// fragment directly in the containing UI.
		View detailsFrame = getActivity().findViewById(R.id.details);
		mDualPane = detailsFrame != null
				&& detailsFrame.getVisibility() == View.VISIBLE;

		if (savedInstanceState != null) {
			// Restore last state for checked position.
			mCurCheckPosition = savedInstanceState.getInt("curChoice", 0);
		} 

		if (mDualPane) {  
			// In dual-pane mode, the list view highlights the selected item.
			getListView().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
			// Make sure our UI is in the correct state.
			showDetails(mCurCheckPosition);
		}else{
			System.out.println("NOT DUAL");
		}
	}  

	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putInt("curChoice", mCurCheckPosition);
	}

	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		showDetails(position);
	}

	/**
	 * Helper function to show the details of a selected item, either by
	 * displaying a fragment in-place in the current UI, or starting a whole new
	 * activity in which it is displayed.
	 */
	void showDetails(int index) { 
		mCurCheckPosition = index;
		if (mDualPane) {
			// We can display everything in-place with fragments, so update
			// the list to highlight the selected item and show the data.
			getListView().setItemChecked(index, true);

			// Check what fragment is currently shown, replace if needed.
			DetailsFragment details = (DetailsFragment) getFragmentManager()
					.findFragmentById(R.id.details);
			if (details == null || details.getShownIndex() != index) {
				// Make new fragment to show this selection.
				details = DetailsFragment.newInstance(index);

				// Execute a transaction, replacing any existing fragment
				// with this one inside the frame.
				FragmentTransaction ft = getFragmentManager()
						.beginTransaction();
				ft.replace(R.id.details, details);
				ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
				ft.commit();
			}

		} else {
			// Otherwise we need to launch a new activity to display
			// the dialog fragment with selected text.
			Intent intent = new Intent();
			intent.setClass(getActivity(), DetailsActivity.class);
			intent.putExtra("index", index);
			startActivity(intent);
		}
	}
}

Note this Line

View detailsFrame = getActivity().findViewById(R.id.details);
		mDualPane = detailsFrame != null
				&& detailsFrame.getVisibility() == View.VISIBLE;

Since for phones there will not be Details Fragment in the first layout as you see in the phones the layout/left_panel.xml is loaded and it has no DETAIL Fragment.

Now we will write class for the DETAIL Fragment.
DetailsFragment.java

package com.coderzheaven.googlefragment;

import android.app.Fragment;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

public class DetailsFragment extends Fragment {
	/**
	 * Create a new instance of DetailsFragment, initialized to show the text at
	 * 'index'.
	 */
	static int i = 0;

	public static DetailsFragment newInstance(int index) {
		DetailsFragment f = new DetailsFragment();

		// Supply index input as an argument.
		Bundle args = new Bundle();
		args.putInt("index", index);

		i = index;
		f.setArguments(args);

		return f;
	}

	public int getShownIndex() {
		return getArguments().getInt("index", 0);
	}


	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		View v = getActivity().getLayoutInflater().inflate(
				R.layout.layout_details_content, null);
		TextView tv = (TextView)v.findViewById(R.id.tv1);
		tv.setText(TitlesFragment.titles[i].toUpperCase());
		tv.setTextColor(Color.RED);
		tv.setTextSize(25);
		
		return v;
	}
}

Note this fragement is used By phones and TABLETS while in portrait or LANDSCAPE Mode.
Only difference is when in Phone it is not shown at first since it is not present in the first layout.
Then we will check whether it is in the first layout. If it is there then we are in the LANDSCAPE MODE and if it is not present then we are in the portrait mode in PHONES AND TABLETS. So at that time we will start another DetailActivity which will load the DetaisFragment.

This is the line checking whether second fragment is in the layout or not

View detailsFrame = getActivity().findViewById(R.id.details);
		mDualPane = detailsFrame != null
				&& detailsFrame.getVisibility() == View.VISIBLE;

Here is the Second Activity for PHONES AND TABLETS IN THE PORTRAIT MODE.
DetailsActivity.java

package com.coderzheaven.googlefragment;

import android.app.Activity;
import android.app.Fragment;
import android.content.res.Configuration;
import android.os.Bundle;

public class DetailsActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
			setContentView(R.layout.details_lay); 
			return;
		}

		if (savedInstanceState == null) {
			// During initial setup, plug in the details fragment.
			Fragment details = new DetailsFragment();
			details.setArguments(getIntent().getExtras());
			getFragmentManager().beginTransaction()
					.add(android.R.id.content, details).commit();
		}
	}
}

For you understanding I am also pasting the AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.coderzheaven.googlefragment"
    android:versionCode="1"
    android:versionName="1.0" >
  
    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="17" />

    <uses-permission android:name="android.permission.INTERNET"/>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.coderzheaven.googlefragment.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.coderzheaven.googlefragment.DetailsActivity"></activity>
    </application>

</manifest>

How to create Swiping Windows in Android from Android 2.1 onwards?

Have you seen the Google Play application in your Android phone. Wondered about how they implemented swiping windows in it.
Don’t Worry, Here is an example which implements it.

Swipe Fragments in Android

Swipe Fragments in Android

Swipe Fragments in Android

Here we will create three pages which can be swiped to access it.

These are the three layouts for the three sections.

section1.xml


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Layout 1" />

    </LinearLayout>

section2.xml


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Layout 2" />

    </LinearLayout>

section3.xml


    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Layout 3" />

    </LinearLayout>

Now the java for these layouts. These are also similar , only change is the layout.

Page1.java

package com.example.swipewindows;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Page1 extends Fragment {
	Context c;

        public Page1(){
		
	}
	public Page1(Context c) {
		this.c = c;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.section1, null);
		return       v;
	}
}

Page2.java

package com.example.swipewindows;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Page2 extends Fragment {
	Context c;

        public Page2(){
		
	}
	public Page2(Context c) {
		this.c = c;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.section2, null);

		return v;
	}
}

Page3.java

package com.example.swipewindows;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

public class Page3 extends Fragment {
	Context c;

        public Page3(){
		
	}
	public Page3(Context c) {
		this.c = c;
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		View v = inflater.inflate(R.layout.section3, null);

		return v;
	}
}

Now the MainActivity.java that uses these sections to join together.

package com.example.swipewindows;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;

public class MainActivity extends FragmentActivity {

	/**
	 * The android.support.v4.view.PagerAdapter that will provide fragments for
	 * each of the sections. We use a
	 * android.support.v4.app.FragmentPagerAdapter derivative, which will keep
	 * every loaded fragment in memory. If this becomes too memory intensive, it
	 * may be best to switch to a
	 * android.support.v4.app.FragmentStatePagerAdapter.
	 */
	SectionsPagerAdapter mSectionsPagerAdapter;

	/**
	 * The ViewPager that will host the section contents.
	 */
	ViewPager mViewPager;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main_act);
		// Create the adapter that will return a fragment for each of the three
		// primary sections
		// of the app.
		mSectionsPagerAdapter = new SectionsPagerAdapter(this,
				getSupportFragmentManager());

		// Set up the ViewPager with the sections adapter.
		mViewPager = (ViewPager) findViewById(R.id.pager);
		mViewPager.setAdapter(mSectionsPagerAdapter);

	}

	/**
	 * A FragmentPagerAdapter that returns a fragment corresponding to one of
	 * the primary sections of the app.
	 */
	public class SectionsPagerAdapter extends FragmentPagerAdapter {

		Context c;

		public SectionsPagerAdapter(Context c, FragmentManager fm) {
			super(fm);
			this.c = c;
		}

		@Override
		public Fragment getItem(int i) {
			Fragment fragment = null;
			if (i == 0) {
				fragment = new Page1(c);
			}
			if (i == 1) {
				fragment = new Page2(c);
			}
			if (i == 2) {
				fragment = new Page3(c);
			}
			return fragment; 
		}

		@Override
		public int getCount() {
			return 3;
		}

		@Override
		public CharSequence getPageTitle(int position) {
			switch (position) {
			case 0:
				return getString(R.string.title_section1).toUpperCase();
			case 1:
				return getString(R.string.title_section2).toUpperCase();
			case 2:
				return getString(R.string.title_section3).toUpperCase();
			}
			return null;
		}
	}

}

Now the Strings.xml that contains the section titles.

<resources>

    <string name="app_name">SwipeWindows</string>
    <string name="title_section3">Section 3</string>
    <string name="title_section2">Section 2</string>
    <string name="title_section1">       Section 1      </string>
    <string name="hello_world">Hello world!</string>
    <string name="menu_settings">     Settings   </string>
    <string name="title_activity_main">SwipeActivity</string>

</resources>

Download the complete source from here.