ViewPager(懒加载)+Fragment+自定义View
来源:互联网 发布:手机延时软件 编辑:程序博客网 时间:2024/06/16 17:46
主界面的UI与设计
现在一般的项目都是底部几个按钮对应这几个fragment这种情况,这种大体上可以有2种写法
- FragmentTabHost/(RadiuGroup+RadiuButton)等等一些底部按钮+Fragment来展示
- 一些底部按钮+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
- ViewPager(懒加载)+Fragment+自定义View
- ViewPager+Fragment懒加载
- Viewpager Fragment懒加载
- ViewPager+Fragment懒加载
- ViewPager+Fragment懒加载
- viewPager fragment 懒加载
- fragment viewpager 懒加载
- ViewPager加载Fragment懒加载
- ViewPager+Fragment自定义View滑动条
- viewpager+fragment的懒加载
- ViewPager实现Fragment懒加载
- viewpager+fragment 懒加载操作
- ViewPager+Fragment懒加载方式
- viewpager嵌套Fragment懒加载
- viewpager fragment 实现懒加载
- Android ViewPager + Fragment懒加载
- ViewPager + Fragment实现懒加载
- ViewPager+Fragment实现懒加载
- Mybatis之Mapper动态代理
- 自己实现Struts2(五)实现StrutsPrepareAndExecuteFilter
- Servlet与JSP思维导图
- L1-2. 点赞
- android7.0闪退问题java.lang.SecurityException: MODE_WORLD_READABLE no longer supported
- ViewPager(懒加载)+Fragment+自定义View
- EventBus学习笔记(三)
- LaTeX初学知识点总结
- L1-3. 情人节
- Android热修复技术初览
- eclipse下配置tomcat
- POJ 1847 火车变轨道 (简单最短路)
- 算法第五周解题报告
- TensorFlow使用的一个小案例