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及以上才会生效。
最后看一下效果吧:
如果有哪位大牛有更好的设计方法,请务必告诉我,找了一天了,最后还是用的书上面的方法,真是崩溃!!!
相关阅读
Java中Map的 entrySet() 详解以及用法(四种遍历map的
Entry 由于Map中存放的元素均为键值对,故每一个键值对必然存在一个映射关系。 Map中采用Entry内部类来表示一个映射项,映射项包含
Beanutils.copyProperties( )用法及重写提高效率
一、简介:BeanUtils提供对Java反射和自省API的包装。其主要目的是利用反射机制对JavaBean的属性进行处理。我们知道,一个JavaBean通
/*** Calendar:日历类* add() roll()* @author Administrator**/public class CalendarDemo {/** * @param args */ public sta
meshgrid:网格1、主要使用的函数为[X,Y]=meshgrid(xgv,ygv);meshgrid函数生成的X,Y是大小相等的矩阵,xgv,ygv是两个网格矢量,xgv,ygv都
在Linux内核源码中,实现和链表相关的接口list_entry()时,会调用container_of()宏定义,它的作用是:给定结构体中某个成员的地址、该结