手把手教你如何搭建一个自己的安卓快速开发框架之带你做自己的APP(三)

版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/u012534831/article/details/70040106

点击查看上一篇文章:手把手教你如何搭建一个自己的安卓快速开发框架之带你做自己的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");
    }

}

很简单,做了一些初始化操作。我们的子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);

    }
}

因为暂时我们没有用到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));
        }
    } 

接下来,当我们点击底部每个按钮时:

    /**
     * 点击第一个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));
    }

这个方法用来判断到底是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;
    }

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

在布局和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"/>
   /**
    *Activity中
    */

    // 绑定要显示的View
    emptyView.bindView(content);

    // 注册点击事件,加载失败后点击重试执行onload方法
    emptyView.buttonClick(this, "onClick");

    在我们的onResponse中执行 emptyView.succees();方法
    在我们的onError中执行 emptyView.succees();方法
    在我们的onBefore中执行 emptyView.Loading();方法

原理就是利用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

猜你喜欢

转载自blog.csdn.net/u012534831/article/details/70040106