ViewPager(懒加载)+Fragment+自定义View

来源:互联网 发布:手机延时软件 编辑:程序博客网 时间:2024/06/16 17:46

主界面的UI与设计

现在一般的项目都是底部几个按钮对应这几个fragment这种情况,这种大体上可以有2种写法

  1. FragmentTabHost/(RadiuGroup+RadiuButton)等等一些底部按钮+Fragment来展示
  2. 一些底部按钮+ViewPager+Fragment来实现

这两种我个人更喜欢使用的是第二种,并且在最近的项目中也是用第二种方式来实现的,如果产品说底部按钮对应的页面是不能够滑动的,那么两种没什么区别,(viewPager可以禁止滑动来实现)可后来如果产品又说需要滑动了,那如果用第一种实现的就傻了,而第二种默认就是可以滑动的只需要简单的修改一下就可以

public class ViewPagerMain  extends ViewPager{    private boolean mIsScroll=true;//通过这个值来判断是否需要禁止滑动    public ViewPagerMain(Context context) {        super(context);    }    public ViewPagerMain(Context context, AttributeSet attrs) {        super(context, attrs);    }    @Override    public boolean onInterceptTouchEvent(MotionEvent ev) {        if (mIsScroll==true){            return super.onInterceptTouchEvent(ev);        }else{            return mIsScroll;        }    }    @Override    public boolean onTouchEvent(MotionEvent ev) {        if (mIsScroll==true){            return super.onTouchEvent(ev);        }else{            return mIsScroll;        }    }    public void setIsScroll(boolean isScroll){        mIsScroll = isScroll;    }}

至于底部的那些按钮我并没有使用上面的一些Android原生控件,而是通过
布局文件自己摆放,我个人认为这样的话扩展性更高一些,当然这只是一部分原因后面的代码大家可以看到这么写的好处
底部xml

<LinearLayout    android:id="@+id/main_bottom_root"    android:layout_width="match_parent"    android:layout_height="@dimen/y96"    android:background="#fff"    >    <LinearLayout        android:id="@+id/home_root"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:orientation="vertical"        android:gravity="center"        >        <LinearLayout            android:layout_width="wrap_content"            android:layout_height="match_parent"            android:orientation="vertical"            android:gravity="center"            >            <ImageView                android:id="@+id/iv_home"                style="@style/bottom_iv"                android:background="@drawable/home_selector"                />            <TextView                android:id="@+id/tv_home"                style="@style/main_tv"                android:text="晒e晒"                />        </LinearLayout>    </LinearLayout>    <LinearLayout        android:id="@+id/rb_message"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:orientation="vertical"        android:gravity="center"        >        <ImageView            android:id="@+id/iv_message"            style="@style/bottom_iv"            android:background="@drawable/message_selector" />        <TextView            android:id="@+id/tv_message"            style="@style/main_tv"            android:text="消息"            />    </LinearLayout>    <LinearLayout        android:id="@+id/rb_service"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:orientation="vertical"        android:gravity="center"        >        <ImageView            style="@style/bottom_iv"            android:background="@drawable/service_selector"            android:id="@+id/iv_service" />        <TextView            android:id="@+id/tv_service"            style="@style/main_tv"            android:text="服务"            />    </LinearLayout>    <LinearLayout        android:id="@+id/rb_find"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:orientation="vertical"        android:gravity="center"        >        <ImageView            android:id="@+id/iv_find"            style="@style/bottom_iv"            android:background="@drawable/find_selector" />        <TextView            android:id="@+id/tv_find"            style="@style/main_tv"            android:text="发现"            />    </LinearLayout>    <LinearLayout        android:id="@+id/rb_my"        android:layout_width="0dp"        android:layout_height="match_parent"        android:layout_weight="1"        android:orientation="vertical"        android:gravity="center"        >        <ImageView            android:id="@+id/iv_mine"            style="@style/bottom_iv"            android:background="@drawable/mine_selector" />        <TextView            android:id="@+id/tv_mine"            style="@style/main_tv"            android:text="我的"            />    </LinearLayout></LinearLayout>/** * 监听底部按钮的切换状态,mMainBottomRoot为底部按钮的根布局,这样封装的话如果底部按钮的数量有变动 * 这段代码不用发生什么变动,而且下一个项目用到的话直接复制粘贴private void setBottomListener() {    int childCount = mMainBottomRoot.getChildCount();    for (int i = 0; i <childCount ; i++) {        //获得子布局,为每个子view设置点击事件        LinearLayout child = (LinearLayout) mMainBottomRoot.getChildAt(i);        child.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                //通过mMainBottomRoot来获得点击view对应的索引值                int indexOfChild = mMainBottomRoot.indexOfChild(view);                //根据索引来改变UI效果                changeUI(indexOfChild);                //viewPager也跳到对应的Fragment中                mViewpagerMain.setCurrentItem(indexOfChild, false);            }        });    }}/** *  当viewPager切换的时候更改底部按钮的UI状态 * @param position */private void changeUI(int position) {    for (int i = 0; i <mMainBottomRoot.getChildCount() ; i++) {        if (i==position){            setEnable(mMainBottomRoot.getChildAt(i),false);        }else{            setEnable(mMainBottomRoot.getChildAt(i),true);        }    }}/** * 更改底部按钮UI状态,如果是view直接setEnable,如果是viewGroup递归遍历其中的view setEnable * @param childAt * @param b */private void setEnable(View childAt, boolean b) {    childAt.setEnabled(b);    if (childAt instanceof ViewGroup){        for (int i = 0; i < ((ViewGroup) childAt).getChildCount(); i++) {            setEnable(((ViewGroup) childAt).getChildAt(i),b);        }    }}

至于Fragment 我这里对Fragment展示的布局做了进一步封装,因为现在项目的主界面大体上不外呼刚进来时候弹个ProgressBar,DialogFragmen等与用户进行交互,当数据请求回来再隐藏销毁,如果数据请求失败再展示个失败的界面
这里我对它又进行了一次封装,不仅减少了代码的书写也加强了扩展性和维护性
/**
* BaseFragment
*/

public abstract class MyBaseFragment extends Fragment {    protected Context context;    protected StateLayout stateLayout;    protected boolean isFirst = true;    protected boolean isPrepared;    private Unbinder mUnbinder;    @Override    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {        context = getActivity();        //防止Fragment重复加载        if (stateLayout == null) {            // 说明这个Fragemnt的onCreateView方法是第一次执行            View view = getContentView();            mUnbinder = ButterKnife.bind(this, view);            //对Fragment展示的布局进一步封装            stateLayout = StateLayout.newInstance(context, view);            initView();            initListener();            //            isPrepared = true;        } else {            ViewGroup parent = (ViewGroup) stateLayout.getParent();            if (parent != null) {                parent.removeView(stateLayout);            }        }        return stateLayout;    }    /**     * Fragment当前状态是否可见     */    protected boolean isVisible;    @Override    public void setUserVisibleHint(boolean isVisibleToUser) {        super.setUserVisibleHint(isVisibleToUser);        if (isVisibleToUser) {            isVisible = true;            LogUtil.e(getClass().getName()+"__________setUserVisibleHint");            onVisible();        } else {            isVisible = false;            onInvisible();        }    }    @Override    public void onResume() {        super.onResume();        LogUtil.e(getClass().getName()+"__________onResume");        onVisible();    }    /**     * 对initData再进一步的封装     */    protected void onVisible() {        //保证ViewPager能够实现懒加载的方式并保证只有第一次进入这个Fragment的时候才进行数据的加载        LogUtil.e("isFirst _____________" + isFirst);        LogUtil.e("isVisible _____________" + isVisible);        LogUtil.e("isPrepared _____________" + isPrepared);        if (!isFirst || !isVisible || !isPrepared) {            return;        }        initData();        isFirst = false;    }    /**     * 不可见     */    protected void onInvisible() {    }    /**     * 查找View,增加这个方法是为了略强转     *     * @param id     * @return     */    @SuppressWarnings("unchecked")    public <T> T findView(int id) {        T view = (T) stateLayout.findViewById(id);        return view;    }    @Override    public void onDestroy() {        super.onDestroy();        if (mUnbinder!=null){            mUnbinder.unbind();        }    }    /**     * 返回Fragment自己的名称     */    protected  CharSequence getTitle(){        return getClass().getName();    };    /**     * 初始化View相关的代码写在这个方法中     */    public abstract void initView();    /**     * 初始化Listener的代码写在这个方法中     */    public abstract void initListener();    /**     * 初始化数据的代码写在这个方法中     */    public abstract void initData();    /**     * 返回正常的界面想要展示的View或View的Id     */    public abstract View getContentView();}
public class StateLayout extends FrameLayout {    private View loadingView;    private View failView;    private View emptyView;    private View contentView;    public StateLayout(Context context, AttributeSet attrs) {        super(context, attrs);    }    /**     * 创建一个StateLayout实现     * @param contentView 正常想要展示的View     */    public static StateLayout newInstance(Context context, View contentView) {        StateLayout stateLayout = (StateLayout) LayoutInflater.from(context).inflate(R.layout.state_layout, null);        stateLayout.contentView=contentView;        // StateLayout inflate之后就有3个状态的View了,还需要第四种状态        stateLayout.addView(contentView);        //当添加完成后暂时给隐藏掉        contentView.setVisibility(View.GONE);        return stateLayout;    }    /**     * 渲染完毕后展示获取view对象     */    @Override    protected void onFinishInflate() {        loadingView = findViewById(R.id.loadingView);        failView = findViewById(R.id.failView);        emptyView = findViewById(R.id.emptyView);        showLoadingView();    }    /** 显示正在加载的View */    public void showLoadingView() {        showView(loadingView);    }    /** 显示失败的View */    public void showFailView() {        showView(failView);    }    /** 显示加载为空的View */    public void showEmptyView() {        showView(emptyView);    }    /** 显示正常界面的View */    public void showContentView() {        showView(contentView);    }    /**      * 显示指定的View,并且隐藏其它的View     * @param view 指定要显示的View     */    private void showView(View view) {        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i); //            child.setVisibility(view == child ? View.VISIBLE : View.GONE);        }    }}

具体的我就不细说了,
有需要的话可以
下来看看https://github.com/wangrun1992/MainUiFrame

1 0