如果移動端訪問不佳或需要更好的瀏覽體驗,歡迎使用 ==> Github 版
使用 RadioGroup 和 ViewPager 實現更加可定制的效果。
昨天設計圖剛出1點,寫了《Android 必知必會 - 動態切換著色模式和全屏模式》,記錄了動態修改頁面顯示模式的方式。今天又有新圖,不過設計師只斟酌 iOS 平臺的設計,拿到設計圖發現 TabLayout + ViewPager
的套路實現起來很麻煩,斟酌了下,為了方便,決定使用 RadioGroup + ViewPager
來實現,之所以使用 RadioGroup
,是由于它內部多個 RadioButton
的狀態是互斥的,也就是只有1個是選中狀態,不需要我們進行過剩的處理。整體來講比較簡單,就是細節略多了點。
主要知識點:
RadioButton
樣式 : selector + shape
RadioButton
文字樣式 : selector
ViewPager + Fragment
及其適配器RadioGroup
狀態監聽ViewPager
頁面切換監聽先看效果圖:
UI:
RadioGroup
,內部包括兩個 RadioButton
RadioButton
需要自定義背景和文字ViewPager
聯動事件:
ViewPager
ViewPager
寫適配器,以配合 Fragment
addOnPageChangeListener()
為其添加監聽頁面變動的事件onPageSelected(int position)
方法中修改 RadioGroup
中 RadioButton
的選中狀態RadioGroup
setOnCheckedChangeListener
監聽,并在其中修改 ViewPager
的狀態<LinearLayout
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"
android:orientation="vertical"
>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="45dp"
android:background="@color/title_bar">
<RadioGroup
android:id="@+id/main_top_rg"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="horizontal">
<RadioButton
android:id="@+id/top_rg_a"
android:layout_width="76dp"
android:layout_height="29dp"
android:background="@drawable/top_r_bg"
android:button="@null"
android:checked="true"
android:gravity="center"
android:text="@string/main_tab1"
android:textColor="@drawable/top_r_text"
android:textColorHighlight="@color/title_bar"
android:textSize="15sp"/>
<RadioButton
android:id="@+id/top_rg_b"
android:layout_width="76dp"
android:layout_height="29dp"
android:background="@drawable/top_r_bg2"
android:button="@null"
android:gravity="center"
android:layout_marginLeft="⑴dp"
android:text="@string/main_tab2"
android:textColor="@drawable/top_r_text"
android:textColorHighlight="@color/title_bar"
android:textSize="15sp"/>
</RadioGroup>
<ImageView
android:id="@+id/main_top_right"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:paddingLeft="@dimen/left_padding"
android:paddingRight="@dimen/right_padding"
android:src="@drawable/main_search"
/>
</RelativeLayout>
<android.support.v4.view.ViewPager
android:id="@+id/main_viewpager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
重點在 RadioButton
的幾個屬性:
android:button="@null"
隱藏 RadioButton
默許的圖標android:background="@drawable/top_r_bg"
設置背景,實際上是1個 selector
android:textColor="@drawable/top_r_text"
設置文字色彩,它也是1個 selector
RadioButton
: android:layout_marginLeft="⑴dp"
和描邊寬度1樣,避免出現間隙下面把 xml 代碼放在1起看,它們都放在 drawable
目錄下:
<!-- drawable/top_r_bg -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/top_r_bg_a"
android:state_checked="false"/>
<item
android:drawable="@drawable/top_r_bg_b"
android:state_checked="true"/>
</selector>
<!-- drawable/top_r_bg_a -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:bottomLeftRadius="2dp"
android:bottomRightRadius="0dp"
android:topLeftRadius="2dp"
android:topRightRadius="0dp"
/>
<stroke
android:width="1dp"
android:color="@color/white"/>
<solid android:color="@color/transparent"/>
</shape>
<!-- drawable/top_r_bg_b -->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:bottomLeftRadius="2dp"
android:topLeftRadius="2dp"/>
<solid android:color="@color/white"/>
</shape>
<!-- drawable/top_r_text -->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/white" android:state_checked="false"/>
<item android:color="@color/title_bar" android:state_checked="true"/>
</selector>
上面只貼出了左側按鈕的樣式,右側的類似,不再張貼。UI 到這里已完成,下面看事件:
private void init() {
List<Fragment> fragments = new ArrayList<>();
fragments.add(new FragmentMain01A());
fragments.add(new FragmentMain01B());
NotePagerAdapter pagerAdapter = new NotePagerAdapter(getFragmentManager(), fragments);
mainViewpager.setAdapter(pagerAdapter);
/**
* 為 Viewpager 設置頁面切換監聽,當頁面切換完成被選中時,我們同步 RadioButton 的狀態
**/
mainViewpager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == 0) radioButtonA.setChecked(true);
else radioButtonB.setChecked(true);
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
/**
* 為 RadioGroup 設置選中變化事件監聽,當 RadioButton 狀態變化,我們同步 Viewpager 的選中頁面
**/
mRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == radioButtonA.getId()) mainViewpager.setCurrentItem(0);
else if (checkedId == radioButtonB.getId()) mainViewpager.setCurrentItem(1);
}
});
//設置默許選中頁
mainViewpager.setCurrentItem(0);
}
對了,還有 NotePagerAdapter
的代碼,這個比較簡單,是 ViewPager
和 Fragment
的適配器:
public class NotePagerAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragments;
public NotePagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
}
注意,以上代碼使用的是 android.support.v4
包的類,理論上不使用 V4
包是沒問題的。
看完全體的代碼發現并沒甚么難點,純屬基礎知識的疊加,主要是 UI 控件上的細節需要處理的比較多。
再者,如果頂部的控件超過2個,還需要更多的 xml 文件,頂部的幾個控件是可以封裝成1個自定義 View 的,乃至加上中間的 ViewPager
1起封裝。等待我后面的成果吧。如果有甚么疑問或建議,可以通過文末的聯系方式和我交換。
最后,記念1下自己今天正式成為 CSDN博客專家
,祝賀廣大程序員都能在編程的路上有所成績!
PS:你可以通過下面的方式和我聯系
- 微博:cafeting
- Github: likfe
- CSDN:他叫自己Mr.張
上一篇 計算從[1,n]的素數個數
下一篇 HDU 5901 Count Primes (模板 + 數論知識)——2016 ACM/ICPC Asia Regional Shenyang Online