最近决定,从头整理Android基础知识,和常用基本架构 和框架 ,方便以后使用,更主要是知道自己到底会些什么,突破技术瓶颈!!!
这一篇先从基本上每个应用都会搭建的软件UI 总结做起,这里的软件架构是指对现在流行软件中都会搭建的UI界面底部导航,并切换不同的片段或者跳转页面,如下图:
主要实现一共是以下两种选择:
1、RadioButton 加帧布局并替换帧布局中的片段 实现点击按钮可切换片段的效果(这里面采用尚硅谷杨老师的封装方法)
2、结合RadioButton 加ViewPager 填充片段实现可点击并支持滑动切换片段的底部导航
一、RadioButton 加帧布局并替换帧布局中的片段
相信这种实现方式,很多人都会,这里面涉及到的主要是片段的生命周期,片段事务的使用,替换,添加,覆盖,还有就是Radiobutton的使用已经很普遍了,写在这里就算是总结,之后如果需要直接过来粘贴了。
效果图如下,很简单的效果,但是这里面加入了一下代码结构设计的思想,方便提升,还有就是防止片段重复,反复的初始化:
1、首先我们需要一个主Activity,然后就是四个片段
片段的生命周期这里就不做赘述了,直接来看这几个片段的创建过程,我是很喜欢这种方式,也为之后写代码提供了一种思路:
首先一个BaseFragment作为基类:这样就定义了一个规范,有时感觉定义接口并没有这样优雅。
package com.wgd.fragment;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
/**
* Created by wangg on 2018/7/26.
* * 作用:基类,公共类
* CommonFragment,ThirdPartyFragment,CustomFragment,OtherFragment等都要继承该类
*/
public abstract class BaseFragment extends Fragment {
//上下文
protected Context context;
protected String TAG="FragmentTAG";
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
context=getActivity();
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return initView();
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initData();
}
protected abstract View initView();
/**
* 当孩子需要初始化数据,或者联网请求绑定数据,展示数据的 等等可以重写该方法
*/
protected void initData(){}
}
然后四个片段主要是依照这个抽象类的标准去完成:
举例:
package com.wgd.fragment;
import android.graphics.Color;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.TextView;
/**
* Created by 王国栋 on 2018/7/26.
* qq 1350802989
* 微信 WGDLOVELC
* 你的煎熬,都是因为你的上进心和你的能力不成正比
*/
public class CommonFragment extends BaseFragment{
TextView textView;
@Override
protected View initView() {
Log.i(TAG, "initView: CommonFragment初始化了");
textView=new TextView(context);
textView.setTextSize(20);
textView.setTextColor(Color.RED);
textView.setGravity(Gravity.CENTER);
return textView;
}
@Override
protected void initData() {
super.initData();
textView.setText("common");
}
}
以此类推创建另外三个,最后添加到主Activity中,在Activity中完成片段的添加替换和覆盖操作,什么是覆盖?就是为了防止片段反复初始化!
主Activity代码:
package com.wgd.example1;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
import android.widget.RadioGroup;
import com.wgd.fragment.BaseFragment;
import com.wgd.fragment.CommonFragment;
import com.wgd.fragment.CustomFragment;
import com.wgd.fragment.OtherFragment;
import com.wgd.fragment.ThirdPartyFragment;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RadioGroup mRg_main;
private List mBaseFragment;
/**
* 选中的Fragment的对应的位置
*/
private int position;
/**
* 上次切换的Fragment
*/
private Fragment mContent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//初始化View
initView();
//初始化Fragment
initFragment();
//设置RadioGroup的监听
setListener();
}
private void setListener() {
mRg_main.setOnCheckedChangeListener(new MyOnCheckedChangeListener());
//设置默认选中常用框架
mRg_main.check(R.id.rb_common_frame);
}
class MyOnCheckedChangeListener implements RadioGroup.OnCheckedChangeListener {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
switch (checkedId){
case R.id.rb_common_frame://常用框架
position = 0;
break;
case R.id.rb_thirdparty://第三方
position = 1;
break;
case R.id.rb_custom://自定义
position = 2;
break;
case R.id.rb_other://其他
position = 3;
break;
default:
position = 0;
break;
}
//根据位置得到对应的Fragment
BaseFragment to = getFragment();
//替换
switchFrament(mContent,to);
}
}
/**
*
* @param from 刚显示的Fragment,马上就要被隐藏了
* @param to 马上要切换到的Fragment,一会要显示
*/
private void switchFrament(Fragment from,Fragment to) {
if(from != to){
mContent = to;
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
//才切换
//判断有没有被添加
if(!to.isAdded()){
//to没有被添加
//from隐藏
if(from != null){
ft.hide(from);
}
//添加to
if(to != null){
ft.add(R.id.fl_content,to).commit();
}
}else{
//to已经被添加
// from隐藏
if(from != null){
ft.hide(from);
}
//显示to
if(to != null){
ft.show(to).commit();
}
}
}
}
// private void switchFrament(BaseFragment fragment) {
// //1.得到FragmentManger
// FragmentManager fm = getSupportFragmentManager();
// //2.开启事务
// FragmentTransaction transaction = fm.beginTransaction();
// //3.替换
// transaction.replace(R.id.fl_content, fragment);
// //4.提交事务
// transaction.commit();
// }
/**
* 根据位置得到对应的Fragment
* @return
*/
private BaseFragment getFragment() {
BaseFragment fragment = mBaseFragment.get(position);
return fragment;
}
private void initFragment() {
mBaseFragment = new ArrayList<>();
mBaseFragment.add(new CommonFragment());//常用框架Fragment
mBaseFragment.add(new ThirdPartyFragment());//第三方Fragment
mBaseFragment.add(new CustomFragment());//自定义控件Fragment
mBaseFragment.add(new OtherFragment());//其他Fragment
}
private void initView() {
setContentView(R.layout.activity_main);
mRg_main = (RadioGroup) findViewById(R.id.rg_main);
}
}
activty_main.xml文件
bottom_tag_style文件
bottom_textcolor_drawable_selector
rb_common_frame_drawable_selector文件,另外三个片段一样
这个例子RadioButton的字体的颜色是通过Selector变化的,也可以像下面一样,第二种方式实现。
二、RadioButton 加ViewPager 填充片段实现(可点击可滑动)
1、首先同样需要一个主Activity,四个片段(一般应用底部都会分为四个部分,可根据实际需求添加)
底部导航栏的图片,每个主题对应深色和浅色两张图片,分别用来给RedioButton填充背景,作为待选择和被选择的效果。
主Activity布局文件
style如下:
Selecter文件如下(需要几个导航栏就创建几个)
RedioButton 和 Selecter的用法应该不用多说了,主要是再Style样式里面的配置。
RedioButton 图片下发的字体颜色还可以用这种方式实现,就是先再在xml中设置一个默认颜色,然后在Activty中根据选中状态,修改字体颜色。
Selecter 给选中和未被选中时两个不同颜色的图片即可,注意是state_checked
主Activity中的代码
/**
* author wanggd
*
* 主入口Activity
*/
public class MainActivity extends FragmentActivity
implements RadioGroup.OnCheckedChangeListener,ViewPager.OnPageChangeListener{
private RadioButton r1, r2, r3, r4;
private RadioGroup radioGroup;
private ViewPager pager;
private List fraglist;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
fraglist = new ArrayList<>();
fraglist.add(new WorkBankFragment());
fraglist.add(new JobFairFragment());
fraglist.add(new NewsFragment());
fraglist.add(new MineFragment());
r1 = (RadioButton) findViewById(R.id.r1);
r2 = (RadioButton) findViewById(R.id.r2);
r3 = (RadioButton) findViewById(R.id.r3);
r4 = (RadioButton) findViewById(R.id.r4);
radioGroup = (RadioGroup) findViewById(R.id.radiogroup);
radioGroup.setOnCheckedChangeListener(this);
pager = (ViewPager) findViewById(R.id.viewpager);
pager.setPageTransformer(true, new DepthPageTransformer());
pager.addOnPageChangeListener(this);
pager.setAdapter(new MyAdapter(getSupportFragmentManager()));
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId == R.id.r1) {
checkLogin();
r1.setTextColor(ContextCompat.getColor(this, R.color.blue));
r2.setTextColor(ContextCompat.getColor(this, R.color.gray));
r3.setTextColor(ContextCompat.getColor(this, R.color.gray));
r4.setTextColor(ContextCompat.getColor(this, R.color.gray));
pager.setCurrentItem(0);
} else if (checkedId == R.id.r2) {
checkLogin();
r2.setTextColor(ContextCompat.getColor(this, R.color.blue));
r1.setTextColor(ContextCompat.getColor(this, R.color.gray));
r3.setTextColor(ContextCompat.getColor(this, R.color.gray));
r4.setTextColor(ContextCompat.getColor(this, R.color.gray));
pager.setCurrentItem(1);
} else if (checkedId == R.id.r3) {
checkLogin();
r3.setTextColor(ContextCompat.getColor(this, R.color.blue));
r1.setTextColor(ContextCompat.getColor(this, R.color.gray));
r2.setTextColor(ContextCompat.getColor(this, R.color.gray));
r4.setTextColor(ContextCompat.getColor(this, R.color.gray));
pager.setCurrentItem(2);
} else if (checkedId == R.id.r4) {
checkLogin();
r4.setTextColor(ContextCompat.getColor(this, R.color.blue));
r1.setTextColor(ContextCompat.getColor(this, R.color.gray));
r3.setTextColor(ContextCompat.getColor(this, R.color.gray));
r2.setTextColor(ContextCompat.getColor(this, R.color.gray));
pager.setCurrentItem(3);
}
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
switch (position) {
case 0:
r1.setChecked(true);
break;
case 1:
r2.setChecked(true);
break;
case 2:
r3.setChecked(true);
break;
case 3:
r4.setChecked(true);
break;
default:
break;
}
}
@Override
public void onPageScrollStateChanged(int state) {
}
private class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return fraglist.get(position);
}
@Override
public int getCount() {
return fraglist.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//这个地方注释掉可以防止ViewPager加载卡顿的问题
//super.destroyItem(container, position, object);
}
}
}
Fragment 的实现 可以结合第一种方式实现。或者如果java基础薄弱根据实际需要直接创建不同的Fragment,然后每个Fragment一个布局文件也可以,只是会显得杂乱而已
到此,就可以实现结合viewpager的滑动导航,其实也可以结合上面的例子,将代码精简很多,这是很久之前写的代码了,作为例子放到这。