RadioGroup的RadioButton簡單用法——學習筆記

關於RadioButton,它的具體例子嘛,就好像是QQ啊、微信之類的app底部那幾個按鈕,不過他們是不是用RadioButton來實現的我不太清楚,但是RadioButton基本上就是這樣的效果

接下來就接着上一篇來實現一下RadioButton吧,使用RadioButton必須在RadioGroup組件中。

首先,上一篇將MainActiviy主界面替換成ContentFragment後,現在要把ContentFragment的代碼重新修改一下,以便於顯示RadioButton,在此之前,先創建一個ContentFragment的佈局文件吧。

佈局文件——content_fragment.xml:

<?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/content_viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"/>

    <RadioGroup
        android:id="@+id/rd_group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/holo_blue_dark"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/rd_news"
            android:text="新聞"
            android:drawableTop="@drawable/rb_news_drawable_selector"
            style="@style/button_tag_style"/>
        <RadioButton
            android:id="@+id/rd_weather"
            android:text="天氣"
            android:drawableTop="@drawable/rb_weather_drawable_selector"
            style="@style/button_tag_style"/>
        <RadioButton
            android:id="@+id/rd_picture"
            android:text="圖片"
            android:drawableTop="@drawable/rb_picture_drawable_selector"
            style="@style/button_tag_style"/>
        <RadioButton
            android:id="@+id/rd_vedio"
            android:text="視頻"
            android:drawableTop="@drawable/rb_vedio_drawable_selector"
            style="@style/button_tag_style"/>
        <RadioButton
            android:id="@+id/rd_shopping"
            android:text="購物"
            android:drawableTop="@drawable/rb_shopping_drawable_selector"
            style="@style/button_tag_style"/>

    </RadioGroup>

</LinearLayout>

從上面的代碼其實可以很明顯的看到,RadioButton位於RadioGroup中,而RadioButton是配合ViewPager來使用的,每點擊一個RadioButton,就切換另外一個頁面,其中有幾點需要注意的。

1.整個佈局是放在LinearLayout中的,因爲需要用到權重,也就是weight這個屬性,所以最外層的佈局是LinearLayout。

2.其實點開RadioGroup會看到【public class RadioGroup extends LinearLayout{…}】,這說明RadioGroup繼承的LinearLayout,所以在RadioGroup的屬性裏面,需要設置方向,也就是orientation的設置,由於底部按鈕是一橫排,這裏自然是設置水平方向horizontal了。

3.你會發現每一個RadioButton的屬性設置只有短短几行代碼,其實是因爲每個RadioButton設置的屬性,有一大部分是重複的,於是將些重複的部分寫在了values下的style.xml中,比如一個RadioButton原來的代碼是:

<RadioButton
            android:id="@+id/rd_shopping"
            android:text="購物"
            android:drawableTop="@drawable/rb_shopping_drawable_selector"
            android:layout_height="wrap_content"
            android:layout_width="0dp"
            android:layout_gravity="center"
            android:textSize="14sp"
            android:gravity="center"
            android:button="@null"
            android:drawablePadding="4dp"
            android:textColor="@drawable/rb_text_drawable_selector"
            android:layout_weight="1"/>

除開前面三行,剩下的都是可以重複寫的部分。
不過有幾點需要注意:

1.android:drawableTop這條屬性,是將圖片或某個控件繪製在某組件的上部,這裏是將RadioButton繪製在RadioGroup的上部,相當於覆蓋。

2.android:button=”@null”這條屬性,如果不加上這條屬性,你會發現RadioButton旁邊會有一個小圓圈按鈕,看着蛋疼,加上這條屬性用來將其隱藏。

然後將重複的部分寫在style.xml中,接着引用即可,於是在style.xml中寫如下代碼:

<style name="button_tag_style">
        <!-- Customize your theme here. -->
        <item name="android:layout_height">wrap_content</item>
        <item name="android:layout_width">0dp</item>
        <!--<item name="android:layout_gravity">center_vertical</item>-->
        <item name="android:textSize">14sp</item>
        <item name="android:gravity">center</item>
        <item name="android:button">@null</item>
        <item name="android:drawablePadding">4dp</item>
        <item name="android:textColor">@drawable/rb_text_drawable_selector</item>
        <item name="android:layout_weight">1</item>
    </style>

其中android:textColor指定的是drawable下的rb_text_drawable_selector.xml文件,創建這個文件,具體的代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="false" android:color="@android:color/black"/>
    <item android:state_checked="true" android:color="@android:color/white"/>
</selector>

和這個佈局內容相似的是每個RadioButton設置的android:drawableTop屬性,比如說第一個RadioButton,id是android:id=”@+id/rd_news”,表示新聞按鈕,它的drawableTop屬性的佈局文件是rb_news_drawable_selector.xml,具體代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_checked="false" android:drawable="@drawable/rb_news_black"/>
    <item android:state_checked="true" android:drawable="@drawable/rb_news_white"/>
</selector>

關鍵點在於,這裏指定的是否按下狀態用的不是android:state_pressed=”false或者true”,而是使用的android:state_checked屬性,這點十分重要,因爲它是RadioButton!存在於一個RadioGroup中,所以用了選中——check,而不是按下——pressed。

基本上每一個RadioButton的android:drawableTop佈局代碼都一樣,不同的只是選中和沒選中這兩種狀態所用的圖片。

接下來就是ContentFragment的具體代碼了,如下:

public class ContentMenuFragment extends BaseFragment {


    private ViewPager content_viewpager;
    private RadioGroup rd_group;

    @Override
    public View initView() {
        LogUtil.e("主頁面被初始化");
        View view = View.inflate(context, R.layout.content_fragment, null);
        content_viewpager = (ViewPager)view.findViewById(R.id.content_viewpager);
        rd_group = (RadioGroup)view.findViewById(R.id.rd_group);

        return view;
    }

    @Override
    public void initData() {
        super.initData();
        rd_group.check(R.id.rd_news);
        LogUtil.e("主頁面數據被初始化");
    }
}

上面的代碼中,有一點是需要注意的,那就是rd_group.check(R.id.rd_news),這裏使用的check方法的作用是設置一個默認選中的RadioButton,這裏傳入的id是新聞按鈕的id,就表示新聞按鈕是被默認選中的。
最後來看一下運行界面:
這裏寫圖片描述
WTF?!!!
虛擬按鍵把按鈕給擋住了,在網上找了一下解決這個問題的方法,解決辦法就是在MainActivity的onCreate方法裏面的setContentView()前添加這行代碼:

     getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

再看一下運行界面——
這裏寫圖片描述

大概就是這麼個點擊效果~~
ps:找圖片素材可花了不少時間!!!

不過這樣明顯是不行的,接下來可以給ViewPager加上頁面,然後給每個按鈕添加點擊事件,用於切換頁面,做完這些,RadioButton的使用效果纔會更加明顯。
首先,是添加頁面,由於每一個按鈕對應一個頁面,所以要創建五個頁面,不過這五個頁面當中,每一個的佈局都有重複的部分,比如標題欄就需要重複寫五遍,爲了減少這類麻煩,可以和之前創建基類Fragment一樣,爲頁面寫一個基類佈局,接下來就是這個基類——BasePager的代碼:

public class BasePager {

    //都要寫成public,不然子類無法調用
    public final Context context;
    public Toolbar toolbar;
    public TextView title_text;
    public CircleImageView menu_circle_image;
    public FrameLayout base_content_fl; //用來加載各個不同的子頁面

    public View rootView; //代表各個不同子頁面的視圖

    //構造方法
    public BasePager(Context context){
        this.context = context;
        rootView = initView();
    }

    public View initView(){
        View view = View.inflate(context, R.layout.base_pager, null);
        toolbar = (Toolbar) view.findViewById(R.id.base_title_toolbar);
        title_text = (TextView) view.findViewById(R.id.title_text);
        menu_circle_image = (CircleImageView) view.findViewById(R.id.menu_circle_image);
        base_content_fl = (FrameLayout) view.findViewById(R.id.base_content_fl);
        menu_circle_image.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                MainActivity mainActivity = (MainActivity) context;
                mainActivity.getSlidingMenu().toggle();
            }
        });
        return view;
    }

    public void initData(){
    }
}

上面的代碼中,初始化了一個圓形圖片,並且爲這個圖片添加了點擊事件,用來替代標題欄的導航按鈕,代碼中還寫了一個rootView,如果A頁面繼承了這個BasePager,那麼A的視圖就用A的rootView來表示,所以rootView的作用是方便調用。
使用圓形化圖片需要添加依賴:

compile 'de.hdodenhof:circleimageview:2.1.0'

下面是BasePager的佈局base_pager.xml的代碼:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:app="http://schemas.android.com/apk/res-auto"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <include layout="@layout/titlebar"/>

    <FrameLayout
        android:id="@+id/base_content_fl"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

上面的佈局中,將標題的佈局代碼抽出來放入了titlebar.xml中,然後include進來,不過這一步不是必須的,下面是標題欄的佈局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.Toolbar
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/base_title_toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:background="@android:color/holo_blue_dark"
    android:theme="@style/ThemeOverlay.AppCompat.Light"
    app:popupTheme="@style/ThemeOverlay.AppCompat.Light">

        <TextView
            android:id="@+id/title_text"
            android:text="標題"
            android:layout_gravity="center"
            android:textSize="20sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <de.hdodenhof.circleimageview.CircleImageView
            android:id="@+id/menu_circle_image"
            android:src="@drawable/huaji1"
            android:paddingTop="5dp"
            android:paddingBottom="5dp"
            android:layout_width="45dp"
            android:layout_height="wrap_content"/>

</android.support.v7.widget.Toolbar>

標題欄使用的是ToolBar,裏面插入了一個TextView用於顯示標題,以及一個圓形化圖片用於裝逼。
基本上BasePager算是佈局完成了,然後創建五個頁面,分別對應每一個RadioButton,每一個頁面代碼幾乎一樣,下面是其中NewsPager的代碼:

public class NewsPager extends BasePager {
    public NewsPager(Context context) {
        super(context);
    }

    @Override
    public void initData() {
        super.initData();
        title_text.setText("新聞");

        TextView textView = new TextView(context);
        textView.setText("我是新聞頁面");
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(30);
        textView.setTextColor(Color.RED);

        base_content_fl.addView(textView);//添加視圖
    }
}

五個頁面創建完成後,自然是要添加到ContentFragment對應佈局中的ViewPager中,然後給ViewPager設置適配器,用於將五個頁面綁定到ViewPager上,接下來順便給每個RadioButton設置點擊事件,用來切換頁面,下面是ContentFragment的代碼:

public class ContentMenuFragment extends BaseFragment {


    private ViewPager content_viewpager;
    private RadioGroup rd_group;
    private ArrayList<BasePager> pagers;

    @Override
    public View initView() {
        LogUtil.e("主頁面被初始化");
        View view = View.inflate(context, R.layout.content_fragment, null);
        content_viewpager = (ViewPager)view.findViewById(R.id.content_viewpager);
        rd_group = (RadioGroup)view.findViewById(R.id.rd_group);


        return view;
    }

    @Override
    public void initData() {
        super.initData();
        LogUtil.e("主頁面數據被初始化");
        rd_group.check(R.id.rd_news);
        pagers = new ArrayList<>();
        pagers.add(new NewsPager(context));
        pagers.add(new WeatherPager(context));
        pagers.add(new PicturePager(context));
        pagers.add(new VedioPager(context));
        pagers.add(new ShoppingPager(context));


        content_viewpager.setAdapter(new ContentFragmentAdapter());
        rd_group.setOnCheckedChangeListener(new MyOnCheckedChangeListener());
    }

    class MyOnCheckedChangeListener implements RadioGroup.OnCheckedChangeListener{

        @Override
        public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) {
            switch (checkedId){
                case R.id.rd_news:
                    content_viewpager.setCurrentItem(0, false);
                    isEnableScroll(SlidingMenu.TOUCHMODE_FULLSCREEN);
                    break;
                case R.id.rd_weather:
                    content_viewpager.setCurrentItem(1, false);
                    isEnableScroll(SlidingMenu.TOUCHMODE_NONE);
                    break;
                case R.id.rd_picture:
                    content_viewpager.setCurrentItem(2, false);
                    isEnableScroll(SlidingMenu.TOUCHMODE_NONE);
                    break;
                case R.id.rd_vedio:
                    content_viewpager.setCurrentItem(3, false);
                    isEnableScroll(SlidingMenu.TOUCHMODE_NONE);
                    break;
                case R.id.rd_shopping:
                    content_viewpager.setCurrentItem(4, false);
                    isEnableScroll(SlidingMenu.TOUCHMODE_NONE);
                    break;
                default:

            }
        }
    }

    private void isEnableScroll(int tochMode){
        MainActivity mainActivity = (MainActivity) context;
        mainActivity.getSlidingMenu().setTouchModeAbove(tochMode);
    }

    class ContentFragmentAdapter extends PagerAdapter{

        @Override
        public int getCount() {
            return pagers.size();
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            BasePager pager = pagers.get(position);
            pager.initData();
            View rootView = pager.rootView;
            container.addView(rootView);
            return rootView;
        }

        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
            container.removeView((View) object);
        }
    }
}

上面的代碼中,爲了防止點擊頁面出現的滑動動畫,所以setCurrentItem第二個參數設置爲false;並且,爲了防止每個頁面的SlidingMenu都能滑動從而覆蓋掉ViewPager的滑動事件,只在新聞頁面設置了能滑動SlidingMenu;同時需要注意,在ViewPager的適配器中的instantiateItem方法裏面,綁定頁面的同時需要調用頁面的InitData方法,這樣才能顯示文字,否則initData中的TextView就白設置了。
下面是運行效果:
這裏寫圖片描述

但是還有很多問題沒有處理!比如狀態欄顏色的問題,按鈕能切換頁面但是滑動頁面卻無法切換按鈕等等,顏色狀態的問題下次再解決,先來看一下切換頁面卻無法改變對應按鈕狀態的情況:
這裏寫圖片描述

先解決掉切換切換頁面時對應的滑動頁面卻無法切換這個問題,其實很簡單,既然可以通過按鈕來切換頁面,那就沒必要再設置滑動切換頁面的功能了,只需要將滑動時間屏蔽就行。
因爲這裏使用的是ViewPager,所以只需要再創建一個類讓其繼承ViewPager,同時在該類中解決滑動問題,然後把ContentFragment中的ViewPager和佈局中的ViewPager全替換成這個類即可,於是創建一個叫NoScrollViewPager的類:

public class NoScrollViewPager extends ViewPager {


    public NoScrollViewPager(Context context) {
        super(context);
    }

    public NoScrollViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return true;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return false;
    }
}

上面的類中,除了必須重寫的兩個構造方法之外,還重寫了onTouch()方法和onInterceptTouchEvent()方法,其中onInterceptTouchEvent()是ViewGroup提供的方法,返回false表示不攔截事件,而onTouch()是View提供的方法,返回true表示消耗掉事件。這樣,就不會有滑動效果了。

接下來,是如何更改頂部狀態欄的問題,其實如果是在繼承了AppcompatActivity的Activity中倒是好修改,不過這些佈局都是和Fragment相關聯的,找了一天的辦法,目前只有一個能用,而且顏色要自己去設置,並不是自動去填充或者自己變透明什麼的。現在來介紹一下方法:

首先,在res目錄下創建一個values-v21目錄,然後在這個目錄下創建styles.xml文件,如果android的API版本在21以上會自動去加載這個文件,否則加載values文件下的styles.xml。接着在values-v21文件裏的styles中設置:

<resourses>
<style name="MainActivityTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <item name="android:windowTranslucentNavigation">true</item>
        <item name="android:statusBarColor">@android:color/holo_blue_dark</item>
</style>
<resourses>

其中第一條可以讓虛擬按鍵不去遮擋底部的佈局,第二條就是設置頂部系統狀態欄的顏色,如果把這個屬性設置成@android:color/transparent表示設置成透明狀態,但是不知道爲什麼這麼設置後效果是這樣的
這裏寫圖片描述

顯示出來的圖片頂部全是白色的,由於文章背景是白色的,所以看起來好像沒了,但其實非常蛋疼!!使用這條屬性的同時我也試過在根佈局加上了 android:fitsSystemWindows=”true”這條屬性,不過依舊沒有效果,最後乾脆把顏色設置成和標題欄一樣的顏色,不過與此同時,還需要在values下的styles.xml中添加如下代碼:

<style name="MainActivityTheme" parent="Theme.AppCompat.Light.NoActionBar">
    </style>

這樣API版本不到21的時候會加載這個文件,之所以這樣設置是因爲android:statusBarColor這條屬性只在API21及以上纔會生效。
最後看一下效果吧:
這裏寫圖片描述

如果有哪位大牛有更好的設計方法,請務必告訴我,找了一天了,最後還是用的書上面的方法,真是崩潰!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章