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

概述

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


代码详解


1. 主界面布局解析。



// RadioButton抽取style


// RadioButton选择器

    
    

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


完整代码


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




    

    

    

        

        

        

        

        

    


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();
            }
        }
    }
}


最终效果

你可能感兴趣的:(Android应用主界面Tab切换框架详解之Fragment)