新建一个工程,取名引导页面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;
}
}
“`