手把手教你如何搭建一个自己的安卓快速开发框架之带你做自己的APP(三)
点击查看上一篇文章:手把手教你如何搭建一个自己的安卓快速开发框架之带你做自己的APP(二)
继上一篇我们的进一步封装,包含
- OkhttpRequest
 - EventBus
 - Json解析,基类数据封装
 - ButterKnife
 
那么,这一篇,我准备加入:
- BaseFragment
 - 精美的仿微信底部菜单栏
 - 网络请求失败时如何显示空View
 
继续来完善我们的快速开发框架。
1、开门见山,看下BaseFragment都做了些什么?
/**
 * Created by QHT on 2017-04-08.
 */
public abstract class BaseFragment extends Fragment
{
    /**
     * 依附的activity
     */
    protected FragmentActivity mActivity;
    /**
     * 根view
     */
    protected View mRootView;
    @Override
    @Nullable
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState)
    {
        if (getContentViewId() != 0) {
            mRootView= inflater.inflate(getContentViewId(), null);
        } else {
            mRootView= super.onCreateView(inflater, container, savedInstanceState);
        }
        ButterKnife.bind(this, mRootView);
        LogUtil.e(this.getClass().getName()+"--->onCreateView");
        initData(getArguments());
        return mRootView;
    }
    @Override
    public void onAttach(Context context)
    {
        super.onAttach(context);
        mActivity = getActivity();
    }
    /**
     * 设置根布局资源id
     * @return
     */
    public abstract int getContentViewId();
    /**
     * 初始化数据
     * @param arguments 接收到的从其他地方传递过来的参数
     */
    protected void initData(Bundle arguments)
    {
    }
    @Override
    public void onResume() {
        super.onResume();
        LogUtil.e(this.getClass().getName()+"--->onResume");
    }
    @Override
    public void onStop() {
        super.onStop();
        LogUtil.e(this.getClass().getName()+"--->onStop");
    }
    @Override
    public void onDestroy() {
        super.onDestroy();
        LogUtil.e(this.getClass().getName()+"--->onDestroy");
    }
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 
很简单,做了一些初始化操作。我们的子Fragment只需要继承并重写2个方法即可。
public class FragmentSecond extends BaseFragment {
  @Override
    public int getContentViewId() {
        return R.layout.fragment_second;
    }
    @Override
    protected void initData(Bundle arguments) {
        super.initData(arguments);
    }
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 
因为暂时我们没有用到viewpage,所以不需要懒加载,等下面用到了的时候再加进去。
2、接下来看看我们的仿微信底部菜单栏是怎么做的? 
MainActivity的布局呢,就是上面一个toolbar,中间一个Linearlayout用来显示Fragment,下面一个Ralativelayout容纳4个按钮
首先,初始化我们的Fragment状态,第一个fragment为默认加载的Fragment
    /**
     * 初始化底部标签
     */
    private void initTab() {
        if (oneFragment == null) {
        /** 默认加载第一个Fragment*/
            oneFragment = new FragmentFrist();
        }
        if (!oneFragment.isAdded()) {
       /** 如果第一个未被添加,则添加到管理器中*/
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.content_layout, oneFragment).commit();
       /** 记录当前Fragment*/
            currentFragment = oneFragment;
       /** 设置图片文本的变化*/  
llBottomIvOne.setImageResource(R.mipmap.bottom_home_click);
llBottomTvOne.setTextColor(getResources()
                    .getColor(R.color.bottom_click));
            llBottomIvTwo.setImageResource(R.mipmap.bottom_notice_normal);
llbottomTvTwo.setTextColor(getResources().getColor(
                    R.color.bottom_normal));
           llBottomIvThree.setImageResource(R.mipmap.bottom_bill_normal);
llBottomTvThree.setTextColor(getResources().getColor(
                    R.color.bottom_normal));          
            llBottomIvFour.setImageResource(R.mipmap.bottom_me_normal);
llBottomTvFour.setTextColor(getResources().getColor(
                    R.color.bottom_normal));
        }
    } 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 
接下来,当我们点击底部每个按钮时:
    /**
     * 点击第一个tab
     */
    private void clickTab1Layout() {
        if (oneFragment == null) {
            oneFragment = new FragmentFrist();
        }
        addOrShowFragment(getSupportFragmentManager().beginTransaction(), oneFragment);
llBottomIvOne.setImageResource(R.mipmap.bottom_home_click);
llBottomTvOne.setTextColor(getResources()
                .getColor(R.color.bottom_click));
        llBottomIvTwo.setImageResource(R.mipmap.bottom_notice_normal);
llbottomTvTwo.setTextColor(getResources().getColor(
                R.color.bottom_normal));
        llBottomIvThree.setImageResource(R.mipmap.bottom_bill_normal);
llBottomTvThree.setTextColor(getResources().getColor(
                R.color.bottom_normal));
        llBottomIvFour.setImageResource(R.mipmap.bottom_me_normal);
llBottomTvFour.setTextColor(getResources().getColor(
                R.color.bottom_normal));
    }
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 
这个方法用来判断到底是add还是show/hide 我们的Fragment
/**
     * 添加或者显示碎片
     *
     * @param transaction
     * @param fragment
     */
    private void addOrShowFragment(FragmentTransaction transaction,
                                   Fragment fragment) {
        if (currentFragment == fragment)
            return;
        if (!fragment.isAdded()) { 
        // 如果当前fragment未被添加,则添加到Fragment管理器中
            transaction.hide(currentFragment)
                    .add(R.id.content_layout,        
                    fragment).commit();
           } else {
        // 如果当前fragment已被添加,则显示即可
transaction.hide(currentFragment).show(fragment).commit();
        }
        currentFragment = fragment;
    }
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 
3、再来看看我们的空View是怎么实现的呢?
在使用listview时我们见过 setEmptyView() 方法(内部实现原理也是通过 Visible 去控制显示的),但是其他的 view 却没有吧,因此我们实现一个自己的空 View,在什么时候都可以使用。 
public class EmptyViewLayout extends RelativeLayout {
    private ImageView failure;//加载失败的图片
    private View bindView;// 绑定的View,即要显示的View
    private Button loading_btn;//重试按钮
    public EmptyViewLayout(Context context) {
        super(context);
        initView(context);
    }
    public EmptyViewLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context);
    }
    private void initView(Context context) {
        View view =              LayoutInflater.from(context).inflate(R.layout.empty_view,null);
        failure = (ImageView)view.findViewById(R.id.loading_failure);
        loading_btn= (Button) view.findViewById(R.id.loading_btn);
        //设置View参数
        LinearLayout.LayoutParams param = new LinearLayout.LayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
        //最后添加进ViewGroup
        addView(view, param);
    }
    /**
     *正在加载中
     */
    public void Loading() {
        setVisibility(View.VISIBLE);
        if (bindView != null) {
            failure.setVisibility(View.GONE);
            loading_btn.setVisibility(View.GONE);
        }
    }
    /**
     *加载成功
     */
    public void succees() {
        setVisibility(View.GONE);
        if (bindView != null) {
            bindView.setVisibility(View.VISIBLE);
        }
    }
    /**
     *加载失败
     */
    public void failure() {
        setVisibility(View.VISIBLE);
        if (bindView != null) {
            failure.setVisibility(View.VISIBLE);
            bindView.setVisibility(View.GONE);
            loading_btn.setVisibility(View.VISIBLE);
        }
    }
    // 绑定加载 的view
    public void bindView(View view) {
        this.bindView = view;
    }
    /*
     * 利用反射机制,响应对方需要响应的方法
     */
    public void buttonClick(final Object base, final String method) {
        loading_btn.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                  Method m=base.getClass().getDeclaredMethod(method);
                         m.setAccessible(true);
                         m.invoke(base, null);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
}
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 
在布局和Activity中我们这样使用:
   /**
    *布局中
    */
 <com.qht.blog2.View.EmptyViewLayout
        android:id="@+id/emptyView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@+id/toolbar"/>
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 
   /**
    *Activity中
    */
    // 绑定要显示的View
    emptyView.bindView(content);
    // 注册点击事件,加载失败后点击重试执行onload方法
    emptyView.buttonClick(this, "onClick");
    在我们的onResponse中执行 emptyView.succees();方法
    在我们的onError中执行 emptyView.succees();方法
    在我们的onBefore中执行 emptyView.Loading();方法
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 
- 1
 - 2
 - 3
 - 4
 - 5
 - 6
 - 7
 - 8
 - 9
 - 10
 - 11
 - 12
 - 13
 - 14
 
原理就是利用View的Visible和Gone去控制显示哪个View。
下一篇,我准备开始实现功能了: 
(因为我们刚开始选用的接口为快递100的,所以功能上考虑为一款快递查询APP)
- Fragment 和 ViewPage 结合实现顶部标签切换
 - RecycleView 实现精美的订单追踪页面
 
我的QQ: 1003077897 
我的csdn:http://blog.csdn.net/u012534831 
我的github:https://github.com/qht1003077897/AppFrame 
我的个人博客:https://qht1003077897.github.io
                    
                
                
            
        
浙公网安备 33010602011771号