Wednesday, February 24, 2016

Common template for any android project (Multi screens support)

OutDated : Do not use this! There are better ways which android OS provides.

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 :-) ......

1 comment:

  1. Great articles and great layout. Your blog post deserves all of the positive feedback it’s been getting.
    Android Wear

    ReplyDelete