Android 最简单的导航栏实现

在开发中,我们经常碰到这样的控件,用来切换不同的Fragment

这种控件的实现的效果有多种多样,一般来说我们都是使用一个LinearLayout嵌套几个Button来实现,然后通过for循环来实现单一的选择。

虽然代码量不多,但对于我们这样有追求的人来说,是不会屑于使用方式了。因为android上已经有了个RadioGroup了,为毛还要写个for循环来控制单一的选择状态呢。

废话少说,直接上代码:

<RelativeLayout 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" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.yuyu.navigationbardemo.MainActivity" tools:showIn="@layout/activity_main">

    <FrameLayout  android:id="@+id/content" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_above="@+id/navigation" />

    <RadioGroup  android:id="@+id/navigation" android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentBottom="true" android:background="@android:color/white" android:orientation="horizontal">
        <!--android:drawableTop="@mipmap/ic_launcher"-->
        <!--top的图片直接设置选择器的了,选择器状态state-->
        <RadioButton  style="@style/MainRadioButtonStyle" android:tag="0" android:text="红色" />

        <RadioButton  style="@style/MainRadioButtonStyle" android:tag="1" android:text="蓝色" />

        <RadioButton  style="@style/MainRadioButtonStyle" android:tag="2" android:text="绿色" />

        <RadioButton  style="@style/MainRadioButtonStyle" android:tag="3" android:text="黄色" />
    </RadioGroup>

</RelativeLayout>

没啥好说的,这就一个简单的布局代码,要注意的是,在RadioButton里面我使用了自定义的风格。

这是RadioButton自定义风格,也没啥好说的

<style name="MainRadioButtonStyle">
        <item name="android:layout_marginTop">8dp</item>
        <item name="android:drawablePadding">2dp</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:layout_width">wrap_content</item>
        <item name="android:layout_marginBottom">5dp</item>
        <item name="android:textSize">12sp</item>
        <item name="android:layout_weight">1</item>
        <item name="android:button">@null</item>
        <item name="android:gravity">center</item>
        <item name="android:textColor">@drawable/selector_navigation_text_bg</item>
    </style>

同时为了能让被选择的字体变色,我们需要一个字体选择器和一个图标的选择器,选择器依然没什么好说的..
唯一需要注意的是:两个选择器的状态需要一致

字体颜色选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_checked="true" />
    <item android:color="@android:color/black" android:state_checked="false" />
</selector>

图标选择器:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/icon_selected" android:state_checked="true" />
    <item android:drawable="@mipmap/icon_un_selected" android:state_checked="false" />
</selector>

布局文件什么的已经上完,是时候来搞java代码了,不废话,还是直接上java代码

public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
    private String TAG = "MainActivity";
    private RadioGroup mNavigationBar;
    private FragmentManager mFm;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        init();
    }

    private void init() {
        mFm = getSupportFragmentManager();
        mNavigationBar = (RadioGroup) findViewById(R.id.navigation);

        //设置图标
        int size = (int) getResources().getDimension(R.dimen.navigation_top_icon_size);
        for (int i = 0, count = mNavigationBar.getChildCount(); i < count; i++) {
            RadioButton rb = (RadioButton) mNavigationBar.getChildAt(i);
            Drawable topIcon = getResources().getDrawable(R.drawable.selector_navigation_bg);
            topIcon.setBounds(0, 0, size, size);
            rb.setCompoundDrawables(null, topIcon, null, null);
            rb.setId(i);
        }
        mNavigationBar.setOnCheckedChangeListener(this);
        ((RadioButton) mNavigationBar.getChildAt(0)).setChecked(true);
    }

    //进行Fragment切换
    private void chooseFragment(String tag) {
        int color = Color.RED;
        switch (tag) {
            case "0":
                color = Color.RED;
                break;
            case "1":
                color = Color.BLUE;
                break;
            case "2":
                color = Color.GREEN;
                break;
            case "3":
                color = Color.YELLOW;
                break;
        }
        Fragment fragment = DummyFragment.newInstance(color);
        FragmentTransaction ft = mFm.beginTransaction();
        ft.replace(R.id.content, fragment);
        ft.commit();
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        RadioButton rb = (RadioButton) group.getChildAt(checkedId);
        if (rb.isChecked()) {
            chooseFragment(String.valueOf(rb.getTag()));
        }
    }

    @SuppressLint("ValidFragment")
    public static class DummyFragment extends Fragment {
        int color;

        public static DummyFragment newInstance(@ColorInt int color) {
            return new DummyFragment(color);
        }

        private DummyFragment() {
        }


        private DummyFragment(int color) {
            this.color = color;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View view = inflater.inflate(R.layout.test_game_detail_fragment, container, false);
            view.setBackgroundColor(color);
            return view;
        }
    }

}

简单吧,这就是全部的控制代码了,虽然有几十行,但是核心的代码也就那么几行,核心方法就是onCheckedChanged回调函数,在最开始初始化控件的时候,我们按照排列顺序依次给没一个RadioButton设置了递增的id,所以在RadioGroup被选中时,便可以直接获取到被点中的子控件。

这里还有个坑需要注意!!!
那便是设置图标的时候,不能直接把下面这代码提到循环外

  Drawable topIcon = getResources().getDrawable(R.drawable.selector_navigation_bg);

如果提到循环外,那他便是一个局部变量,会同时被所有RadioButton共用,到时候进行状态选择时,图标的状态将完全混乱!!

好了,最后是效果图:
Android 最简单的导航栏实现_第1张图片

最后的最后便是源代码快,点击我

你可能感兴趣的:(android,控件,导航)