Android应用主界面Tab切换框架详解之Fragment

来源:互联网 发布:js 读取ios沙盒文件 编辑:程序博客网 时间:2024/05/18 16:16

概述

  • 时下APP主流主界面Tab切换框架之一 --- Fragment 的搭建。
  • Fragment作为内容区域:MainActivity只作为一个调度器,支配Fragment的显示和隐藏,使得管理的控件事件等不需放在MainActivity中造成代码冗长,便于复用及后期维护。
  • 解决 ' 切换Tab反复初始化Fragment影响性能、增加流量消耗 ' 问题。
  • 解决 ' 横竖屏切换导致内容重叠 ' 问题。
  • 源码:https://github.com/tyyecec/EczomFrame


代码详解


1. 主界面布局解析。

<RadioButton    style="@style/tab_style"    android:id="@+id/rb_e"    android:drawableTop="@drawable/rb_e_selector" />// RadioButton抽取style<style name="tab_style">    <item name="android:layout_width">0dp</item>    <item name="android:layout_height">wrap_content</item>    <item name="android:layout_gravity">center_vertical</item>    <item name="android:button">@null</item>    <item name="android:background">@null</item>    <item name="android:gravity">center</item>    <item name="android:layout_weight">1</item>    <item name="android:paddingTop">8dp</item></style>// RadioButton选择器<selector xmlns:android="http://schemas.android.com/apk/res/android">    <item android:state_checked="true" android:drawable="@drawable/e_pressed"  />    <item android:drawable="@drawable/e_normal"  /></selector>

2. 创建BaseFragment抽象类继承Fragment便于代码复用。

// 在onCreate()中getActivity()得到上下文bfContext// 在onCreateView()中initView()// 在onActivityCreated()中initData()// 由子类实现不同的视图效果public abstract View initView();// 子类需联网请求数据时重写public void initData() { }

3. 创建EFragment | CFragment | ZFragment | OFragment | MFragment继承BaseFragment,另四个类将E改为对应字母。

public class EFragment extends BaseFragment {    private TextView textView;    @Override    public View initView() {        textView = new TextView(bfContext);        textView.setGravity(Gravity.CENTER);        textView.setTextSize(70);        return textView;    }    @Override    public void initData() {        super.initData();        textView.setText("E");    }}

4. 在MainActivity onCreate()中initFragment(),初始化各Fragment 。

// 各Fragment实例private EFragment eFragment;private CFragment cFragment;private ZFragment zFragment;private OFragment oFragment;private MFragment mFragment;private void initFragment() {    eFragment = new EFragment();    cFragment = new CFragment();    zFragment = new ZFragment();    oFragment = new OFragment();    mFragment = new MFragment();}

5. 在MainActivity onCreate()中initListener(),监听RadioGroup选择事件。

private void initListener() {    rgTab.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {        @Override        public void onCheckedChanged(RadioGroup radioGroup, int i) {            Fragment fragment = null;            switch (i) {                case R.id.rb_e:                    fragment = eFragment;                    break;                case R.id.rb_c:                    fragment = cFragment;                    break;                case R.id.rb_z:                    fragment = zFragment;                    break;                case R.id.rb_o:                    fragment = oFragment;                    break;                case R.id.rb_m:                    fragment = mFragment;                    break;            }            // 切换对应Fragment            switchFragment(cacheFragment, fragment);        }    });    // 默认选择E    rgTab.check(R.id.rb_e);}

6. 切换对应Fragment 。

由于replace()会导致每次切换Tab都重新初始化Fragment,造成性能上的影响及流量的多余消耗。此次,采用add() + hide() + show()的方式实现Fragment只初始化一次。

7. 解决 ' 切换Tab反复初始化Fragment影响性能、增加流量消耗 ' 问题。

// 当前Fragment缓存private Fragment cacheFragment;private void switchFragment(Fragment nowFragment, Fragment toFragment) {    if (nowFragment != toFragment) {        // 缓存即将切换的Fragment,以便下一次对比判断        cacheFragment = toFragment;        // 开启事物        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();        // 判断即将切换的Fragment是否add过        if (!toFragment.isAdded()) {            // 初始无缓存,需判断            if (nowFragment != null) {                // 隐藏当前Fragment                ft.hide(nowFragment);            }            // 添加即将切换的Fragment,并提交事物            ft.add(R.id.fl_main, toFragment).commit();        } else {            // 初始无缓存,需判断            if (nowFragment != null) {                // 隐藏当前Fragment                ft.hide(nowFragment);            }            // 显示即将切换的Fragment,并提交事物            ft.show(toFragment).commit();        }    }}

8. 解决 ' 横竖屏切换导致内容重叠 ' 问题。

// AndroidManifest.xml中配置configChanges属性,禁止切换时重新加载Activity<activity    android:name=".activity.MainActivity"    android:configChanges="orientation|screenSize|keyboardHidden" />


完整代码


1. 欢迎界面 --- WelcomeActivity.java

package com.eczom.eczomframe.activity;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.os.Handler;import com.eczom.eczomframe.R;public class WelcomeActivity extends Activity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_welcome);        //2s后进入主界面        new Handler().postDelayed(new Runnable() {            @Override            public void run() {                startActivity(new Intent(WelcomeActivity.this,MainActivity.class));                finish();            }        },2000);    }}

2. 主界面 --- activity_main.xml

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.eczom.eczomframe.activity.MainActivity">    <include layout="@layout/title" />    <FrameLayout        android:id="@+id/fl_main"        android:layout_width="match_parent"        android:layout_height="0dp"        android:layout_weight="1"        android:background="#DDDDDD" />    <RadioGroup        android:id="@+id/rg_tab"        android:layout_width="match_parent"        android:layout_height="50dp"        android:background="#ffffff"        android:orientation="horizontal">        <RadioButton            style="@style/tab_style"            android:id="@+id/rb_e"            android:drawableTop="@drawable/rb_e_selector" />        <RadioButton            android:id="@+id/rb_c"            style="@style/tab_style"            android:drawableTop="@drawable/rb_c_selector" />        <RadioButton            android:id="@+id/rb_z"            style="@style/tab_style"            android:drawableTop="@drawable/rb_z_selector" />        <RadioButton            android:id="@+id/rb_o"            style="@style/tab_style"            android:drawableTop="@drawable/rb_o_selector" />        <RadioButton            android:id="@+id/rb_m"            style="@style/tab_style"            android:drawableTop="@drawable/rb_m_selector" />    </RadioGroup></LinearLayout>

3. 主界面 --- MainActivity.java

package com.eczom.eczomframe.activity;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentTransaction;import android.widget.RadioGroup;import com.eczom.eczomframe.R;import com.eczom.eczomframe.fragment.CFragment;import com.eczom.eczomframe.fragment.EFragment;import com.eczom.eczomframe.fragment.MFragment;import com.eczom.eczomframe.fragment.OFragment;import com.eczom.eczomframe.fragment.ZFragment;import butterknife.BindView;import butterknife.ButterKnife;public class MainActivity extends FragmentActivity {    @BindView(R.id.rg_tab)    RadioGroup rgTab;    // 各Fragment实例    private EFragment eFragment;    private CFragment cFragment;    private ZFragment zFragment;    private OFragment oFragment;    private MFragment mFragment;    // 当前Fragment缓存    private Fragment cacheFragment;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ButterKnife.bind(this);        initFragment();        initListener();    }    private void initFragment() {        // 初始化各Fragment        eFragment = new EFragment();        cFragment = new CFragment();        zFragment = new ZFragment();        oFragment = new OFragment();        mFragment = new MFragment();    }    private void initListener() {        // 监听RadioGroup选择事件        rgTab.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {            @Override            public void onCheckedChanged(RadioGroup radioGroup, int i) {                Fragment fragment = null;                switch (i) {                    case R.id.rb_e:                        fragment = eFragment;                        break;                    case R.id.rb_c:                        fragment = cFragment;                        break;                    case R.id.rb_z:                        fragment = zFragment;                        break;                    case R.id.rb_o:                        fragment = oFragment;                        break;                    case R.id.rb_m:                        fragment = mFragment;                        break;                }                // 切换对应Fragment                switchFragment(cacheFragment, fragment);            }        });        // 默认选择E        rgTab.check(R.id.rb_e);    }    private void switchFragment(Fragment nowFragment, Fragment toFragment) {        if (nowFragment != toFragment) {            // 缓存即将切换的Fragment,以便下一次对比判断            cacheFragment = toFragment;            // 开启事物            FragmentTransaction ft = getSupportFragmentManager().beginTransaction();            // 判断即将切换的Fragment是否add过            if (!toFragment.isAdded()) {                // 初始无缓存,需判断                if (nowFragment != null) {                    // 隐藏当前Fragment                    ft.hide(nowFragment);                }                // 添加即将切换的Fragment,并提交事物                ft.add(R.id.fl_main, toFragment).commit();            } else {                // 初始无缓存,需判断                if (nowFragment != null) {                    // 隐藏当前Fragment                    ft.hide(nowFragment);                }                // 显示即将切换的Fragment,并提交事物                ft.show(toFragment).commit();            }        }    }}


最终效果

0 0
原创粉丝点击