TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】

您所在的位置:网站首页 代码创建viewpager TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】

TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】

2023-03-13 20:57| 来源: 网络整理| 查看: 265

版权声明:本文为HaiyuKing原创文章,转载请注明出处!

前言

使用TabLayout搭配ViewPager实现可滑动的顶部选项卡效果。

效果图

代码分析

1、演示常规的设置。

2、通过自定义ViewPager(MyCustomViewPager)解决解决切换需要经过中间页的问题、实现控制viewpager是否可滑动的功能;

3.1、通过在Fragment中的OnCreateView中判断rootView是否为空来解决viewpager+fragment来回滑动fragment重新加载的问题;

3.2、还有一个方案是在自定义的viewpager适配器类中重写destroyItem方法,来解决重新加载的问题;【核心就是不销毁fragment】

4、通过自定义Fragment基类(BaseLazyFragment)来实现配合viewpager使用时禁止懒加载的功能;

存在一个问题:那就是当选项卡比较多的时候,从首页切换到尾页,然后切换回来首页的时候,会重新请求数据,因为首页已经销毁了,执行了onDestroyView方法。

解决方案:

一、使用setOffscreenPageLimit()方法, 设置数字越大越好(可以设置总数目);

二、采用3.2方案;

使用步骤 一、项目组织结构图

注意事项:

1、 导入类文件后需要change包名以及重新import R文件路径

2、 Values目录下的文件(strings.xml、dimens.xml、colors.xml等),如果项目中存在,则复制里面的内容,不要整个覆盖

二、导入步骤 引入依赖库

在APP的build.gradle文件中添加以下代码【注意:版本号和com.android.support:appcompat-v7保持一致】

注意:TabLayout为5.0之后的新控件,所以styles.xml中的主题应该使用Theme.AppCompat.Light.NoActionBar或者Theme.AppCompat.Light等Theme.AppCompat.XXX的主题

apply plugin: 'com.android.application' android { compileSdkVersion 25 buildToolsVersion "25.0.3" defaultConfig { applicationId "com.why.project.tablayoutviewpagerdemo" minSdkVersion 15 targetSdkVersion 25 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(include: ['*.jar'], dir: 'libs') androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { exclude group: 'com.android.support', module: 'support-annotations' }) compile 'com.android.support:appcompat-v7:25.3.1' testCompile 'junit:junit:4.12' //TabLayout compile 'com.android.support:design:25.3.1' } 在colors.xml文件中添加以下代码:【后续可根据实际情况更改背景颜色、文字颜色值】 #3F51B5 #303F9F #FF4081 #00ffffff #3090d9 #191919 #3090d9 在dimens.xml文件中添加以下代码:【后续可根据实际情况更改底部选项卡区域的高度值、文字大小值】 16dp 16dp 10dp 18sp 3dp 在styles.xml文件中添加以下代码: @color/colorPrimary @color/colorPrimaryDark @color/colorAccent @dimen/tab_top_auto_title_size 在AndroidManifest.xml文件中添加网络请求的权限【demo中用到的】 三、使用方法 在Activity布局文件中引用TabLayout【注意更改MyViewpager的完整路径】 创建需要用到的fragment类和布局文件【后续可根据实际情况更改命名,并且需要重新import R文件】

fragment_web.xml文件布局如下

WebViewFragment

package com.why.project.tablayoutviewpagerdemo.fragment; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.webkit.WebView; import android.webkit.WebViewClient; import com.why.project.tablayoutviewpagerdemo.R; /** * @Created HaiyuKing * @Used 首页界面——碎片界面 */ public class WebViewFragment extends BaseLazyFragment{ private static final String TAG = "WebViewFragment"; /**View实例*/ private View myView; private WebView web_view; /**传递过来的参数*/ private String bundle_param; //重写 public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { //使用FragmentTabHost时,Fragment之间切换时每次都会调用onCreateView方法,导致每次Fragment的布局都重绘,无法保持Fragment原有状态。 //http://www.cnblogs.com/changkai244/p/4110173.html if(myView == null){ myView = inflater.inflate(R.layout.fragment_web, container, false); //接收传参 Bundle bundle = this.getArguments(); bundle_param = bundle.getString("param"); } //缓存的rootView需要判断是否已经被加过parent, 如果有parent需要从parent删除,要不然会发生这个rootview已经有parent的错误。 ViewGroup parent = (ViewGroup) myView.getParent(); if (parent != null) { parent.removeView(myView); } return myView; } @Override public void onActivityCreated(Bundle savedInstanceState) { //初始化控件以及设置 initView(); //初始化控件的点击事件 initEvent(); // TODO Auto-generated method stub super.onActivityCreated(savedInstanceState); } //实现禁止预加载的功能 @Override public void fetchData() { //初始化数据 initData(); } //实现禁止预加载的功能 @Override public void onInvisible() { } @Override public void onResume() { super.onResume(); } @Override public void onPause() { super.onPause(); } @Override public void onDestroy() { super.onDestroy(); } /** * 初始化控件 */ private void initView() { web_view = (WebView) myView.findViewById(R.id.web_view); //设置支持js脚本 // web_view.getSettings().setJavaScriptEnabled(true); web_view.setWebViewClient(new WebViewClient() { /** * 重写此方法表明点击网页内的链接由自己处理,而不是新开Android的系统browser中响应该链接。 */ @Override public boolean shouldOverrideUrlLoading(WebView webView, String url) { //webView.loadUrl(url); return false; } }); } /** * 初始化数据 */ public void initData() { Log.e("tag","{initData}bundle_param="+bundle_param); web_view.loadUrl(bundle_param);//加载网页 } /** * 初始化点击事件 * */ private void initEvent(){ } } BaseLazyFragment package com.why.project.tablayoutviewpagerdemo.fragment; import android.os.Bundle; import android.util.Log; /** * Used 主要实现配合viewpager使用时禁止懒加载 * 我们一般在onCreateView方法初始化视图,onActivityCreated方法初始化数据, * 通过setUserVisibleHint和getUserVisibleHint方法来设置和获取Fragment的显示状态,当显示了才去加载数据。 * * setUserVisibleHint: isVisibleToUser = false onAttach onCreate setUserVisibleHint: isVisibleToUser = true onCreateView onActivityCreated onStart onResume onPause onStop onDestroyView onDestroy onDetach 参考资料:https://blog.csdn.net/aiynmimi/article/details/73277836 */ public abstract class BaseLazyFragment extends BaseFragment{ private static final String TAG = BaseLazyFragment.class.getSimpleName(); /** * rootView是否初始化标志,防止回调函数在rootView为空的时候触发 */ protected boolean isViewInitiated;//view是否初始化 /** * 当前Fragment是否处于可见状态标志,防止因ViewPager的缓存机制而导致回调函数的触发 */ protected boolean isVisibleToUser;//是否可见 protected boolean isDataInitiated;//数据是否加载完成 @Override public void setUserVisibleHint(boolean isVisibleToUser) { Log.e(TAG,"{setUserVisibleHint}isVisibleToUser="+isVisibleToUser); super.setUserVisibleHint(isVisibleToUser); this.isVisibleToUser = isVisibleToUser; if(getUserVisibleHint()) { prepareFetchData(); } else { if(isViewInitiated){ onInvisible(); } } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); isViewInitiated = true; prepareFetchData(); } /** * 视图销毁的时候 Fragment是否初始化的状态变为false */ @Override public void onDestroyView() { Log.e(TAG,"{onDestroyView}"); super.onDestroyView(); isViewInitiated = false; isVisibleToUser = false; isDataInitiated = false; } //初始化数据 public abstract void fetchData(); //当隐藏的时候执行的方法 public abstract void onInvisible(); public boolean prepareFetchData() { return prepareFetchData(false); } /** * 请求数据 * @param forceUpdate : 是否强制请求数据*/ public boolean prepareFetchData(boolean forceUpdate) { if (isVisibleToUser && isViewInitiated && (!isDataInitiated || forceUpdate)) { fetchData(); isDataInitiated = true; return true; } return false; } }

BaseLazyFragment.java

创建选项卡子项model类TabItemModel package com.why.project.tablayoutviewpagerdemo.model; /** * Created by HaiyuKing * Used */ public class TabItemModel { private String tabTitle; private String tabUrl; public TabItemModel(String tabTitle, String tabUrl){ this.tabTitle = tabTitle; this.tabUrl = tabUrl; } public String getTabTitle() { return tabTitle; } public void setTabTitle(String tabTitle) { this.tabTitle = tabTitle; } public String getTabUrl() { return tabUrl; } public void setTabUrl(String tabUrl) { this.tabUrl = tabUrl; } } 创建viewpager的适配器 package com.why.project.tablayoutviewpagerdemo.adapter; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.view.ViewGroup; import com.why.project.tablayoutviewpagerdemo.model.TabItemModel; import java.util.List; /** * Created by HaiyuKing * Used 当viewpager中fragment数量多的时候用FragmentStatePagerAdapter,反之则用FragmentPagerAdapter。 */ public class ContentPagerAdapter extends FragmentStatePagerAdapter { private List tabIndicators; /**碎片集合*/ private List fragmentList; public ContentPagerAdapter(FragmentManager fm) { super(fm); // TODO Auto-generated constructor stub } /** * 自定义构造函数:用于传递碎片集合过来 * 一般都写上*/ public ContentPagerAdapter(FragmentManager fm, List tabIndicators, List fragmentList) { super(fm); this.tabIndicators = tabIndicators; this.fragmentList = fragmentList; } @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } @Override public CharSequence getPageTitle(int position) { return tabIndicators.get(position).getTabTitle(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { //viewpager+fragment来回滑动fragment重新加载的简单解决办法:注释下面的代码 //不建议使用,因为当选项卡过多的时候,如果不销毁的是,担心内存溢出 //http://blog.csdn.net/qq_28058443/article/details/51519663 super.destroyItem(container, position, object); } } MyCustomViewPager package com.why.project.tablayoutviewpagerdemo.viewpager; import android.content.Context; import android.support.v4.view.ViewPager; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * Created by HaiyuKing * Used 自定义的viewpager * https://www.cnblogs.com/tangs/articles/5933233.html * 解决切换需要经过中间页的问题; * 实现控制viewpager是否可滑动; * 解决视频播放器和viewpager滑动冲突问题【可扩展到任何view】; */ public class MyCustomViewPager extends ViewPager { /**是否可以滑动:默认可以滑动*/ private boolean isCanScroll = true; public MyCustomViewPager(Context context) { super(context); } public MyCustomViewPager(Context context, AttributeSet attrs) { super(context, attrs); } /** * 解决切换需要经过中间页 */ @Override public void setCurrentItem(int item) { //super.setCurrentItem(item);源码 super.setCurrentItem(item,false);//smoothScroll false表示切换的时候,不经过两个页面的中间页 } /** * 让ViewPager不能左右滑动 */ @Override public boolean onTouchEvent(MotionEvent ev) { if(isCanScroll){ return super.onTouchEvent(ev); }else{ return false; } } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { if(isCanScroll){ return super.onInterceptTouchEvent(ev); }else{ return false; } } /** * 暴露出去的方法,屏蔽ViewPager的滑动,默认不可滑动 * @param isCanScroll 为true可以左右滑动,为false不可滑动 */ public void setIsCanScroll(boolean isCanScroll){ this.isCanScroll = isCanScroll; } @Override protected boolean canScroll(View v, boolean checkV, int dx, int x, int y) { /*if (v instanceof IjkVideoView) {//解决视频播放器和viewpager滑动冲突问题 return true; }*/ return super.canScroll(v, checkV, dx, x, y); } }

MyCustomViewPager.java

在Activity中使用如下【继承FragmentActivity或者其子类】 package com.why.project.tablayoutviewpagerdemo; import android.os.Bundle; import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v7.app.AppCompatActivity; import com.why.project.tablayoutviewpagerdemo.adapter.ContentPagerAdapter; import com.why.project.tablayoutviewpagerdemo.fragment.WebViewFragment; import com.why.project.tablayoutviewpagerdemo.model.TabItemModel; import com.why.project.tablayoutviewpagerdemo.viewpager.MyCustomViewPager; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private TabLayout mTabLayout; private MyCustomViewPager mTabViewPager; private List tabIndicators; private List tabFragments; private ContentPagerAdapter contentAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initViews(); initDatas(); initEvents(); } private void initViews() { mTabLayout = (TabLayout) findViewById(R.id.tl_top); mTabViewPager = (MyCustomViewPager) findViewById(R.id.vp_tab); mTabViewPager.setOffscreenPageLimit(3);//禁止预加载【如果想要延迟首个选项卡的销毁时间,那么就需要设置这个数值高点】 } private void initDatas() { //初始化选项卡子项的文本、超链接model集合 tabIndicators = new ArrayList(); tabIndicators.add(new TabItemModel("百度","http://www.baidu.com")); tabIndicators.add(new TabItemModel("CSDN","http://blog.csdn.net")); tabIndicators.add(new TabItemModel("博客园","http://www.cnblogs.com")); tabIndicators.add(new TabItemModel("极客头条","http://geek.csdn.net/mobile")); tabIndicators.add(new TabItemModel("优设","http://www.uisdc.com/")); tabIndicators.add(new TabItemModel("玩Android","http://www.wanandroid.com/index")); tabIndicators.add(new TabItemModel("掘金","https://juejin.im/")); //初始化碎片集合 tabFragments = new ArrayList(); for(int i=0;i TabLayoutViewPagerDemo【TabLayout+ViewPager可滑动】的更多相关文章 Android TabLayout+ViewPager禁止滑动

1.重写ViewPager并重写覆盖ViewPager的onInterceptTouchEvent(MotionEvent arg0)方法和onTouchEvent(MotionEvent arg0) ...

关于TabLayout+ViewPager组合实现多页面滑动

转载请注明出处:http://blog.csdn.net/ht_android/article/details/46647711 在android提供的design library中新增了一个控件,叫 ...

011 Android TabLayout+ViewPager实现顶部滑动效果(多个页面)

1.TabLayout介绍 TabLayout提供了一个水平的布局用来展示Tabs,很多应用都有这样的设计,典型的有网易新闻,简书,知乎等.TabLayout就可以很好的完成这一职责,首先TabLay ...

浅谈TabLayout(ViewPager+Tab联动)

google发布了的Android Support Design库中提供了TabLayout 通过TabLayout+ViewPager实现导航栏效果,点击Tab ,ViewPager跟随变化,滑动V ...

介绍三个Android支持库控件:TabLayout+ViewPager+RecyclerView

本文主要介绍如下三个Android支持库控件的配合使用: TabLayout:android.support.design.widget.TabLayout ViewPager:android.sup ...

Android开发之漫漫长途 Fragment番外篇——TabLayout+ViewPager+Fragment

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了以及



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3