Dynamically create Fragments in android with ViewPager
In this article I am going to describe step by step how we can Dynamically create tabs in the android app. Steps involve in achieving the result:
1. Start with creating a new project
2. Define the Database Layer
3. Writing Fragment and Fragment Pager Adapter
4. Update main activity to work with ViewPager
Part 1: Start with creating a new app project
(I am using android studio for development)Click on android studio >
Start a new Android Studio Project >
Specify Project Name, location and Press Next >
Select your appropriate Minimum SDK and click Next >
Select Empty Activity and Press Next >
Specify the Activity name (if required) and Press Finish.
So now we are ready to go.
Part 2: Implementing Database Layer
Contract Class
Our next step is creating a Database layer - why we need Database the answer is we will be fetching the tab details from sqlite database.Create a folder 'Data' under your package folder and then create a class "TabsContract"
Implementing SQLiteOpenHelper Abstract Class
Now create "DBHelper" Class by extending "SQLiteOpenHelper" base class like thisImplementation of onCreate, onUpgrade, and onDowngrade methods:
@Override
public void onCreate(SQLiteDatabase db) {
try{
db.execSQL(CREATE_TABLE_CHANNEL);
}catch (SQLiteException e){
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
try{
db.execSQL(DELETE_TABLE_CHANNEL);
onCreate(db);
}catch (SQLiteException e){
}
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
onUpgrade(db,oldVersion,newVersion);
}
Writing ContentProvider Class
Now create "TabContentProvider" by extending "ContentProvider" base class. when you extends the class android studio will prompt you the missing methods required to be implemented in the newly created class.Here is the actual implementation of the class. declare variables and DBHelper class declaration
private DBHelper mDBHelper;
private static final int TAB = 100;
private static final int TAB_ID = 101;
private static final UriMatcher sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
static {
sUriMatcher.addURI(TabsContract.CONTENT_AUTHORITY, TabsContract.PATH_TAB , TAB);
sUriMatcher.addURI(TabsContract.CONTENT_AUTHORITY, TabsContract.PATH_TAB + "/#", TAB_ID);
}
In onCreate method create the object of DBHelper class
static {
sUriMatcher.addURI(TabsContract.CONTENT_AUTHORITY, TabsContract.PATH_TAB , TAB);
sUriMatcher.addURI(TabsContract.CONTENT_AUTHORITY, TabsContract.PATH_TAB + "/#", TAB_ID);
}
In onCreate method create the object of DBHelper class
@Override
public boolean onCreate() {
mDBHelper = new DBHelper(getContext());
return true;
}
ContentProvider class has four abstract method which allow us to perform CRUD operation on the data, so let define the implementation of those methods
public boolean onCreate() {
mDBHelper = new DBHelper(getContext());
return true;
}
ContentProvider class has four abstract method which allow us to perform CRUD operation on the data, so let define the implementation of those methods
@Nullable
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
SQLiteDatabase db = mDBHelper.getReadableDatabase();
Cursor cursor;
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB:
cursor = db.query(TabsContract.TabsName.TABLE_NAME,projection, selection,selectionArgs, null, null, sortOrder );
break;
case TAB_ID:
cursor = db.query(TabsContract.TabsName.TABLE_NAME,projection,selection,selectionArgs, null, null, sortOrder );
break;
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
@Override
public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
SQLiteDatabase db = mDBHelper.getReadableDatabase();
Cursor cursor;
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB:
cursor = db.query(TabsContract.TabsName.TABLE_NAME,projection, selection,selectionArgs, null, null, sortOrder );
break;
case TAB_ID:
cursor = db.query(TabsContract.TabsName.TABLE_NAME,projection,selection,selectionArgs, null, null, sortOrder );
break;
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
cursor.setNotificationUri(getContext().getContentResolver(),uri);
return cursor;
}
@Override
public String getType(@NonNull Uri uri) {
final int match = sUriMatcher.match(uri);
switch (match) {
case TAB:
return TabsContract.TabsName.CONTENT_LIST_TYPE;
case TAB_ID:
return TabsContract.TabsName.CONTENT_ITEM_TYPE;
default:
throw new IllegalStateException("Unknown URI " + uri + " with match " + match);
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB:
return insertTabDetail(uri,values);
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
}
private Uri insertTabDetail(Uri uri, ContentValues values){
SQLiteDatabase db = mDBHelper.getWritableDatabase();
long id = db.insert(TabsContract.TabsName.TABLE_NAME,null,values);
Uri sUri = ContentUris.withAppendedId(uri,id);
getContext().getContentResolver().notifyChange(uri, null);
return sUri;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
int id;
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB_ID:
id = deleteTabDetail(selection,selectionArgs);
break;
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
if(id!=0) {
getContext().getContentResolver().notifyChange(uri,null);
}
return id;
}
private int deleteTabDetail(String selection, String[] selectionArgs){
SQLiteDatabase db = mDBHelper.getWritableDatabase();
int id;
id = db.delete(TabsContract.TabsName.TABLE_NAME,selection,selectionArgs);
return id;
}
as for now i am not doing writing any code for update method.
@Override
public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB:
return insertTabDetail(uri,values);
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
}
private Uri insertTabDetail(Uri uri, ContentValues values){
SQLiteDatabase db = mDBHelper.getWritableDatabase();
long id = db.insert(TabsContract.TabsName.TABLE_NAME,null,values);
Uri sUri = ContentUris.withAppendedId(uri,id);
getContext().getContentResolver().notifyChange(uri, null);
return sUri;
}
@Override
public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
int id;
int match = sUriMatcher.match(uri);
switch (match)
{
case TAB_ID:
id = deleteTabDetail(selection,selectionArgs);
break;
default:
throw new IllegalArgumentException("Cannot query unknown uri : " + uri);
}
if(id!=0) {
getContext().getContentResolver().notifyChange(uri,null);
}
return id;
}
private int deleteTabDetail(String selection, String[] selectionArgs){
SQLiteDatabase db = mDBHelper.getWritableDatabase();
int id;
id = db.delete(TabsContract.TabsName.TABLE_NAME,selection,selectionArgs);
return id;
}
as for now i am not doing writing any code for update method.
So now, the next thing is you need to define your provider information in your manifest file like this
android:name=".Data.TabsContentProvider"
android:exported="false"/>
Part 3 : Defining Fragment Class and Fragment Pager Adapter Class
Implementing Class extends Fragment
In this class, we define what we need to show in various tab in our application for this example, I am updating a textview with the tab name or tab order. By doing this you will get the idea how to pass a value in the fragment.
Create as "public static" inner class (under your main activity page) name "FragmentPlaceHolder" and extends its to "Fragment". Then create a xml layout file "fragment_main2.xml".
Code for "FragmentPlaceHolder"
/*** The fragment argument representing the tab name & number for this
* fragment.
*/
private static final String ARG_TAB_NUMBER = "tabOrder";
private static final String ARG_TAB_NAME ="tabName";
public PlaceholderFragment() {
}
/**
* Returns a new instance of this fragment for the given tab name and number.
*/
public static PlaceholderFragment newInstance(int sectionNumber, String name) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_TAB_NUMBER, sectionNumber);
args.putString(ARG_TAB_NAME,name);
fragment.setArguments(args);
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main2, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
String tabName = getArguments().getString(ARG_TAB_NAME);
String tabOrder = getString(R.string.section_format, getArguments().getInt(ARG_TAB_NUMBER));
textView.setText(tabName + " - " + tabOrder);
return rootView;
}
Code for "fragment_main2.xml"
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"
tools:context="com.example.android.mydynamictabapp.Main2Activity$PlaceholderFragment">
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Writing Fragment Pager Adapter
Create a new java inner class (under main activity class) "TabSectionAdapter" extends "FragmentPagerAdapter" and inherits the abstract methods.
public TabSectionAdapter(FragmentManager fm ) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// getItem is called to instantiate the fragment for the given page.
// Return a PlaceholderFragment (defined as a static inner class below).
Tabs tab = entries.get(position);
return PlaceholderFragment.newInstance(tab.getmTabOrder(),tab.getmName());
}
@Override
public int getCount() {
// Show 3 total pages.
return entries.size();
}
@Override
public CharSequence getPageTitle(int position) {
Tabs tab = entries.get(position);
return tab.getmName();
}
}
Part 4: Update main activity class
Declare all variables
// class which handles tabs private TabSectionAdapter tabSectionAdapter;
// use to create tabs
private ViewPager mViewPager;
// arraylist of tabs in which tab details are stored
private ArrayList
// to hold tabs data when first fetch from sqlite db
private Cursor cursor;
Overwrite the onCreate method with this code below:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// fill the entries Arraylist define in the start
fillTabs();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Create the adapter that will return a fragment for each of the three
// primary sections of the activity.
tabSectionAdapter = new TabSectionAdapter(getSupportFragmentManager());
// Set up the ViewPager with the sections adapter.
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(tabSectionAdapter);
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
}
try{
//Toast.makeText(MainActivity.this, "entered in the method", Toast.LENGTH_LONG).show();
String[] Projection = { "rowid _id", TabsContract.TabsName.COLUMN_CHANNEL_NAME, TabsContract.TabsName.COLUMN_TAB_POSITION};
cursor = getContentResolver().query(TabsContract.TabsName.CONTENT_URI,Projection,null,null, TabsContract.TabsName.COLUMN_TAB_POSITION);
entries = new ArrayList
//Toast.makeText(MainActivity.this, "Tabs = "+ cursor.getCount(), Toast.LENGTH_LONG).show();
if (cursor != null) {
if (cursor.moveToFirst()) {
do{
String name;
int tabOrder;
tabOrder = cursor.getInt(2);
name = cursor.getString(1);
entries.add(new Tabs(tabOrder, name));
}while (cursor.moveToNext());
}
cursor.close();
}
}catch (NullPointerException | SQLException e) {
}
finally {
cursor.close();
}
}
Now we are good to run the app for the first time.
Download the code from here (if you want to delete/insert new tabs check the code behind InsertRecord.java) download



Comments
Post a Comment