Android การใช้งาน TabLayout และ Set Custom Tab

Android การใช้งาน TabLayout และ Set Custom Tab

วันนี้ผมจะมาเขียนบทความเกี่ยวกับการใช้ TabLayout ใน android โดยมีการ set custom tab หรือการกำหนดว่าแต่ละ tab นั้นจะประกอบด้วยอะไรบ้างเช่น TextView หรือ icon ต่างๆแล้วแต่เรากำหนด โดยเริ่มแรกผมจะทำการสร้าง Project ขึ้นมาใหม่ CustomTab

โดยกำหนดให้ Project support minSdkVersion ไว้ที่ version 17 เพราะ version ต่ำกว่านี้จะไม่รองรับบ้างคำสั่ง โดยกำหนดที่ไฟล์  build.gradle ในส่วนของ Module ตามภาพด้านล่างเลยครับ

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

android การใช้ TabLayout

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

หลังจากกำหนด minSDK แล้วก็ทำการสร้าง class Fragment ในตัวอย่างนี้ผมจะทำการสร้างทั้งหมด 3 Fragment โดยมีชื่อว่า TabFragmentA, TabFragmentB, TabFragmentC โดยให้สังเกตและจำชื่อ Fragment Layout Name ด้วยเพื่อจะได้ทำการแก้ไขถูก tab ในภายหลัง

ก่อนการใช้งาน TabLayout ต้องทำการเพิ่ม dependencies ด้วยโดยไปที่ไฟล์ build.gradle อันเดิมจากด้านบน

โดยเพิ่มคำสั่งต่อไปนี้

compile ‘com.android.support:appcompat-v7:25.3.1’
compile ‘com.android.support:design:25.3.1’

จากได้ตามรูปด้านล่างนี้ครับ

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ต่อจากนั้นให้ทำการสร้าง layout สำหรับรูปแบบ tab โดยผมจะตั้งชื่อว่า tab_header เป็น layout แบบ RelativeLayout

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ประกอบด้วย TextView สำหรับข้อความบน Tab และ View สำหรับเป็นเส้นขีด โดยมีโค้ดดังนี้


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/holo_orange_dark">

<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:background="@android:color/holo_blue_bright"/>
<TextView
android:id="@+id/tab_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:textStyle="bold"
android:text="title"
android:textColor="@android:color/white"/>
</RelativeLayout>

ต่อจากนั้นก่อนจะทำการ implement TabLayout ใน MainAcitivity ได้นั้นต้องทำการสร้าง TabAdapter ก่อนเพื่อเป็นตัวจัดการ Tab แต่ละ Tab โดยผมทำการสร้าง Class ที่มีชื่อว่า TabAdapter โดยมีโค้ดดังต่อไปนี้ครับ


package customtab.example.thaicoding.customtab;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;

&nbsp;

public class TabAdapter extends FragmentStatePagerAdapter{

int nTabs;

public TabAdapter(FragmentManager fm, int numOfTabs) {
super(fm);
this.nTabs = numOfTabs;
}

@Override
public Fragment getItem(int position) {
Bundle bundle = new Bundle();
switch(position){
case 0:
TabFragmentA tabA = new TabFragmentA();
bundle.putString("select_tab","select TabA");
tabA.setArguments(bundle);
return tabA;
case 1:
TabFragmentB tabB = new TabFragmentB();
bundle.putString("select_tab","select TabB");
tabB.setArguments(bundle);
return tabB;
case 2:
TabFragmentC tabC = new TabFragmentC();
bundle.putString("select_tab","select TabC");
tabC.setArguments(bundle);
return tabC;
default:
return null;
}
}

@Override
public int getCount() {
return this.nTabs;
}
}

สังเกตโค้ดใน method getItem จะเป็นการ return Fragment A ถึง C จากที่เราทำการสร้างไว้ก่อนหน้านี้ นอกจากนี้ยังมีการ pass argument ไปยัง Fragment ด้วยเพื่อที่จะได้ระบุว่าคือค่า Fragment อันไหนไป

ต่อมาก็จะเป็นการเขียนโค้ดใน MainActivity เพื่อทำการใช้งาน TabLayout โดยมีโค้ดดังนี้


package customtab.example.thaicoding.customtab;

import android.content.Context;
import android.support.design.widget.TabLayout;
import android.support.v4.content.ContextCompat;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("TabA"));
tabLayout.addTab(tabLayout.newTab().setText("TabB"));
tabLayout.addTab(tabLayout.newTab().setText("TabC"));

final ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
final TabAdapter tabAdapter = new TabAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(tabAdapter);

}

}

เมื่อกด Run program ดูก็จะได้ Tab ขึ้นมา 3 อันคือ TabA, TabB, TabC ตามภาพด้านล่างครับผม

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

สังเกตว่า tab แต่ละอันนั้นจะเป็นสีขาวธรรมดาและข้อความปกติ ต่อมาเราจะทำการใส่ custom header จากไฟล์ Layout tab_header ให้กับ Tab

โดยทำการเพิ่มโค้ดในไฟล์ MainAcitivity.java ในส่วนเฉพาะ method onCreate โดยมีโค้ดดังนี้


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("TabA"));
tabLayout.addTab(tabLayout.newTab().setText("TabB"));
tabLayout.addTab(tabLayout.newTab().setText("TabC"));

for(int i = 0; i < tabLayout.getTabCount();i++){
TabLayout.Tab tab = tabLayout.getTabAt(i);
RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(this)
.inflate(R.layout.tab_header, tabLayout,false);
TextView tabTextView = (TextView)relativeLayout.findViewById(R.id.tab_title);
tabTextView.setText(tab.getText());
tab.setCustomView(relativeLayout);
tab.select();
}

final ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
final TabAdapter tabAdapter = new TabAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(tabAdapter);

}

สังเกตโค้ด for loop จะทำการลูปทุก tab แล้วใช้คำสั่ง RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(this) เพื่อเอา layout จากไฟล์ tab_header มา setCustomView ให้กับแต่ละ Tab นอกจากนี้ยังมีการกำหนดข้อความ TextView ที่อยู่ใน layout tab_header อีกด้วยซึ่งทำให้เห็นว่าเราสามารถเพิ่ม control อื่นๆเข้าไปได้อีกด้วย เมื่อเสร็จแล้วลองรันดูก็จะเห็นว่าแต่ละ tab ก็ถูกแทนที่ด้วยรูปแบบของ tab_header

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

แต่เมื่อลองกดแต่ละ tab จะเห็นว่าสีของ tab มีการไม่มีการเปลี่ยนแปลงเลยทำให้คนใช้งานไม่รู้ว่า tab ยังทำงานได้หรือโปรแกรมยังทำงานได้รึเปล่า ซึ่งก็แก้ปัญหาด้วยการกำหนดสีอีกสีเมื่อมีการกด tab โดยทำการ implement addOnTabSelectedListener และ addOnPageChangeListener โดยทำการเพิ่มโค้ดในส่วนของ onCreate เมื่อเดิมโดยมีโค้ดดังต่อไปนี้


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TabLayout tabLayout = (TabLayout)findViewById(R.id.tab_layout);
tabLayout.addTab(tabLayout.newTab().setText("TabA"));
tabLayout.addTab(tabLayout.newTab().setText("TabB"));
tabLayout.addTab(tabLayout.newTab().setText("TabC"));

for(int i = 0; i < tabLayout.getTabCount();i++){
TabLayout.Tab tab = tabLayout.getTabAt(i);
RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(this)
.inflate(R.layout.tab_header, tabLayout,false);
TextView tabTextView = (TextView)relativeLayout.findViewById(R.id.tab_title);
tabTextView.setText(tab.getText());
tab.setCustomView(relativeLayout);
tab.select();
}

final ViewPager viewPager = (ViewPager)findViewById(R.id.pager);
final TabAdapter tabAdapter = new TabAdapter(getSupportFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(tabAdapter);

viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){

@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
Log.d("tabselect",tab.getPosition()+"");
Context context = getApplicationContext().getApplicationContext();
int tabIconColor = ContextCompat.getColor(context, R.color.colorPrimaryDark);
int textColor = ContextCompat.getColor(context,R.color.colorAccent);
tab.getCustomView().setBackgroundColor(tabIconColor);
TextView textTitle = (TextView)tab.getCustomView().findViewById(R.id.tab_title);
textTitle.setTextColor(textColor);
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {
Context context = getApplicationContext().getApplicationContext();
int tabIconColor = ContextCompat.getColor(context, android.R.color.holo_orange_dark);
int textColor = ContextCompat.getColor(context, android.R.color.white);
tab.getCustomView().setBackgroundColor(tabIconColor);
TextView textTitle = (TextView)tab.getCustomView().findViewById(R.id.tab_title);
textTitle.setTextColor(textColor);
}

@Override
public void onTabReselected(TabLayout.Tab tab) {

}
});

}

สังเกตโค้ด เราสามารถอ้างอิง control ต่างๆที่อยู่ใน customView ได้โดยอ้างผ่าน tab.getCustomView() ตามโค้ดนั้นเองซึ่งทำให้เราสามารถกำหนดทั้งสี และข้อความได้อีกด้วย และจุดสังเกตอีกอย่างคือตอน onTabUnselected ก็ต้องทำการปรับสีเพื่อกลับมาเหมือนเดิมตอนยังไม่กด ไม่ฉะนั้นแล้ว สี tab ก็จะค้างๆเลยๆจนครบทุก tab ที่เรากดทำให้ไม่สามารถบอกได้ว่า tab อันไหนที่ active จากการกดของเรา

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ภาพปัญหาสีค้างเนื่องจากไม่ทำการกำหนดสีใน method onTabUnselected

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

จากนั้นผมจะทำการกำหนด id ของ TextView แต่ละอันที่อยู่ใน Layout Fragment A ถึง C โดยใน Layout Fragment A มีโค้ดดังนี้

ไฟล์ tab_fragment_a.xml


&amp;amp;amp;amp;lt;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="customtab.example.thaicoding.customtab.TabFragmentA"&amp;amp;amp;amp;gt;

&amp;amp;amp;amp;lt;!-- TODO: Update blank fragment layout --&amp;amp;amp;amp;gt;
&amp;amp;amp;amp;lt;TextView
android:id="@+id/txt_content_tabA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textStyle="bold"
android:textSize="20dp"
android:text="@string/hello_blank_fragment" /&amp;amp;amp;amp;gt;

&amp;amp;amp;amp;lt;/RelativeLayout&amp;amp;amp;amp;gt;

โดยในไฟล์ tab_fragment_b.xml และ tab_fragment_c.xml ก็มีโค้ดคล้ายกันแต่แค่ id เปลี่ยนจาก txt_content_tabA เป็น txt_content_tabB , txt_content_tabC ต่อจากนั้นให้ทำการแก้ไขไฟล์ class TabFragmentA ให้มีโค้ดดังต่อไปนี้


package customtab.example.thaicoding.customtab;

import android.os.Bundle;
import android.support.v4.app.Fragment;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* A simple {@link Fragment} subclass.
* Activities that contain this fragment must implement the
* to handle interaction events.
* create an instance of this fragment.
*/
public class TabFragmentA extends Fragment {

private String select_tab;

public TabFragmentA() {
// Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
select_tab = getArguments().getString("select_tab");
}
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.tab_fragment_a, container, false);
TextView textView = (TextView)rootView.findViewById(R.id.txt_content_tabA);
textView.setText(select_tab);
return rootView;
}

}

ถ้าในกรณีที่ android studio มีการ generate code อื่นนอกเหนือจากนี้ให้ทำการลบออกไม่นั้นจะทำการรันไม่ผ่านเพราะไม่ได้ทำการ implement method บ้าง method ครับ และโค้ดในส่วนของ tab B, tab C ก็จะเหมือนกันแตกต่างกันแค่ตรง R.id.txt_content_tabA เป็นของ tabB  และ tabC เท่านั้น

สังเกตโค้ด method onCreate จะเห็นว่ามีการเรียกใช้ getString() ซึ่งค่า String ที่มีชื่อว่า “select_tab” นั้นเราได้ทำการส่งมาตั้งแต่ใน TabAdapter แล้ว จากนั้นก็นำค่า String มา set ให้กับ TextView ที่อยู่ใน layout fragment แต่ละ Tab นั้นเอง เมื่อลองรันก็จะได้ดังรูปด้านล่างครับ

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ก็ถือว่าเป็นอันเสร็จสิ้นการใช้งาน TabLayout ใน android และการสร้าง layout tab เพื่อกำหนด custom แต่ละ tab ให้มีหน้าตาแบบไหน อีกอย่างที่มักเจอปัญหาคือ เมื่อใช้การกำหนด custom tab ถ้าใน TabLayout ไม่ใส่ tag

app:tabPaddingStart=”0dp”
app:tabPaddingEnd=”0dp”

จะทำให้เกิดช่องว่างแต่ละ tab ตามรูปด้านล่างครับ

 

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ANDROID การใช้งาน TABLAYOUT และ SET CUSTOM TAB

ผมก็ขอจบบทความนี้ไว้เพียงเท่านี้นะครับสามารถ download source code ตาม link  ด้านล่างเลยครับ

Download Sourcecode

Add a Comment

Your email address will not be published. Required fields are marked *