Android ViewPager制作新手导航页(动态加载)

我们来讲个老生常谈的话题,估计大家都用过的—>ViewPager,用它来做新手导航页面,虽然这次也是讲这个,但是和以往的用法可能有些不同,大家都看到标题进来的,应该知道的是:动态加载指示器。

什么叫动态加载呢,是不是感觉很高大上呢,其实呢就是动态的去加载指示器的数量的,而不是在布局文件中写死。希望看了这篇文章大家对ViewPager有新的认识。

看到这个效果大家应该都很不屑吧,今天讲这个就是为了让大家有新的认识。好了,好好听,开始了。

这个动态加载就是为了动态的加载下面的灰色圆点指示器和红色圆点指示器,大家有没有注意到当我滑动的时候(即切换页面的时候)红色圆点会跟着移动。没错。

第一步:

在布局文件中添加ViewPager,并添加灰色圆点和红色圆点的布局,先来想想都用什么布局呢,首先三个灰色圆点可以用线性布局,一个红色圆点可以采用相对布局(原因:其实红色圆点就是覆盖在灰色圆点上)

 <RelativeLayout
    android:id="@+id/rl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="30dp" >
    <!--灰色圆点的布局-->
    <LinearLayout
      android:id="@+id/ll"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="horizontal" >
    </LinearLayout>
  </RelativeLayout>

第二步:

在onCreate方法中声明ViewPager和灰色圆点和红色圆点布局的示例(原因:因为我们需要动态加载圆点),并为ViewPager添加适配器和监听器。

  //ViwePager
  private ViewPager viewPager;
  //存放三个灰色圆点的线性布局
  private LinearLayout ll;
  //用来存放红色圆点和灰色圆点的相对布局
  private RelativeLayout rl;
  //初始化组件
  private void initView() {
    viewPager = (ViewPager)   findViewById(R.id.viewPager);
    imageViews = new ArrayList<ImageView>();
    ll = (LinearLayout) findViewById(R.id.ll);
    rl = (RelativeLayout) findViewById(R.id.rl);
    btn = (Button) findViewById(R.id.btn);
  //为ViewPager添加适配器
  viewPager.setAdapter(new MyAdapter());
  viewPager.setOnPageChangeListener();

第三步:

将三个图片加到ViewPager的适配器中。

注:为了在滑动的时候不重复创建图片实例,所以我们可以先将需要加载的资源的放在一个集合中,当每次滑动需要加载的时候就从集合中取出即可,这样节省了系统资源。

//导航页资源
  private int[] images = new int[]{
    R.drawable.guide_1,
    R.drawable.guide_2,
    R.drawable.guide_3,
  };
  //用来存放导航图片实例(保证唯一性,滑动的时候不重复创建)
  private List<ImageView> imageViews;
    //初始化导航页面
    for (int i = 0; i < images.length; i++) {
      ImageView iv = new ImageView(MainActivity.this);
      iv.setImageResource(images[i]);
      imageViews.add(iv);
    }
    //PagerAdapter有四个方法
  class MyAdapter extends PagerAdapter {
    //返回导航页的个数
    @Override
    public int getCount() {
      return images.length;
    }
    //判断是否由对象生成
    @Override
    public boolean isViewFromObject(View view,Object object) {
      return view == object;
    }
    //加载页面
    //ViewGroup:父控件指ViewPager
    //position:当前子控件在父控件中的位置
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
      ImageView iv = imageViews.get(position);
      container.addView(iv);
      return iv;
    }
    //移除页面
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
      container.removeView((View) object);
    }
  }

第四步:

重要的部分来了,这一步是动态的将灰色圆点和红色圆点添加进来,并让红色圆点随着滑动也跟着一起滑动。

首先动态的添加灰色圆点和红色圆点:

for (int i = 0; i < images.length; i++) {
      ImageView iv = new ImageView(MainActivity.this);
      iv.setImageResource(images[i]);
      imageViews.add(iv);
      //动态加载灰色圆点
      ImageView gray_Iv = new ImageView(this);
      gray_Iv.setImageResource(R.drawable.grar_circle);
      LinearLayout.LayoutParams layoutParams =
          new LayoutParams(LayoutParams.WRAP_CONTENT,
              LayoutParams.WRAP_CONTENT);
      //从第二个开始有边距
      if (i > 0) {
        layoutParams.leftMargin = 20;  //注意单位是px
      }
      gray_Iv.setLayoutParams(layoutParams);
      ll.addView(gray_Iv);
    }
    //添加红色圆点
    red_Iv = new ImageView(this);
    red_Iv.setImageResource(R.drawable.red_circle);
    rl.addView(red_Iv);

注:灰色圆点是从第二个开始有左边距的,为组件动态的设置边距的话使用布局的LayoutParams(衣服),记住三个灰色圆点使用的是哪个布局就采用那种布局的LayoutParams来进行设置。

下面就是让红色圆点随着ViewPager滑动也跟着一起滑动:

//任何一个组件都可以得到视图树
    red_Iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
      //视图完成绘制的时候调用
      @Override
      public void onGlobalLayout() {
        left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
        System.out.println(left);
        //移除视图树的监听
        red_Iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      }
    });
    //导航页滑动的时候调用
      //positionOffset:滑动的百分比([0,1})
      @Override
      public void onPageScrolled(int position, float positionOffset, int arg2) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
        layoutParams.leftMargin = (int) (left * positionOffset + position * left);
        red_Iv.setLayoutParams(layoutParams);
      }

注:这里需要明白一个概念–>视图树,为什么要明白这个呢,因为我们是动态的将灰色圆点添加进去,不知道这个视图什么才能绘制好,所以需要监听到整个视图的绘制状态,任何一个组件都可以拿到视图树,对视图树的绘制进行监听。这样就可以得到灰色圆点之间的距离,大家又会问一开始添加灰色圆点的时候不是设置了左边距吗???是的,但是这个单位是px,而现在是dp不能直接设置。

灰色圆点之间的距离:

left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
public void onPageScrolled(int position, float positionOffset, int arg2)中参数positionOffset指滑动的百分比(范围[0-1))

现在就可以知道红色圆点需要滑动多少了。

      //导航页滑动的时候调用
      //positionOffset:滑动的百分比([0,1))
      @Override
      public void onPageScrolled(int position, float positionOffset, int arg2) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
        layoutParams.leftMargin = (int) (left * positionOffset + position * left);
        red_Iv.setLayoutParams(layoutParams);
      }

第五步:

新手导航页,一般移动到最后一页的时候会有个按钮跳到主界面。这个只需要在导航页被选择的时候设置一下即可

//导航页被选择的时候调用
      @Override
      public void onPageSelected(int position) {
        //滑动到最后一页,显示按钮
        if (position == images.length - 1) {
          btn.setVisibility(View.VISIBLE);
        //不是最后一页,不显示按钮
        }else {
          btn.setVisibility(View.GONE);
        }
      }

核心代码:

布局文件:

<RelativeLayout 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_parent"
  tools:context="com.example.viewpager.MainActivity" >

  <android.support.v4.view.ViewPager
    android:id="@+id/viewPager"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
  </android.support.v4.view.ViewPager>

  <RelativeLayout
    android:id="@+id/rl"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="30dp" >
    <!--灰色圆点的布局-->
    <LinearLayout
      android:id="@+id/ll"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="horizontal" >
    </LinearLayout>

  </RelativeLayout>
  <Button
    android:layout_width="wrap_content"
    android:id="@+id/btn"
    android:layout_alignParentBottom="true"
    android:layout_centerHorizontal="true"
    android:layout_marginBottom="50dp"
    android:layout_height="wrap_content"
    android:text="体验"
    android:visibility="gone"
    />
</RelativeLayout>

MainActivity.java

public class MainActivity extends Activity {
  //ViwePager
  private ViewPager viewPager;
  private Button btn;
  //导航页资源
  private int[] images = new int[]{
    R.drawable.guide_1,
    R.drawable.guide_2,
    R.drawable.guide_3,
  };
  //圆点与圆点之间的边距
  private int left;
  //用来存放导航图片实例(保证唯一性,滑动的时候不重复创建)
  private List<ImageView> imageViews;
  //存放三个灰色圆点的线性布局
  private LinearLayout ll;
  //用来存放红色圆点和灰色圆点的相对布局
  private RelativeLayout rl;
  //红色圆点ImageView
  private ImageView red_Iv;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    initView();
    //初始化导航页面和灰色圆点
    for (int i = 0; i < images.length; i++) {
      ImageView iv = new ImageView(MainActivity.this);
      iv.setImageResource(images[i]);
      imageViews.add(iv);
      //动态加载灰色圆点
      ImageView gray_Iv = new ImageView(this);
      gray_Iv.setImageResource(R.drawable.grar_circle);
      LinearLayout.LayoutParams layoutParams =
          new LayoutParams(LayoutParams.WRAP_CONTENT,
              LayoutParams.WRAP_CONTENT);
      //从第二个开始有边距
      if (i > 0) {
        layoutParams.leftMargin = 20;  //注意单位是px
      }
      gray_Iv.setLayoutParams(layoutParams);
      ll.addView(gray_Iv);
    }
    red_Iv = new ImageView(this);
    red_Iv.setImageResource(R.drawable.red_circle);
    rl.addView(red_Iv);
    //任何一个组件都可以得到视图树
    red_Iv.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
      //视图完成绘制的时候调用
      @Override
      public void onGlobalLayout() {
        left = ll.getChildAt(1).getLeft() - ll.getChildAt(0).getLeft();
        System.out.println(left);
        //移除视图树的监听
        red_Iv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
      }
    });
    //为ViewPager添加适配器
    viewPager.setAdapter(new MyAdapter());
    viewPager.setOnPageChangeListener(new OnPageChangeListener() {
      //导航页被选择的时候调用
      @Override
      public void onPageSelected(int position) {
        if (position == images.length - 1) {
          btn.setVisibility(View.VISIBLE);
        }else {
          btn.setVisibility(View.GONE);
        }
      }
      //导航页滑动的时候调用
      //positionOffset:滑动的百分比([0,1})
      @Override
      public void onPageScrolled(int position, float positionOffset, int arg2) {
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) red_Iv.getLayoutParams();
        layoutParams.leftMargin = (int) (left * positionOffset + position * left);
        red_Iv.setLayoutParams(layoutParams);
      }
      //导航页滑动的状态改变的时候调用
      @Override
      public void onPageScrollStateChanged(int arg0) {

      }
    });
  }
  //初始化组件
  private void initView() {
    viewPager = (ViewPager) findViewById(R.id.viewPager);
    imageViews = new ArrayList<ImageView>();
    ll = (LinearLayout) findViewById(R.id.ll);
    rl = (RelativeLayout) findViewById(R.id.rl);
    btn = (Button) findViewById(R.id.btn);
  }
  //PagerAdapter有四个方法
  class MyAdapter extends PagerAdapter {
    //返回导航页的个数
    @Override
    public int getCount() {
      return images.length;
    }
    //判断是否由对象生成
    @Override
    public boolean isViewFromObject(View view,Object object) {
      return view == object;
    }
    //加载页面
    //ViewGroup:父控件指ViewPager
    //position:当前子控件在父控件中的位置
    @Override
    public Object instantiateItem(ViewGroup container, int position) {
      ImageView iv = imageViews.get(position);
      container.addView(iv);
      return iv;
    }
    //移除页面
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
      container.removeView((View) object);
    }
  }
}

大家赶紧试试吧。会有不同的认识。

以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。

(0)

相关推荐

  • Android动态给ViewPager添加Indicator导航

    先看下效果 小圆点的形状和颜色都是可以自己定义的,看需求 首先第一步,滑2个圆点,一个是选中后的圆点,一个是未选中的圆点,看选中的圆点shape <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > &l

  • Android ViewPager导航小圆点实现无限循环效果

    之前用View Pager做了一个图片切换的推荐栏(就类似与淘宝.头条客户端顶端的推荐信息栏),利用View Pager很快就能实现,但是一次无意间使用淘宝APP的时候,突然发现它的效果和我做的还不一样,淘宝APP的推荐栏可以左右无限循环切换,而ViewPager自身其实并没有支持这个功能. 其实实现这个无限循环不难,只需要在数据源的首尾各添加一张多余的图片,在onPagerChangeListener()中监听position<1和position>(总数据条目-1)就可以了.另外一点需要注

  • Android使用ViewPager实现导航

    首先先了解ViewPager实现的出效果是能够使视图左右滑动. ViewPager在XML文件中的声明和其他一些控件的声明有点儿不一样 而android.support.v4.view是Android界面特殊效果的第三方加载的jar包,能够向下兼容. <android.support.v4.view.ViewPager ... ... > </android.support.v4.view.ViewPager> 加载显示的页卡:需要将layout布局文件转型为View对象 (1)

  • ViewPager顶部导航栏联动效果(标题栏条目多)

    如果标题栏过多,超过屏幕的宽度,该怎么弄,下面我们就来解决一下,效果如下: 其实和之前写的也差不多,我就是在哪个demo里面添加和修改了一下,就加了几个title标题,加了几个图片,最重要的是给TableLayout添加了一个属性: app:tabMode="scrollable" 这个属性就是设置设置TableLayout可以滚动,看我滚动上面的标题栏: 这里我还给标题栏设置了几个附加的属性,让它显得更好看: <span style="white-space:pre&

  • Android 中 TabHost与ViewPager结合实现首页导航效果

    今天发的是TabHost结合ViewPager实现首页底部导航的效果,虽然说网上有很多这样的Demo,不过呢,我还是要把自己练习写的发出来,没错!就是这么任性: 先上效果图,如下: 代码里面有注释,就不过多解释了,说几点需要注意的问题 1:TabHost .TabWidget.FrameLayout一定添加id这个属性,否则会报错 android:id="@android:id/tabhost" android:id="@android:id/tabcontent"

  • 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自定义ViewPagerIndicator实现炫酷导航栏指示器(ViewPager+Fragment)

    ViewPagerIndicator导航栏指示器运行效果: 实现这个效果,我是看了很多大神写的博客和视频后自己敲的,欢迎指正 github地址:https://github.com/dl10210950/TabViewPagerIndicator 自定义一个ViewPagerIndicator 自定义一个Indicator继承LinearLayout,在构造方法里面设置画笔的一些属性 public ViewPagerIndicator(Context context, AttributeSet

  • Android中TabLayout+ViewPager 简单实现app底部Tab导航栏

    前言 在谷歌发布Android Design Support Library之前,app底部tab布局的实现方法就有很多种,其中有RadioGroup+FrameLayout.TabHost+Fragment.FragmentPagerAdapter+ViewPager等方法,虽然这些方法虽然能达到同样的效果,但我个人总觉得有些繁琐.然而,Google在2015的IO大会上,给开发者们带来了全新的Android Design Support Library,里面包含了许多新控件,这些新控件有许多

  • Android 利用ViewPager+GridView实现首页导航栏布局分页效果

    最近我尝试使用ViewPager+GridView实现的,看起来一切正常,废话不多说,具体代码如下: 如图是效果图 首先分析下思路 1.首先是怎么布局:整体是一个ViewPager将GridView作为一个View添加到ViewPager的adapter中,下方是圆点 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.a

  • Android ViewPager制作新手导航页(动态加载)

    我们来讲个老生常谈的话题,估计大家都用过的->ViewPager,用它来做新手导航页面,虽然这次也是讲这个,但是和以往的用法可能有些不同,大家都看到标题进来的,应该知道的是:动态加载指示器. 什么叫动态加载呢,是不是感觉很高大上呢,其实呢就是动态的去加载指示器的数量的,而不是在布局文件中写死.希望看了这篇文章大家对ViewPager有新的认识. 看到这个效果大家应该都很不屑吧,今天讲这个就是为了让大家有新的认识.好了,好好听,开始了. 这个动态加载就是为了动态的加载下面的灰色圆点指示器和红色圆点

  • Android开发实现的ViewPager引导页功能(动态加载指示器)详解

    本文实例讲述了Android开发实现的ViewPager引导页功能(动态加载指示器).分享给大家供大家参考,具体如下: 先看效果图咯~ 现在几乎每个App都会有引导页,是不是感觉很炫很厉害,所以就想做出来一个学习一下~让自己的App看起来更加的美观~ 现在来分析一下: 这个引导页可以分为俩部分~ 1.小红点--来提醒这是第几页了~ 2."开始体验"这个Button--可以进入主界面,但是要控制这个Button只能在最后一页出现 布局的话使用相对布局~ 那现在来看看布局吧: activi

  • Android ViewPager动态加载问题

    今天做项目时,纠结了很久,动态添加view,刚开始按照其他的adapter处理,但是不会刷新view,来回翻几页,还会view覆盖,最后手动调用adapter的destroyItem和instantiateItem方法,还是不行,最后重写notifyDataSetChanged中removeAllViews和instantiateItem,有点效果,可是还是不理想.最后查询资料要重写PagerAdapter的方法 如下: public int getItemPosition(Object obj

  • Android应用开发中Fragment的静态加载与动态加载实例

    1.Fragment的静态使用 Fragment是作为Activity的UI的一部分,它内嵌在Activity中,多个Fragment可以把一个Activity分成多个部分,这在大屏幕手机或者平板电脑中会比较多的用到,这样就不用使用多个Activity来切换这么麻烦了.当然Fragment也可以不显示,只在后台处理一些数据,这篇文章中就暂时不谈到这个.以下来看怎么静态地在Activity的布局文件中添加Fragment. 自定义的Fragment通常要继承Fragment这个类,也有一些特殊的是

  • Android开发中Listview动态加载数据的方法示例

    本文实例讲述了Android开发中Listview动态加载数据的方法.分享给大家供大家参考,具体如下: 最近在研究网络数据加载的问题,比如我有几百,甚至上千条数据,这些数据如果一次性全部加载到arraylist,然后再加载到Listview中.我们必然会去单独开线程来做,这样造成的结果就是会出现等待时间很长,用户体验非常不好.我的想法是动态加载数据,第一次加载十条,然后往下面滑动的时候再追加十条,再往下面滑动的时候再去追加,这样大大减少了用户等待的时间,同时给处理数据留下了时间.网上看到了这样一

  • Android 中动态加载.jar的实现步骤

    首先第一个是 jar 文件的制作,Java 里面直接把 .class 文件打包到 .jar 文件里面就可以了,但是 Android 的 Dalvik VM 是不认 Java 的 byte code 的,所以不能直接这么打包,而要用 dx 工具转成 Dalvik byte code 才可以.当然,dx 工具转了之后,jar 包里面就不 是 .class 文件了,而是 .dex 文件. 第二个是,Android 里面虽然也提供了 URLClassLoader 的实现,但是并不能用.要动态加载其它类,

  • Android实现listview动态加载数据分页的两种方法

    在android开发中,经常需要使用数据分页,比如要实现一个新闻列表的显示,或者博文列表的显示,不可能第一次加载就展示出全部,这就需要使用分页的方法来加载数据,在android中Handler经常用来在耗时的工作中,它接收子线程发送的数据,并使用数据配合更新UI,AsyncTask是在一个线程中执行耗时操作然后把结果传给UI线程,不需要你亲自去管理线程和句柄. 一.使用Handler+线程方法 1.基础知识 Handler在android系统中,主要负责发送和接收消息,它的用途主要有以下两种:

  • Android 动态加载二维码视图生成快照的示例

    1.需求背景 需要实现一个动态加载但不显示出来的视图,且该视图上有个动态生成的二维码,最后用其去生成一张快照(也就是图片). (常见这种情况是来源于"图片分享"的功能需求,与普通图片分享不同在于,该快照图片是动态加载不显示的.) 2.需求功能拆解 动态二维码的实现 动态视图生成快照的实现 3.踩坑点提要 获取不到动态视图的bitmap 无法获取最新动态视图的bitmap 4.开发实现 动态加载的视图的布局文件代码: <?xml version="1.0" en

  • Android动态加载布局

    ListView我们一直都在用,只不过当Adapter中的内容比较多的时候我们有时候没办法去设置一些组件,举个例子: 可以看到京东的故事里面的这样一个布局,这个布局可以说是我目前见到的内容比较多的了,它的每一项都包含头像.姓名.分类.内容.图片.喜欢.评论.分享以及喜欢的头像.分析了一下布局之后我们不难发现,除了喜欢头像这部分,其余的都很好实现. 那么下面着重说一下这个头像这部分怎么实现? 第一种方案:我们可以用GridView来实现,GridView和ListView的用法是一样的,俗称九宫格

  • Android插件化之资源动态加载

    Android插件化之资源动态加载 一.概述 Android插件化的一个重要问题就是插件资源访问问题,先列出会面对的问题 1.如何加载插件资源 2.如何处理插件资源与宿主资源的处突:插件化资源问题要做到的效果是,如果我们要获取的资源在插件中找得到,则加载优先加载插件的,如果找不到,则到宿主资源中找.这样能做到动态更新的效果. 3.如何确保插件和宿主使用到的是被修改过的资源. 二.原理分析 在做一件事之前必须先弄清楚原理,所以,这里先要弄清楚Android的资源体系原理. 1.资源链 Contex

随机推荐