第一讲 _软件框架的搭建
1_启动页面 (LauncherActivity)
1.1_启动页面的布局
<? xml version= "1.0" encoding= "utf-8" ?> <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android :layout_width= "match_parent" android :layout_height= "match_parent" android :background= "#ffffff" > <ImageView android :id= "@+id/iv_icon" android :layout_width= "wrap_content" android :layout_height= "wrap_content" android :layout_centerInParent= "true" android :src= "@drawable/atguigu_logo" /> <TextView android :layout_width= "wrap_content" android :layout_height= "wrap_content" android :layout_below= "@id/iv_icon" android :layout_centerHorizontal= "true" android :text= " 尚硅谷 Android 世界 ..." android :textSize= "18sp" /> </RelativeLayout >
1.2_启动页面的代码
延迟两秒进入主页面
package com.atguigu.atguigu.activity; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import com.atguigu.atguigu.R; /** * 作用:启动页面 */ public class LauncherActivityextends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_launcher ); new Handler().postDelayed(new Runnable() { @Override public void run() { startMainActivity(); } }, 2000 ); } /** * 启动主页面 */ private void startMainActivity() { Intent intent = new Intent(this ,MainActivity.class ); startActivity(intent); finish(); } }
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
package com.atguigu.atguigu.base; 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; /** * 作用:基类 Fragment * CommonFrameFragment,ThirdParty,CustomFragment,OtherFragment 等类继承它 */ public abstract class BaseFragment extends Fragment { /** * 上下文 */ protected ContextmContext ; /** * 该 Fragment 是否被初始化过 */ private boolean isInit =false ; @Override public void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); mContext = getActivity(); } @Nullable @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 StringTAG = 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 CustomFragmentextends BaseFragment { private static final StringTAG = 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 ThirdPartyFragmentextends BaseFragment { private static final StringTAG = 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 OtherFragmentextends BaseFragment { private static final StringTAG = 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 MyOnCheckedChangeListenerimplements 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 内容重叠问题
在功能清单文件配置
<activity android :name= ".activity.MainActivity" android :configChanges= "orientation|keyboardHidden|screenSize" > </activity >
5_常用框架页面功能实现
5.1_常用框架页面布局 fragment_common_frame.xml
<? xml version= "1.0" encoding= "utf-8" ?> <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" android :layout_width= "match_parent" android :layout_height= "match_parent" > <ListView android :id= "@+id/listview" android :layout_width= "match_parent" android :layout_height= "match_parent" /> </RelativeLayout >
5.2_常用框架页面代码
/** * 作用:常用框架 */ public class CommonFrameFragmentextends BaseFragment { private static final StringTAG = CommonFrameFragment.class .getSimpleName(); private ListView mListview ; private String [] datas ; private CommonFrameFragmentAdapteradapter ; @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 CommonFrameFragmentAdapterextends BaseAdapter { private final ContextmContext ; 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; } }