Android UI 之 Tab類型介面總結,androidui

來源:互聯網
上載者:User

Android UI 之 Tab類型介面總結,androidui

    轉載請註明出處:http://blog.csdn.net/crazy1235/article/details/42678877


    Android 程式中實現Tab類型介面很常見,本人在做項目的時候也經常用到,所以想在這裡總結一下,實現tab類型介面的幾種方式,供大家參考。如有不對之處,歡迎大家指正!

    一、TabActivity + TabWidget + TabHost.

    實現TAB類型介面,首先想到的就是這種方式。但是在API level 13之後官方就不建議使用它了。不過還是在這裡簡單說一下它的使用吧。


    使用它的關鍵就是布局檔案了。需要在布局中添加<TabHost>、<TabWidget>、<FrameLayout>這三個控制項,id分別是系統提供的:@android:id/tabhost 、@android:id/tabs 、@android:id/tabcontent 。

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <TabHost        android:id="@android:id/tabhost"        android:layout_width="match_parent"        android:layout_height="match_parent" >        <RelativeLayout            android:layout_width="match_parent"            android:layout_height="match_parent"            android:orientation="vertical" >            <!-- 可以指定tabwidget的位置    android:layout_alignParentBottom="true" -->            <TabWidget                android:id="@android:id/tabs"                android:layout_width="match_parent"                android:layout_height="wrap_content"                android:layout_alignParentBottom="false" >            </TabWidget>            <FrameLayout                android:id="@android:id/tabcontent"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:layout_below="@android:id/tabs" >                <LinearLayout                    android:id="@+id/tab1"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#DEB887"                    android:orientation="vertical" >                </LinearLayout>                <LinearLayout                    android:id="@+id/tab2"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#BCEE68"                    android:orientation="vertical" >                </LinearLayout>                <LinearLayout                    android:id="@+id/tab3"                    android:layout_width="match_parent"                    android:layout_height="match_parent"                    android:background="#7D9EC0"                    android:orientation="vertical" >                </LinearLayout>            </FrameLayout>        </RelativeLayout>    </TabHost></LinearLayout>
    一個linearlayout對應一個tab頁面的布局。

tabHost = getTabHost();tabHost.addTab(tabHost.newTabSpec("111").setIndicator("", getResources().getDrawable(R.drawable.wuyong)).setContent(R.id.tab1));tabHost.addTab(tabHost.newTabSpec("222").setIndicator("",getResources().getDrawable(R.drawable.gongsunsheng)).setContent(R.id.tab2));tabHost.addTab(tabHost.newTabSpec("333").setIndicator("", getResources().getDrawable(R.drawable.likui)).setContent(R.id.tab3));tabHost.setBackgroundColor(Color.argb(150, 22, 70, 150));tabHost.setCurrentTab(0);tabHost.setOnTabChangedListener(new OnTabChangeListener() {@Overridepublic void onTabChanged(String tabId) {Toast.makeText(FourthActivity.this, tabId, Toast.LENGTH_SHORT).show();}});


二、ViewPager + PageAdapter

    目前最常見的tab介面就是使用viewpager來實現了。

    先來說一下viewpager的一般使用步驟:

    1. 在布局檔案中添加viewpager控制項

    2. 在代碼中設定viewpager適配器,該類繼承與pagerAdapter或它的子類。必須實現以下四個方法:

    (1)getCount()

    (2)instantiateItem()

    (3)destoryItem()

    (4)isViewFromObject()

    3. 初始化viewpager控制項,設定監聽器

    4. 設定監聽事件(setOnPageChangeListener)

    下面看一下這種方式的:


主要的功能代碼如下:

private void init() {viewPager = (ViewPager) findViewById(R.id.first_vp);LayoutInflater inflater = LayoutInflater.from(this);View view1 = inflater.inflate(R.layout.first_layout1, null);View view2 = inflater.inflate(R.layout.first_layout2, null);View view3 = inflater.inflate(R.layout.first_layout3, null);list.add(view1);list.add(view2);list.add(view3);viewPager.setAdapter(pagerAdapter);viewPager.setOnPageChangeListener(new OnPageChangeListener() {@Overridepublic void onPageSelected(int arg0) {setDots(arg0);}@Overridepublic void onPageScrolled(int arg0, float arg1, int arg2) {}@Overridepublic void onPageScrollStateChanged(int arg0) {}});}
private PagerAdapter pagerAdapter = new PagerAdapter() {
        <span style="white-space:pre"></span>//官方建議這麼寫@Overridepublic boolean isViewFromObject(View arg0, Object arg1) {return arg0 == arg1;}   <span style="white-space:pre"></span>//返回一共有多少個介面@Overridepublic int getCount() {return list.size();}<span style="white-space:pre"></span>//執行個體化一個item@Overridepublic Object instantiateItem(ViewGroup container, int position) {container.addView(list.get(position));return list.get(position);} <span style="white-space:pre"></span>//銷毀一個item@Overridepublic void destroyItem(ViewGroup container, int position, Object object) {container.removeView(list.get(position));}};
    適配器中必須要實現以上的四個方法。

    如果只有這幾個頁面,互動性肯定是不好的,所以需要添加“指標”,用來標識當前的頁面是哪一個!我在這裡用點來實現。就像顯示的那樣。

/** * 初始化底部的點 */private void initDots() {pointLayout = (LinearLayout) findViewById(R.id.point_layout);dots = new ImageView[list.size()];for (int i = 0; i < list.size(); i++) {dots[i] = (ImageView) pointLayout.getChildAt(i);}currentIndex = 0;dots[currentIndex].setBackgroundResource(R.drawable.dian_down);}/** * 當滾動的時候更換點的背景圖 */private void setDots(int position) {if (position < 0 || position > list.size() - 1|| currentIndex == position) {return;}dots[position].setBackgroundResource(R.drawable.dian_down);dots[currentIndex].setBackgroundResource(R.drawable.dian);currentIndex = position;}
    重點就是頁面切換之後,點也要切換。這時候就用到了OnPageChangeListener中的onPageSelected(int arg0)這個方法了。

@Overridepublic void onPageSelected(int arg0) {setDots(arg0);}

三、Fragment + FragmentManager

 

    fragment相信大家在項目中肯定都用過。這個方法主要就是利用fragmentManager對fragment的交易管理功能。

// 三個選項卡private LinearLayout tab1Layout, tab2Layout, tab3Layout;// 預設選中第一個tabprivate int index = 1;// fragment管理類private FragmentManager fragmentManager;// 三個fragmentprivate Fragment tab1Fragment, tab2Fragment, tab3Fragment;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_second);fragmentManager = getSupportFragmentManager();init();}/** * 初始化控制項 */private void init() {tab1Layout = (LinearLayout) findViewById(R.id.tab1_layout);tab2Layout = (LinearLayout) findViewById(R.id.tab2_layout);tab3Layout = (LinearLayout) findViewById(R.id.tab3_layout);tab1Layout.setOnClickListener(this);tab2Layout.setOnClickListener(this);tab3Layout.setOnClickListener(this);//setDefaultFragment();}/** * 設定預設顯示的fragment */private void setDefaultFragment() {FragmentTransaction transaction = fragmentManager.beginTransaction();tab1Fragment = new Tab1Fragment();transaction.replace(R.id.content_layout, tab1Fragment);transaction.commit();}/** *切換fragment * @param newFragment */private void replaceFragment(Fragment newFragment) {FragmentTransaction transaction = fragmentManager.beginTransaction();if (!newFragment.isAdded()) {transaction.replace(R.id.content_layout, newFragment);transaction.commit();} else {transaction.show(newFragment);}}/** * 改變現象卡的選中狀態 */private void clearStatus() {if (index == 1) {tab1Layout.setBackgroundColor(getResources().getColor(R.color.tab));} else if (index == 2) {tab2Layout.setBackgroundColor(getResources().getColor(R.color.tab));} else if (index == 3) {tab3Layout.setBackgroundColor(getResources().getColor(R.color.tab));}}@Overridepublic void onClick(View v) {clearStatus();switch (v.getId()) {case R.id.tab1_layout:if (tab1Fragment == null) {tab1Fragment = new Tab1Fragment();}replaceFragment(tab1Fragment);tab1Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 1;break;case R.id.tab2_layout:if (tab2Fragment == null) {tab2Fragment = new Tab2Fragment();}replaceFragment(tab2Fragment);tab2Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 2;break;case R.id.tab3_layout:if (tab3Fragment == null) {tab3Fragment = new Tab3Fragment();}replaceFragment(tab3Fragment);tab3Layout.setBackgroundColor(getResources().getColor(R.color.tab_down));index = 3;break;}}

    每一個fragment對應一個布局,點擊不同的按鈕來切換頁面。效果如:

 

四、ViewPager + Fragment + FragmentPagerAdapter

    如果想使用fragment的時候又想可以左右滑動,就可以使用這種方式。主要的部分就在viewpager的適配器。它的適配器繼承FragmentPagerAdapter.

package com.tab.view.demo3;import java.util.ArrayList;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentManager;import android.support.v4.app.FragmentPagerAdapter;public class FragmentAdapter extends FragmentPagerAdapter {private ArrayList<Fragment> list;public FragmentAdapter(FragmentManager fm, ArrayList<Fragment> list) {super(fm);this.list = list;}@Overridepublic Fragment getItem(int arg0) {return list.get(arg0);}@Overridepublic int getCount() {return list.size();}}

    需要傳入FragmentManager對象和一個存放fragment的list對象。

/** * 初始化viewpager */private void initViewPager() {viewPager = (ViewPager) findViewById(R.id.third_vp);fragmentsList = new ArrayList<>();Fragment fragment = new Tab1Fragment();fragmentsList.add(fragment);fragment = new Tab2Fragment();fragmentsList.add(fragment);fragment = new Tab3Fragment();fragmentsList.add(fragment);viewPager.setAdapter(new FragmentAdapter(getSupportFragmentManager(),fragmentsList));viewPager.setCurrentItem(0);viewPager.setOnPageChangeListener(this);}


    對button添加點擊事件。

@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.tab1_tv:viewPager.setCurrentItem(0);break;case R.id.tab2_tv:viewPager.setCurrentItem(1);break;case R.id.tab3_tv:viewPager.setCurrentItem(2);break;}}

    我在布局檔案中添加了一個imageview作為指標。如果想第一種tab類型介面的實現方式那樣在onPageSelected()方法中進行設定,效果是只能當頁面完全切換過來之後才能把指標移動過去。要想實現滑動頁面的時候同時移動指標,就需要在onPageScrolled()方法中進行設定。

@Overridepublic void onPageScrolled(int position, float positionOffset,int positionOffsetPixels) {offset = (screen1_3 - cursorImg.getLayoutParams().width) / 2;Log.d("111", position + "--" + positionOffset + "--"+ positionOffsetPixels);final float scale = getResources().getDisplayMetrics().density;if (position == 0) {// 0<->1lp.leftMargin = (int) (positionOffsetPixels / 3) + offset;} else if (position == 1) {// 1<->2lp.leftMargin = (int) (positionOffsetPixels / 3) + screen1_3 +offset;}cursorImg.setLayoutParams(lp);currentIndex = position;}


    onPageScrolled中的三個參數比較重要。第一個參數是position。它的含義是表示當前顯示的介面中的第一個介面。意思就是的當滑動的時候,有可能出現兩個介面,position指的是左邊的介面。第二個參數是positionOffset指的是位移量的比例,取值範圍是[0, 1)。第三個參數是positionOffsetPixels是指位移的像素值。後兩個參數都相對頁面(一個page)來說的。

    我之前有看到過設定指標的時候用的前兩個參數的,我也試了一下,OK的。不過感覺比較複雜,看了一下官方api,用第三個參數更簡單。關鍵就是理解第一個參數position。用這種方法我只在代碼裡有兩個判斷就可以完成了。

    如下:

 

五、Viewpager + PagerTitleStrip / PagerTabStrip


    這種方式沒有上一種效果好看,而且標題變動。看一下:

 

    布局檔案:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical" >    <android.support.v4.view.ViewPager        android:id="@+id/fifth_vp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_gravity="center" >        <android.support.v4.view.PagerTabStrip            android:id="@+id/fifth_strip"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="top"            android:background="#7EC0EE"            android:padding="10dip" />    </android.support.v4.view.ViewPager></LinearLayout>

    先來說一下PagerTitleStrip和PagerTabStrip的區別:PagerTitleStrip沒有指標,只有標題,且標題沒有響應事件;而PagerTabStrip是帶有指標的,當然也有標題,具有相應事件。二者的實現只在布局檔案中有區別,只需要把android.support.v4.view.PagerTabStrip改成android.support.v4.viewPagerTitleStrip即可。
    代碼中需要注意的就是,在適配器中重寫getPageTitle(int)方法來顯示標題。

PagerAdapter pagerAdapter = new PagerAdapter() {                //此處省略其他的方法
// 重寫此方法即可顯示標題@Overridepublic CharSequence getPageTitle(int position) {return titleList.get(position);}};


總結:

    我目前所遇到的tab類型介面的實現方式就是這麼多了,若果大家有其他的實現方式,請留言。如果我寫的有誤,請留言指正,共同進步!謝謝!

    Demo:http://download.csdn.net/detail/crazy1235/8358671

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.