手把手教你如何搭建一个自己的安卓快速开发框架之带你做自己的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

posted @ 2017-04-25 10:21  天涯海角路  阅读(233)  评论(0)    收藏  举报