Hi All,
As I learn more about android, I have a need to create a common android project so that I can use it to start the future projects which is surly easy my life. Any android project needs to support both phone and tablets for a flexible UI. So we need fragments (as google recommends) and code logic to handle multiple device support.
I'm going to show you my common project to begin for any android project which supports phones and tablets. I created this project referring developer site for android. But here I think my example will easier to read and understand. And yes, I'm still learning android so if you see any issue or things to improve, please comment. I'll really appreciate it.
Here's how my common template look like in phone and tablet.
Let's see the codes. Here's the project structure.
I put comments in the code so it should be self-explanatory.
1. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.sajithkumara.flexibletemplate" >
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >
<activity android:name=".activity.MainActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".activity.BMIActivity"></activity>
<activity android:name=".activity.BMRActivity"></activity>
</application>
</manifest>
2.build.gradle (Module: app)
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.sajithkumara.flexibletemplate"
minSdkVersion 16
targetSdkVersion 22
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:22.2.1'
compile 'com.android.support:cardview-v7:22.2.1'
}
3. MainActivity
package com.sajithkumara.flexibletemplate.activity;
import android.content.Intent;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.FrameLayout;
import com.sajithkumara.flexibletemplate.R;
import com.sajithkumara.flexibletemplate.fragment.BMIFragment;
import com.sajithkumara.flexibletemplate.fragment.BMRFragment;
import com.sajithkumara.flexibletemplate.fragment.MenuFragment;
// this is the first view which includes MenuFragment
public class MainActivity extends AppCompatActivity implements MenuFragment.OnMenuItemSelectedListener {
FrameLayout frameContainer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // there are 2 activity_main.xml files.
// 1 for phones(in layout), a for tablets (in layout-sw600dp)
frameContainer = (FrameLayout) findViewById(R.id.frame_container);
if (frameContainer == null) {
// If we have a phone activity_main.xml in layout folder loads.Do nothing here.
} else {
// If we have a tablet activity_main.xml in layout-sw600dp folder loads.
// load the BMIFragment in the frame_container
BMIFragment sef = new BMIFragment();
changeFragment(sef); // replace the fragments
}
}
@Override
public void onMenuItemSelect(int layoutId) { // Listener interface in MenuFragment
Intent intent = null;
if (frameContainer == null) { // If we have a phone.......
switch (layoutId) { // layoutId pass from MenuFragment
case 1: // if layoutId = 1, load BMIActivity(not BMIFragment)
intent = new Intent(this, BMIActivity.class);
intent.putExtra("layoutId", layoutId);
startActivity(intent);
return;
case 2:// if layoutId = 2, load BMRActivity(not BMRFragment)
intent = new Intent(this, BMRActivity.class);
startActivity(intent);
return;
}
} else { // If we have a tablet.......
switch (layoutId) {
case 1: //load BMIFragment
BMIFragment sef = new BMIFragment();
changeFragment(sef);
return;
case 2: //load BMRFragment
BMRFragment bmiFragment = new BMRFragment();
changeFragment(bmiFragment);
return;
}
}
}
private void changeFragment(Fragment fragment) {
FragmentTransaction fragmentTransaction = null;
fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.frame_container, fragment);
fragmentTransaction.commit();
}
}
4. BMIActivity
package com.sajithkumara.flexibletemplate.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import com.sajithkumara.flexibletemplate.R;
public class BMIActivity extends AppCompatActivity {
// Put all the java controlling code in BMIFragment. No need to code here.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bmi);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
this.finish(); // end this activity and go back
return super.onOptionsItemSelected(item);
}
}
5. BMRActivity
package com.sajithkumara.flexibletemplate.activity;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;
import com.sajithkumara.flexibletemplate.R;
public class BMRActivity extends AppCompatActivity {
// Put all the java controlling code in BMRFragment. No need to code here.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bmr);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
this.finish(); // end this activity and go back
return super.onOptionsItemSelected(item);
}
}
6. MenuFragment
package com.sajithkumara.flexibletemplate.fragment;
import android.app.Activity;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.sajithkumara.flexibletemplate.R;
public class MenuFragment extends Fragment {
private OnMenuItemSelectedListener mListener;
CardView cardViewBMI, cardViewBMR;
public static MenuFragment newInstance(String param1, String param2) {
MenuFragment fragment = new MenuFragment();
return fragment;
}
public MenuFragment() {
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_menu, container, false);
cardViewBMI = (CardView) v.findViewById(R.id.cardBMI);
cardViewBMR = (CardView) v.findViewById(R.id.cardBMR);
cardViewBMI.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onMenuItemSelected(1); // layoutId = 1 to identify BMI card view click
}
});
cardViewBMR.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onMenuItemSelected(2); // layoutId = 2 to identify BMR card view click
}
});
return v;
}
public void onMenuItemSelected(int layoutId) {
if (mListener != null) {
mListener.onMenuItemSelect(layoutId);
}
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mListener = (OnMenuItemSelectedListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnMenuItemSelectedListener");
}
}
@Override
public void onDetach() {
super.onDetach();
mListener = null;
}
public interface OnMenuItemSelectedListener {
public void onMenuItemSelect(int layoutId);
}
}
7. BMIFragment
package com.sajithkumara.flexibletemplate.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.Toast;
import com.sajithkumara.flexibletemplate.R;
public class BMIFragment extends Fragment {
Button btnToast;
public BMIFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_bmi, container, false);
//adding action bar and setting backward navigation
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (getActivity().getClass().getSimpleName().equals("BMIActivity")) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
actionBar.setTitle("BMI Calculator");
btnToast = (Button)v.findViewById(R.id.btnToast);
btnToast.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(),"You clicked toast message button!!!",Toast.LENGTH_SHORT).show();
}
});
return v;
}
}
8. BMRFragment
package com.sajithkumara.flexibletemplate.fragment;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.sajithkumara.flexibletemplate.R;
public class BMRFragment extends Fragment {
public BMRFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v = inflater.inflate(R.layout.fragment_bmr, container, false);
//adding action bar and setting backward navigation
ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar();
if (getActivity().getClass().getSimpleName().equals("BMRActivity")) {
actionBar.setDisplayHomeAsUpEnabled(true);
}
actionBar.setTitle("BMR Calculator");
return v;
}
}
9. activity_main.xml (in layout folder)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.sajithkumara.flexibletemplate.fragment.MenuFragment"
android:id="@+id/menuFragInActivity"
tools:layout="@layout/fragment_menu" />
</RelativeLayout>
10. activity_main.xml (in layout-sw600dp folder)
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context=".MainActivity">
<fragment
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:name="com.sajithkumara.flexibletemplate.fragment.MenuFragment"
android:id="@+id/menu_fragment"
tools:layout="@layout/fragment_menu" />
<FrameLayout
android:id="@+id/frame_container"
android:layout_width="0dp"
android:layout_weight="2"
android:layout_height="match_parent">
</FrameLayout>
</LinearLayout>
11. activity_bmi.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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"
tools:context="com.sajithkumara.flexibletemplate.activity.BMIActivity">
<fragment
android:id="@+id/exersiceFrag"
android:name="com.sajithkumara.flexibletemplate.fragment.BMIFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="@layout/fragment_bmi" />
<!-- Note the layout is fragment_bmi-->
</RelativeLayout>
12. activity_bmr.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
tools:context="com.sajithkumara.flexibletemplate.activity.BMRActivity">
<fragment
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.sajithkumara.flexibletemplate.fragment.BMRFragment"
android:id="@+id/exersiceFrag"
tools:layout="@layout/fragment_bmr"/>
<!-- Note the layout is fragment_bmr-->
</RelativeLayout>
13. fragment_bmi.xml
<FrameLayout 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:background="#95a5a6"
tools:context="com.sajithkumara.flexibletemplate.fragment.BMIFragment">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="Here place the content for BMI calculator"
android:textColor="#fff"
android:textSize="24sp" />
<Button
android:id="@+id/btnToast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Toast Message"
android:layout_gravity="center_horizontal"
android:layout_marginTop="60dp"/>
</FrameLayout>
14. fragment_bmr.xml
<FrameLayout 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"
tools:context="com.sajithkumara.flexibletemplate.fragment.BMRFragment"
android:background="#7f8c8d">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="BMR Calculator goes here.Place the content for BMR calculator"
android:textColor="#fff"
android:textSize="24sp" />
</FrameLayout>
15. fragment_menu.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"
tools:context="com.sajithkumara.flexibletemplate.fragment.MenuFragment">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:id="@+id/cardBMI"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_margin="8dp"
android:background="@android:color/white"
app:cardCornerRadius="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Body Mass Index"
android:textSize="30sp" />
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:id="@+id/cardBMR"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_margin="8dp"
android:background="@android:color/white"
app:cardCornerRadius="4dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Basal Metabolic Rate"
android:textSize="30sp" />
</android.support.v7.widget.CardView>
</LinearLayout>
</RelativeLayout>
You can download from github from https://github.com/SajithKumara/AndroidFlexibleUI.git
Here is a project in playstore which used this template - BMI Calculator .
That's all. Hope it will help to someone. Happy Coding :-) ......