新建一个工程,取名引导页面Activity为SplashActivity
布局activity_splash代码为:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/rl_splash_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@mipmap/bg_splash"
    tools:context="com.gold.SplashActivity">


</RelativeLayout>

编写完布局文件,下面编写SplashActivity引导页代码

public class SplashActivity extends Activity {

    private RelativeLayout rl_splash_root;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_splash);
        rl_splash_root = (RelativeLayout) findViewById(R.id.rl_splash_root);
        //渐变动画、缩放动画、旋转动画
        AlphaAnimation aa = new AlphaAnimation(0,1);
//        aa.setDuration(500);//持续播放时间
        aa.setFillAfter(true);//播放完停留状态

        ScaleAnimation sa = new ScaleAnimation(0,1,0,1,ScaleAnimation.RELATIVE_TO_SELF,0.5f,ScaleAnimation.RELATIVE_TO_SELF,0.5f);
//        sa.setDuration(500);
        sa.setFillAfter(true);

        RotateAnimation ra = new RotateAnimation(0,360,RotateAnimation.RELATIVE_TO_SELF,0.5f,RotateAnimation.RELATIVE_TO_SELF,0.5f);
//        ra.setDuration(500);
        ra.setFillAfter(true);

        AnimationSet set = new AnimationSet(false);
        //添加三个动画
        set.addAnimation(aa);
        set.addAnimation(sa);
        set.addAnimation(ra);
        set.setDuration(2000);
        rl_splash_root.startAnimation(set);
        //动画监听
        set.setAnimationListener(new MyAnimationListener());
    }

    class MyAnimationListener implements Animation.AnimationListener{

        /**
         * 当动画开启是回调这个方法
         * @param animation
         */
        @Override
        public void onAnimationStart(Animation animation) {

        }

        /**
         * 当动画播放结束回调这个方法,在这个方法中跳转到主页面
         * @param animation
         */
        @Override
        public void onAnimationEnd(Animation animation) {
            Toast.makeText(SplashActivity.this,"动画播放结束了....",Toast.LENGTH_SHORT).show();
            boolean isStartMain = CacheUtils.getBoolean(SplashActivity.this, START_MAIN);

            if (isStartMain){
                 //如果进入过主页面,直接进入主页面
                //延迟2s进入主页面
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        //进入主页面
                        startMainActivity();
                    }
                },2000);
            }else {
                //如果没进入过主页面,进入引导页面
                Intent intent = new Intent(SplashActivity.this,GuideActivity.class);
                startActivity(intent);

            }
        }

        /**
         * 当动画重复播放回调这个方法
         * @param animation
         */
        @Override
        public void onAnimationRepeat(Animation animation) {

        }
    }
 /**
     * 启动主页面
     */
    private void startMainActivity() {
        Intent intent = new Intent(this,MainActivity.class);
        startActivity(intent);
        //关闭当前页
        finish();
    }
}

这里给引导页添加了进入动画
新建一个缓存工具类CacheUtils

public class CacheUtils {

    /**
     * 得到缓存值
     * @param context
     * @param key
     * @return
     */
    public static boolean getBoolean(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences("willkong",Context.MODE_PRIVATE);
        return sp.getBoolean(key,false);
    }
}

引导页activity_guide布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_guide"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.gold.activity.GuideActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <Button
        android:id="@+id/btn_start_main"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="80dp"
        android:background="@drawable/btn_start_main_selector"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:text="开始体验"
        android:textColor="@drawable/btn_start_main_textcolor_selector"
        android:textSize="20sp"
        android:visibility="visible" />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="40dp">

        <LinearLayout
            android:id="@+id/ll_point_group"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" />

        <ImageView
            android:id="@+id/iv_red_point"
            android:layout_width="10dp"
            android:layout_height="10dp"
            android:background="@drawable/point_red" />
    </RelativeLayout>



</RelativeLayout>

体验按钮的样式文件
btn_start_main_selector.xml

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

btn_start_main_textcolor_selector.xml

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

正常点point_normal.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <size android:height="10dp" android:width="10dp"></size>
    <solid android:color="@android:color/darker_gray"></solid>
</shape>

红点point_red.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval">
    <size android:height="10dp" android:width="10dp"></size>
    <solid android:color="@android:color/holo_red_dark"></solid>
</shape>

GuideActivity

public class GuideActivity extends Activity {

    private ViewPager viewpager;
    private Button btn_start_main;
    private LinearLayout ll_point_group;
    private ImageView iv_red_point;
    private ArrayList<ImageView> imageViews;
    private int leftmax;//点的间距
    private int widthdpi;
    private int heightdpi;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_guide);
        viewpager = (ViewPager) findViewById(R.id.viewpager);
        btn_start_main = (Button) findViewById(R.id.btn_start_main);
        ll_point_group = (LinearLayout) findViewById(R.id.ll_point_group);
        iv_red_point = (ImageView) findViewById(R.id.iv_red_point);
        //准备数据
        int ids[] = new int[]{R.mipmap.guide_1,R.mipmap.guide_2,R.mipmap.guide_3};
        imageViews = new ArrayList<>();
        widthdpi = DensityUtil.dip2px(this,10);
        heightdpi = DensityUtil.dip2px(this,10);
        for (int i=0;i<ids.length;i++){
            ImageView imageView = new ImageView(this);
            //设置背景
            imageView.setBackgroundResource(ids[i]);
            //添加到图片集合中
            imageViews.add(imageView);

            //创建点--有多少张图片要显示就有多少个点
            ImageView point = new ImageView(this);
            point.setBackgroundResource(R.drawable.point_normal);
            /**
             * 单位是像素
             * 把单位当成dp转成对应的像素
             */

            LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(widthdpi,heightdpi);
            if (i!=0){
                //不包括第0个,所有的点距离设置为10个像素
                params.leftMargin = widthdpi;
            }
            point.setLayoutParams(params);
            //把点添加到点集合中
            ll_point_group.addView(point);

        }
        //设置ViewPager的适配器
        viewpager.setAdapter(new MyPagerAdapter());
        //根据View的生命周期,当视图执行到onLayout或者onDraw的时候,视图的高和宽,边距都有了,这里就得到两个点之间的间距了
        iv_red_point.getViewTreeObserver().addOnGlobalLayoutListener(new MyOnGlobalLayoutListener());
        //获取ViewPager屏幕滑动的百分比
        viewpager.addOnPageChangeListener(new MyOnPageChangeListener());
    }

    class MyOnPageChangeListener implements ViewPager.OnPageChangeListener{

        /**
         * 当页面滚动了回调这个方法
         * @param position 当前滑动页面的位置
         * @param positionOffset 页面滑动的百分比
         * @param positionOffsetPixels 页面滑动的像素
         */
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
        {
            //两点间移动的距离 =  屏幕百分比 * 间距
            int leftmargin = (int) (positionOffset * leftmax);
            //两点间滑动对应的坐标 = 原来的起始位置 + 两点间移动的距离
            leftmargin = (int) (position * leftmax + positionOffset * leftmax);
            //params.LeftMargin = 两点间滑动对应的坐标
            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)
                    iv_red_point.getLayoutParams();
            params.leftMargin = leftmargin;
            iv_red_point.setLayoutParams(params);
        }

        /**
         * 当页面被选中的时候,回调这个方法
         * @param position 被选中页面的对应位置
         */
        @Override
        public void onPageSelected(int position) {
            if (position == imageViews.size()-1){
                //最后一个页面
                btn_start_main.setVisibility(View.VISIBLE);
            }else {
                //其他页面
                btn_start_main.setVisibility(View.GONE);
            }
        }

        /**
         * 当ViewPager页面滑动状态发生变化的时候会回调这个方法
         * @param state
         */
        @Override
        public void onPageScrollStateChanged(int state) {

        }
    }

    class MyOnGlobalLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener{

        @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        @Override
        public void onGlobalLayout() {
            //执行不止一次
            iv_red_point.getViewTreeObserver().removeOnGlobalLayoutListener(this);

            //间距 = 第一个点距离左边的距离 - 第0个点距离左边的距离
            leftmax = ll_point_group.getChildAt(1).getLeft() - ll_point_group.getChildAt(0).getLeft();
        }
    }


    class MyPagerAdapter extends PagerAdapter {

        /**
         * 返回数据的总个数
         * @return
         */
        @Override
        public int getCount() {
            return imageViews.size();
        }

        /**
         * 作用,getView
         * @param container viewpager
         * @param position 要创建页面的位置
         * @return
         */
        @Override
        public Object instantiateItem(ViewGroup container, int position) {
            ImageView imageView = imageViews.get(position);
            //添加到容器中
            container.addView(imageView);
//            return position;
            return imageView;
        }

        /**
         * 判断
         * @param view 当前创建的视图
         * @param object 上面instantiateItem返回的结果值
         * @return
         */
        @Override
        public boolean isViewFromObject(View view, Object object) {
//            return view == imageViews.get(Integer.parseInt((String) object));
            return view ==  object;
        }


        /**
         * 销毁页面
         * @param container viewpager
         * @param position 要销毁页面的位置
         * @param object 要销毁的视图
         */
        @Override
        public void destroyItem(ViewGroup container, int position, Object object) {
//            super.destroyItem(container, position, object);
            container.removeView((View) object);
        }

    }
}

MainActivity主页面的界面activity_main.xml
2_主页面
2.1_主页面实现的分析
2.2_主页面的布局
主页面采用的是线性布局,中间是FrameLayout并且设置权重1,底部是RadioGroup

<?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">
    <!--标题栏-->
    <include layout="@layout/titlebar"/>
    <!--FrameLayout-->
    <FrameLayout
        android:id="@+id/fl_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1" />
    <!--RadioGroup-->
    <RadioGroup
        android:id="@+id/rg_bottom_tag"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#11000000"
        android:gravity="center_vertical"
        android:orientation="horizontal"
        android:padding="3dp"
        >

        <RadioButton
            android:id="@+id/rb_common_frame"
            android:text="常用框架"
            android:drawableTop="@drawable/rb_common_frame_drawable_selector"
            style="@style/botttom_tag_style"
            />

        <RadioButton
android:id="@+id/rb_thirdparty"
            android:text="第三方"
            android:drawableTop="@drawable/rb_thirdparty_drawable_selector"
            style="@style/botttom_tag_style"
            />

        <RadioButton
            android:id="@+id/rb_custom"
            android:text="自定义控件"
            android:drawableTop="@drawable/rb_custom_drawable_selector"
            style="@style/botttom_tag_style"
            />

        <RadioButton
            android:id="@+id/rb_other"
            android:text="其他"
            android:drawableTop="@drawable/rb_other_drawable_selector"
            style="@style/botttom_tag_style"
            />

    </RadioGroup>

</LinearLayout>

Titlebar标题栏

<?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="50dp"
    android:background="@android:color/holo_blue_light"
    android:gravity="center"
    android:orientation="horizontal">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:text="尚硅谷知识库"
        android:textColor="#ffffff"
        android:textSize="20sp" />
</LinearLayout>

在values/styles/botttom_tag_style 的代码

<style name="botttom_tag_style">
    <!-- Customize your theme here. -->
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_gravity">center_vertical</item>
    <item name="android:button">@android:color/transparent</item>
    <item name="android:drawablePadding">3dp</item>
    <item name="android:gravity">center</item>
    <item name="android:textColor">@drawable/rb_style_textcolor_selector</item>
    <item name="android:textSize">10sp</item>
    <item name="android:layout_weight">1</item>
</style>

rb_style_textcolor_selector代码

颜色值一般是由设计师提供,不需要记住

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

2.3_实例化布局控件

private void initView() {
    setContentView(R.layout.activity_main);
    rg_bottom_tag = (RadioGroup) findViewById(R.id.rg_bottom_tag);
}

3_创建各个子页面
3.1_创建BaseFragment

public abstract class BaseFragment extends Fragment {
    /**
     * 上下文
     */
    protected Context mContext;
    /**
     * 该Fragment是否被初始化过
     */
    private boolean isInit = false;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = getActivity();
    }
  @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return initView();
    }

    /**
     * 由子类实现该方法,创建自己的视图
     * @return
     */
    protected abstract View initView() ;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        initData();
    }
    /**
     * 子类,需要初始化数据,联网请求数据并且绑定数据,等重写该方法
     */
    protected void initData() {
    }
}

3.2_定义各个子页面
CommonFrameFragment 常用框架Fragment

public class CommonFrameFragment extends BaseFragment {

    private static final String TAG = CustomFragment.class.getSimpleName();
    private TextView textView;
    @Override
    protected View initView() {
  Log.e(TAG,"常用框架页面初始化了...");
        textView = new TextView(mContext);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(20);
        textView.setTextColor(Color.BLACK);
        return textView;
    }

    @Override
    protected void initData() {
        super.initData();
        Log.e(TAG, "常用框架数据初始化了...");
        textView.setText("我是常用框架页面");
    }
}

CustomFragment 自定义Fragment类

public class CustomFragment extends BaseFragment {

    private static final String TAG = CustomFragment.class.getSimpleName();
    private TextView textView;
    @Override
    protected View initView() {
        Log.e(TAG,"自定义页面初始化了...");
        textView = new TextView(mContext);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(20);
        textView.setTextColor(Color.BLACK);
        return textView;
    }

    @Override
    protected void initData() {
        super.initData();
        Log.e(TAG, "自定义数据初始化了...");
        textView.setText("我是自定义页面");
    }
}

ThirdPartyFragment 第三方Fragment

public class ThirdPartyFragment extends BaseFragment {

    private static final String TAG = ThirdPartyFragment.class.getSimpleName();
    private TextView textView;
    @Override
    protected View initView() {
        Log.e(TAG,"第三方页面初始化了...");
        textView = new TextView(mContext);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(20);
        textView.setTextColor(Color.BLACK);
        return textView;
    }

    @Override
    protected void initData() {
        super.initData();
        Log.e(TAG, "第三方数据初始化了...");
        textView.setText("我是第三方页面");
    }
}

OtherFragment 其他Fragment

public class OtherFragment extends BaseFragment {

    private static final String TAG = OtherFragment.class.getSimpleName();
    private TextView textView;
    @Override
    protected View initView() {
        Log.e(TAG,"其他页面初始化了...");
        textView = new TextView(mContext);
        textView.setGravity(Gravity.CENTER);
        textView.setTextSize(20);
        textView.setTextColor(Color.BLACK);
        return textView;
    }

    @Override
    protected void initData() {
        super.initData();
        Log.e(TAG, "其他数据初始化了...");
        textView.setText("我是其他页面");
    }
}

3.3_初始化Fragment

/**
 * 初始化Fragment
 */
private void initFragment() {
    mBaseFragments = new ArrayList<>();
    mBaseFragments.add(new CommonFrameFragment());//常用框架
    mBaseFragments.add(new ThirdPartyFragment());//第三方
    mBaseFragments.add(new CustomFragment());//自定义
 mBaseFragments.add(new OtherFragment());//其他

}

``
3.4_设置RadioGroup的监听
private void setListener() { 
 rg_bottom_tag.setOnCheckedChangeListener(new MyOnCheckedChangeListener()); 
 //设置默认主页面 
 rg_bottom_tag.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  fragment = getFragment();
    switchFragment(mContent, fragment);

}

}

3.5_得到Fragment
/** 
 * 得到Fragment 
 * @return 
 */ 
 private BaseFragment getFragment() { 
 if(mBaseFragments != null){ 
 BaseFragment baseFragment = mBaseFragments.get(position); 
 return baseFragment; 
 } 
 return null; 
 }
3.6_切换Fragment
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(); 
 }
4_软件框架性能优化
4.1_解决切换Fragment切换导致重新创建Fragment问题
在项目中切换Fragment,一直都是用replace()方法来替换Fragment。但是这样做有一个问题,每次切换的时候Fragment都会重新实列化,重新加载一次数据,这样做会非常消耗性能用用户的流量。
官方文档解释说:replace()这个方法只是在上一个Fragment不再需要时采用的简便方法。
正确的切换方式是add(),切换时hide(),add()另一个Fragment;再次切换时,只需hide()当前,show()另一个。
这样就能做到多个Fragment切换不重新实例化:
切换方法:
/** 
 * 切换不同的Fragment 
 * @param from 
 * @param to 
 */ 
 public void switchFragment(Fragment from, Fragment to) {
if (mContent != to) {
    mContent = to;
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    if (!to.isAdded()) {
      // 先判断是否被add过
        if(from != null){
            transaction.hide(from);
        }
        if(to != null){
            transaction.add(R.id.fl_content, to).commit(); 
        }

    } else {
        if(from != null){
            transaction.hide(from);
        }
        if(to != null){
            transaction.show(to).commit(); 
        }
    }
}

}

4.2_解决横竖屏切换导致的Fragment内容重叠问题

在功能清单文件配置
5_常用框架页面功能实现
5.1_常用框架页面布局fragment_common_frame.xml
5.2_常用框架页面代码

public class CommonFrameFragment extends BaseFragment {

private static final String TAG = CommonFrameFragment.class.getSimpleName();

private ListView mListview;
private String [] datas;
private CommonFrameFragmentAdapter adapter;
@Override
protected View initView() {
    Log.e(TAG,"常用框架页面初始化了...");
    View view = View.inflate(mContext, R.layout.fragment_common_frame,null);
    mListview = (ListView) view.findViewById(R.id.listview);
    mListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            String data = datas[position];
            Toast.makeText(mContext, "data=="+data, Toast.LENGTH_SHORT).show();
        }
    });
    return view;
}

@Override
protected void initData() {
    super.initData();
    Log.e(TAG, "常用框架数据初始化了...");

    //准备数据
    datas = new String[]{ "OKHttp", "xUtils3","Retrofit2","Fresco","Glide","greenDao","RxJava","volley","Gson","FastJson","picasso","evenBus","jcvideoplayer","pulltorefresh","Expandablelistview","UniversalVideoView","....."};

    //设置适配器
    adapter = new CommonFrameFragmentAdapter(mContext,datas);
    mListview.setAdapter(adapter);
}

}

5.3_常用框架页面适配器
重新创建一个新包,com.atguigu.android.adapter
public class CommonFrameFragmentAdapter extends BaseAdapter { 
 private final Context mContext; 
 private final String[] mDatas;
public CommonFrameFragmentAdapter(Context context,String[] datas){
    this.mContext = context;
    this.mDatas = datas;
}
@Override
public int getCount() {
    return mDatas.length;
}

@Override
public Object getItem(int position) {
    return null;
}

@Override
public long getItemId(int position) {
    return 0;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    TextView textView = new TextView(mContext);
    textView.setPadding(10, 10, 0, 10);
    textView.setText(mDatas[position]);
    textView.setTextColor(Color.BLACK);
    textView.setTextSize(20);
    return textView;
}

}

“`