详解Android中fragment和viewpager的那点事儿

在之前的博文《Android 中使用 ViewPager实现屏幕页面切换和页面轮播效果》和《详解Android中Fragment的两种创建方式》以及《Android中fragment与activity之间的交互(两种实现方式)》中我们介绍了ViewPager以及Fragment各自的使用场景以及不同的实现方式。

那如果将他们两结合起来,会不会擦出点火花呢,答案是肯定的。之前在介绍ViewPager时,我们实现了多个ImageView的切换,并配合更新导航原点的状态。那我们现在就将之前的imageview替换为fragment,将导航原点替换为更加生动的布局,比如我们经常使用的微信(取消了ActionBar):

(1)我们可以通过点击下面的导航按钮选择对应的显示界面(fragment),如下图:

(2)我们也可以通过滑动界面(fragment)来实现界面切换,同时下面的导航按钮状态也会发生变化,如下图:

那么重点来了,这样的效果要怎么实现呢,大至分为以下的步骤

(1)布局文件中直接部署ViewPager以及下方的导航布局

(2)根据导航的个数来建立对应的fragment布局并建立配套的Fragment类(为方便后期扩展,建议建立与导航个数相同的fragments)

(3)drable下使用selector实现导航组件的形态变化

(4)通过FragmentPagerAdapter(V4包下)实现ViewPager与Fragment的关联

(5)设置下方导航的点击事件以及ViewPager的OnPageChangeListener方法实现对应的状态改变

第一步:layout中的主布局文件activity_main.xml文件

取消了actionBar,采用LinearLayout嵌套来实现主布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical" tools:context="com.example.administrator.viewpagerfragment.MainActivity">
 <LinearLayout
 android:background="@color/colorblack"
 android:padding="10dp"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 <TextView
 android:layout_width="0dp"
 android:layout_weight="1"
 android:gravity="center_vertical"
 android:layout_height="match_parent"
 android:layout_marginLeft="5dp"
 android:text="潘侯爷微信"
 android:textSize="20sp"
 android:textColor="@color/colorWhite"/>
 <ImageView
android:src="@mipmap/jy_drltsz_btn_addperson"
 android:adjustViewBounds="true"
 android:maxHeight="23dp"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />
 </LinearLayout>
 <android.support.v4.view.ViewPager
 android:id="@+id/viewPager"
 android:layout_width="match_parent"
 android:layout_height="0dp"
 android:layout_weight="1"/>
 <View
 android:layout_width="match_parent"
 android:layout_height="1dp"
 android:background="@color/colornormal"/>
 <LinearLayout
 android:orientation="horizontal"
 android:padding="5dp"
 android:layout_width="match_parent"
 android:layout_height="wrap_content">
 <LinearLayout
 android:id="@+id/weixin"
 android:clickable="true"
 android:orientation="vertical"
 android:layout_width="0dp"
 android:gravity="center"
 android:layout_weight="1"
 android:layout_height="wrap_content">
 <ImageView
 android:id="@+id/weixin_img"
android:background="@drawable/weixin_picture_selector"
 android:layout_width="30dp"
 android:layout_height="25dp" />
 <TextView
 android:id="@+id/weixin_txt"
 android:layout_width="wrap_content"
 android:gravity="center"
 android:layout_height="wrap_content"
 android:text="微信"
 android:textSize="12sp"
android:textColor="@drawable/weixin_text_selector"/>
 </LinearLayout>
 <LinearLayout
 android:id="@+id/contact"
 android:clickable="true"
 android:orientation="vertical"
 android:layout_width="0dp"
 android:gravity="center"
 android:layout_weight="1"
 android:layout_height="wrap_content">
 <ImageView
 android:id="@+id/contact_img"
android:background="@drawable/txl_picture_selector"
 android:layout_width="30dp"
 android:layout_height="25dp" />
 <TextView
 android:id="@+id/contact_txt"
 android:layout_width="wrap_content"
 android:gravity="center"
 android:layout_height="wrap_content"
 android:text="通讯录"
 android:textSize="12sp"
android:textColor="@drawable/weixin_text_selector"/>
 </LinearLayout>
 <LinearLayout
 android:id="@+id/find"
 android:clickable="true"
 android:orientation="vertical"
 android:layout_width="0dp"
 android:gravity="center"
 android:layout_weight="1"
 android:layout_height="wrap_content">
 <ImageView
 android:id="@+id/find_img"
android:background="@drawable/find_picture_selector"
 android:layout_width="30dp"
 android:layout_height="25dp" />
 <TextView
 android:id="@+id/find_txt"
 android:layout_width="wrap_content"
 android:gravity="center"
 android:layout_height="wrap_content"
 android:text="发现"
 android:textSize="12sp" android:textColor="@drawable/weixin_text_selector"/>
 </LinearLayout>
 <LinearLayout
 android:id="@+id/self"
 android:clickable="true"
 android:orientation="vertical"
 android:layout_width="0dp"
 android:gravity="center"
 android:layout_weight="1"
 android:layout_height="wrap_content">
 <ImageView
 android:id="@+id/self_img"
android:background="@drawable/me_picture_selector"
 android:layout_width="30dp"
 android:layout_height="25dp" />
 <TextView
 android:id="@+id/self_txt"
 android:layout_width="wrap_content"
 android:gravity="center"
 android:layout_height="wrap_content"
 android:text="我"
 android:textSize="12sp"
android:textColor="@drawable/weixin_text_selector"/>
 </LinearLayout>
 </LinearLayout>
</LinearLayout>

第二步:layout中fragment的布局文件(可自由扩展)

这里四个导航对应四个不同的fragment(实现上面的效果,也可以只建立一个fragment,但这样不利于后期扩展),这里我们只演示其中一个weixin_fragment.xml(其他三个为 contactListFragment; findFragment;selfFragment)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:orientation="vertical"
 android:layout_width="match_parent"
 android:layout_height="match_parent">
 <TextView
 android:id="@+id/tv"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:text="没有微信消息"
 android:gravity="center"
 android:textSize="50sp"/>
</LinearLayout>

第三步:drable中设定下方导航组件不同的形态

导航组件中文字形态变化只是颜色不同,图片的话需要设置点击前后不同的图片(这里演示一种)

(1)文字的变化wenxin_text_selector.xml

这里使用selected而不用checked的原因:个人使用的导航布局为linerlayout,并且为linerlayout设置chiclable而不是其中的Text/imageView,所以为了判断变化,这里使用了selected,方便代码中设置调用。

 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:color="@color/colorpressed" android:state_selected="true"/>
 <item android:color="@color/colornormal" android:state_selected="false" />
 </selector>

(2)图片的变化weixin_picture_selector.xml

 <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
 <item android:drawable="@mipmap/weixin_pressed" android:state_selected="true"/>
 <item android:drawable="@mipmap/weixin_normal" android:state_selected="false" />
 </selector>

第四步:Java中对应fragment布局的Fragment继承类

这里建议继承android.support.v4.app.Fragment包下的.Fragment,因为后面要用的FragmentPagerAdapter属于V4包,应该统一。

4个fragment对应4个java类,这里演示一个,其他三个都一样。

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
 * Created by panchengjia on 2016/12/24.
 */
public class WeixinFragment extends Fragment {
 @Nullable
 @Override
 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
 View view = inflater.inflate(R.layout.weixin_fragment,container,false);
 return view;
 }
}

第五步:java中功能实现MainActivity.java文件

代码中详细标注了各个实现步骤的注释,这里不再赘述(为了提高程序运行效率,很多重复方法未封装,代码看起来有点臃肿了)

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
 //声明存储fragment的集合
 private ArrayList<Fragment> fragments;
 //声明四个导航对应fragment
 WeixinFragment weixinFragment;
 ContactListFragment contactListFragment;
 FindFragment findFragment;
 SelfFragment selfFragment;
 //声明ViewPager
 private ViewPager viewPager;
 FragmentManager fragmentManager;//声明fragment管理
 //声明导航栏中对应的布局
 private LinearLayout weixin, contact, find, self;
 //声明导航栏中包含的imageview和textview
 private ImageView weixin_img, contact_img, find_img, self_img;
 private TextView weixin_txt, contact_txt, find_txt, self_txt;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 //初始化加载首页布局
 initView();
 //调用自定义initListener方法,为各个组件添加监听事件
 initListener();
 //设置默认选择的pager和导航栏的状态
 viewPager.setCurrentItem(0);
 weixin_img.setSelected(true);
 weixin_txt.setSelected(true);
 }
 private void initListener() {
 //为四大导航组件添加监听
 weixin.setOnClickListener(this);
 contact.setOnClickListener(this);
 find.setOnClickListener(this);
 self.setOnClickListener(this);
 //为viewpager添加页面变化的监听以及事件处理
 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
 @Override
 public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
 }
 @Override
 public void onPageSelected(int position) {
 //根据位置直接决定显示哪个fragment
 viewPager.setCurrentItem(position);
 switch (position) {
  case 0:
  weixin_img.setSelected(true);
  weixin_txt.setSelected(true);
  contact_img.setSelected(false);
  contact_txt.setSelected(false);
  find_img.setSelected(false);
  find_txt.setSelected(false);
  self_img.setSelected(false);
  self_txt.setSelected(false);
  break;
  case 1:
  weixin_img.setSelected(false);
  weixin_txt.setSelected(false);
  contact_img.setSelected(true);
  contact_txt.setSelected(true);
  find_img.setSelected(false);
  find_txt.setSelected(false);
  self_img.setSelected(false);
  self_txt.setSelected(false);
  break;
  case 2:
  weixin_img.setSelected(false);
  weixin_txt.setSelected(false);
  contact_img.setSelected(false);
  contact_txt.setSelected(false);
  find_img.setSelected(true);
  find_txt.setSelected(true);
  self_img.setSelected(false);
  self_txt.setSelected(false);
  break;
  case 3:
  weixin_img.setSelected(false);
  weixin_txt.setSelected(false);
  contact_img.setSelected(false);
  contact_txt.setSelected(false);
  find_img.setSelected(false);
  find_txt.setSelected(false);
  self_img.setSelected(true);
  self_txt.setSelected(true);
  break;
 }
 }
 @Override
 public void onPageScrollStateChanged(int state) {
 }
 });
 }
 private void initView() {
 //在主布局中根据id找到ViewPager
 viewPager = (ViewPager) findViewById(R.id.viewPager);
 //实例化所属四个fragment
 weixinFragment = new WeixinFragment();
 contactListFragment = new ContactListFragment();
 findFragment = new FindFragment();
 selfFragment = new SelfFragment();
 fragments = new ArrayList<>();
 //添加fragments到集合中
 fragments.add(weixinFragment);
 fragments.add(contactListFragment);
 fragments.add(findFragment);
 fragments.add(selfFragment);
 fragmentManager = getSupportFragmentManager();
 //为ViewPager设置适配器用于部署fragments
 viewPager.setAdapter(new MyFragmentPagerAdapter(fragmentManager));
 weixin = (LinearLayout) findViewById(R.id.weixin);
 contact = (LinearLayout) findViewById(R.id.contact);
 find = (LinearLayout) findViewById(R.id.find);
 self = (LinearLayout) findViewById(R.id.self);
 weixin_img = (ImageView) findViewById(R.id.weixin_img);
 contact_img = (ImageView) findViewById(R.id.contact_img);
 find_img = (ImageView) findViewById(R.id.find_img);
 self_img = (ImageView) findViewById(R.id.self_img);
 weixin_txt = (TextView) findViewById(R.id.weixin_txt);
 contact_txt = (TextView) findViewById(R.id.contact_txt);
 find_txt = (TextView) findViewById(R.id.find_txt);
 self_txt = (TextView) findViewById(R.id.self_txt);
 }
 /**
 * 设置导航栏的点击事件并同步更新对应的ViewPager
 * 点击事件其实就是更改导航布局中对应的Text/ImageView
 * 的选中状态,配合drable中的selector更改图片以及文字变化
 *
 * @param v
 */
 @Override
 public void onClick(View v) {
 switch (v.getId()) {
 case R.id.weixin:
 viewPager.setCurrentItem(0);
 weixin_img.setSelected(true);
 weixin_txt.setSelected(true);
 contact_img.setSelected(false);
 contact_txt.setSelected(false);
 find_img.setSelected(false);
 find_txt.setSelected(false);
 self_img.setSelected(false);
 self_txt.setSelected(false);
 break;
 case R.id.contact:
 viewPager.setCurrentItem(1);
 weixin_img.setSelected(false);
 weixin_txt.setSelected(false);
 contact_img.setSelected(true);
 contact_txt.setSelected(true);
 find_img.setSelected(false);
 find_txt.setSelected(false);
 self_img.setSelected(false);
 self_txt.setSelected(false);
 break;
 case R.id.find:
 viewPager.setCurrentItem(2);
 weixin_img.setSelected(false);
 weixin_txt.setSelected(false);
 contact_img.setSelected(false);
 contact_txt.setSelected(false);
 find_img.setSelected(true);
 find_txt.setSelected(true);
 self_img.setSelected(false);
 self_txt.setSelected(false);
 break;
 case R.id.self:
 viewPager.setCurrentItem(3);
 weixin_img.setSelected(false);
 weixin_txt.setSelected(false);
 contact_img.setSelected(false);
 contact_txt.setSelected(false);
 find_img.setSelected(false);
 find_txt.setSelected(false);
 self_img.setSelected(true);
 self_txt.setSelected(true);
 break;
 }
 }
 //创建FragmentPagerAdapter
 class MyFragmentPagerAdapter extends FragmentPagerAdapter {
 public MyFragmentPagerAdapter(FragmentManager fm) {
 super(fm);
 }
 @Override
 public android.support.v4.app.Fragment getItem(int position) {
 return fragments.get(position);
 }
 @Override
 public int getCount() {
 return fragments.size();
 }
 }
}

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持我们!

时间: 2016-12-23

Android基于ViewPager Fragment实现选项卡

先给大家展示效果图: 1.新建TestFragmen继承Fragment public class TestFragment extends Fragment { private static final String TAG = "TestFragment"; private String hello;// = "hello android"; private String defaultHello = "default value"; pri

Android实现Tab布局的4种方式(Fragment+TabPageIndicator+ViewPager)

Android现在实现Tab类型的界面方式越来越多,今天就把常见的实现方式给大家来个总结.目前写了: 1.传统的ViewPager实现 2.FragmentManager+Fragment实现 3.ViewPager+FragmentPagerAdapter实现 4.TabPageIndicator+ViewPager+FragmentPagerAdapter 1.传统的ViewPager实现 主要就是ViewPager+ViewAdapter这个还是比较常见的,就不多说了 效果图: 代码: p

Android中ViewPager获取当前显示的Fragment

前言 在项目中,有时会用到在ViewPager中显示同样类型的Fragment,同时这样的Fragment的个数是动态的,但是PagerAdapter没有给我们提供getCurrentFragment类似的方法.下面就给大家介绍下Android中ViewPager获取当前显示的Fragment的方法,一起看看吧. 一.使用 getSupportFragmentManager().findFragmentByTag()方法 Viewpager + FragmentPagerAdapter 情况下

Android App在ViewPager中使用Fragment的实例讲解

据说Android最推荐的是在ViewPager中使用FragMent,即ViewPager中的页面不像前面那样用LayoutInflater直接从布局文件加载,而是一个个Fragment.注意这里的Fragment 是android.support.v4.view包里的Fragment,而不是android.app包里的Fragment. 使用v4包里的Fragment的Activity必须继承自FragmentActivity. 其实使用Fragment与前面不使用Fragment非常类似:

Android中ViewPager和Fragment的使用

小案例 XML中 <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent"> </android.support.v4.view.ViewPager> 创建Fragment fragments = new Arr

Android中ViewPager实现滑动条及与Fragment结合的实例教程

自主实现滑动指示条 先上一个基本效果图: 1.XML布局 布局代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="m

Android 开发之BottomBar+ViewPager+Fragment实现炫酷的底部导航效果

BottomBar BottomBar是Github上的一个开源框架,因为从1.3.3开始不支持fragments了,要自己配置,弄了很久,不管是app的fragment还是V4 的程序总是总是闪退.于是就用这种方式实现了,效果还不错.github有详细说明,多余的就不说了. 这个roughike是这个项目的所有者(大神致敬). 我用的是Android studio开发,fragment全部导的V4的包(以为最开始就支持的是v4的,后面也支持了app.fragment). 首先是dependen

Android中ViewPager实现滑动指示条及与Fragment的配合

自主实现滑动指示条 先上效果图: 1.XML布局 布局代码如下: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match

Android App中ViewPager与Fragment结合的一些问题解决

在了解ViewPager的工作原理之前,先回顾ListView的工作原理: ListView只有在需要显示某些列表项时,它才会去申请可用的视图对象:如果为所有的列表项数据创建视图对象,会浪费内存: ListView找谁去申请视图对象呢? 答案是adapter.adapter是一个控制器对象,负责从模型层获取数据,创建并填充必要的视图对象,将准备好的视图对象返回给ListView: 首先,通过调用adapter的getCount()方法,ListView询问数组列表中包含多少个对象(为避免出现数组

Android App中使用ViewPager+Fragment实现滑动切换效果

在android应用中,多屏滑动是一种很常见的风格,没有采用viewpager的代码实现会很长,如果采用ViewPager,代码就会短很多,但是使用ViewPager也有弊端:需要导入android-support-v4.jar.细节无法控制.不过现在情况已经不一样了,android-support-v4中提供了很多实用的功能,以至于现在新建一个android工程默认都会导入这个jar包.那我们就也采用viewpager来做滑动吧.另外一个概念就是Fragment和FragmentActivit

Android App中ListView仿QQ实现滑动删除效果的要点解析

本来准备在ListView的每个Item的布局上设置一个隐藏的Button,当滑动的时候显示.但是因为每次只要存在一个Button,发现每个Item上的Button相互间不好控制.所以决定继承ListView然后结合PopupWindow. 首先是布局文件: delete_btn.xml:这里只需要一个Button <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=

Android App中制作仿MIUI的Tab切换效果的实例分享

1.概述 哈,今天给大家带来一个ViewPagerIndicator的制作,相信大家在做tabIndicator的时候,大多数人都用过TabPageIndicator,并且很多知名APP都使用过这个开源的指示器.大家有没有想过如何自己去实现这样的一个指示器,并且代码会有多复杂呢~~~今天,我就带领大家来从无到有的实现这样一个指示器,当然了,不准备一模一样,搞得没有创新似的,再看标题,跟MIUI相关,所以我们准备做一个特性与TabPageIndicator一致的,但是样子和MIUI的Tab一样的~

Android ViewPager + Fragment实现滑动页面效果

效果: PagerData类: package com.cloud.viewpagerdemo; import java.io.Serializable; class PagerData implements Serializable { private int mImageResId; private String mContent; PagerData(int imageResId, String content) { mImageResId = imageResId; mContent =

Android App中使用ViewPager实现滑动分页的要点解析

以前如果要做 Tab 分页的话,必须要用一个很难用的 TabActivity,而且做出来的效果很差,弹性也很小 忘了从什么时候开始,Google release 了 ViewPager 这好东西取代了以前难用的 Gallery 元件,加上从 Honeycomb 导入的 Fragment 之后终于能够简单做出好看又好用的 Layout 了! 这里我们采用PagerTabStrip ,做出来的效果如下 特色就是使用简单,出来的效果则是目前显示的分页 Tab 的文字会自动置中,然后分别在左右显示上一个

详解Android App中创建ViewPager组件的方法

现在很多app一打开就是一个ViewPager,然后可以用手指滑,每滑一次就换一张图,底下还会有圈圈表示说现在滑到第几章~ 通常这些图片都是放功能简介或是使用教学之类的,我的需求很简单,就是上面提到的那样而已. 有两种做法,一种是找现有套件,查了一堆资料每个都跟我推荐ViewPagerIndicator这套,我之前也看过这套,只是看起来需要有fragment再加上google play范例好像载不到了,所以只好自己实做一个. Viewpager的实作可参考Android ViewPager使用详

Android开发中如何解决Fragment +Viewpager滑动页面重复加载的问题

前言 之前在做一个Viewpager上面加载多个Fragment时总会实例化已经创建好的Fragmnet对象类似 viewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) { @Override public Fragment getItem(int position) { switch(position){ case 0: fragments=new Fragmnet01(); break; case

Android App中ViewPager所带来的滑动冲突问题解决方法

叙述 滑动冲突可以说是日常开发中比较常见的一类问题,也是比较让人头疼的一类问题,尤其是在使用第三方框架的时候,两个原本完美的控件,组合在一起之后,忽然发现整个世界都不好了. 关于滑动冲突 滑动冲突分类: 滑动冲突,总的来说就是两类. 1.同方向滑动冲突 比如ScrollView嵌套ListView,或者是ScrollView嵌套自己 2.不同方向滑动冲突 比如ScrollView嵌套ViewPager,或者是ViewPager嵌套ScrollView,这种情况其实很典型.现在大部分应用最外层都是

Android 中使用 ViewPager实现屏幕页面切换和页面轮播效果

之前关于如何实现屏幕页面切换,写过一篇博文<Android中使用ViewFlipper实现屏幕切换>,相比ViewFlipper,ViewPager更适用复杂的视图切换,而且Viewpager有自己的adapter,这也让其适应复杂对象,实现数据的动态加载. ViewPager是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api.而viewpager就是其中之一,利用它,我们可以做很多事情,从最简单的导航,到页面菜单等等. 下面我们就展示下Vie

Android开发之使用ViewPager实现图片左右滑动切换效果

Android中图片的左右切换随处可见,今天我也试着查阅资料试着做了一下,挺简单的一个小Demo,却也发现了一些问题,话不多说,上代码~: 使用了3个xml文件作为ViewPager的滑动page,布局都是相同的,如下只展示其中之一: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/