文档章节

android开发笔记之ViewPager新手导航页(动态加载指示器)

Mr_Nice
 Mr_Nice
发布于 2016/05/22 20:00
字数 2082
阅读 21
收藏 0
点赞 2
评论 0

今天我们来讲个老生常谈的话题,估计大家都用过的—>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);
        }
    }
}

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

© 著作权归作者所有

共有 人打赏支持
Mr_Nice
粉丝 0
博文 47
码字总数 39947
作品 0
广州
Android UI 特效大全

Android UI特效大全 总体传送门:http://git.oschina.net/bob4j/Android-UI 基本上项目中都有效果图可自行查看 , 并且有些项目中都有README.md 文件,使用前请先阅读以下。 1.弧形(圆形)菜单...

不正经啊不正经
2015/07/31
0
0
android中ViewPager详解--视图滑动、界面卡等效果 (一)

这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api。而viewpager就是其中之一。利用它,我们可以做很多事情,从最简单的导航,到页面菜单...

一别经年
2014/01/21
0
0
Android ViewPager使用详解

这是谷歌官方给我们提供的一个兼容低版本安卓设备的软件包,里面包囊了只有在安卓3.0以上可以使用的api。而viewpager就是其中之一利用它,我们可以做很多事情,从最简单的导航,到页面菜单等...

Remix_jx
2014/10/27
0
0
android 三种实现水平向滑动方式(ViewPager、ViewFilpper、ViewF...

ViewPager ViewPager类提供了多界面切换的新效果。新效果有如下特征: [1] 当前显示一组界面中的其中一个界面。 [2] 当用户通过左右滑动界面时,当前的屏幕显示当前界面和下一个界面的一部分...

带梦想一7飞
2013/08/01
0
1
从零开发Android视频点播APP

第1章 课程介绍,技术选型 本章将向大家介绍本课程你们学到什么,项目功能模块有哪些,并对技术进行分解,方便大家有针对性的准备和学习,同时会将项目结构设计好,为后面项目的开发做好基础准...

13269051240
05/21
0
0
ViewPager不能高度自适应?height=wrap_content 无效解决办法

/* http://my.oschina.net/lifj/blog/283346 */ ViewPager用的很多,主要用啦展示广告条。可是高度却不能自适应内容,总是会占满全屏,即使设置android:height="wrap_content"也是没有用的。...

拉风的道长
2014/06/24
0
9
打造万能的BannerView(ViewPager)无限轮播图

为什么写这篇文章,因为在网上看到的绝大多数BannerView实现了右无限轮播图,甚至没有实现无限轮播图,说成是无限轮播图,实现了左右无限轮播图的,并没有做性能上的优化。 先看张效果图 工程...

Steven_520
05/11
0
0
从零开发Android视频点播APP视频课程 点播APP实战教程

第1章 课程介绍,技术选型 本章将向大家介绍本课程你们学到什么,项目功能模块有哪些,并对技术进行分解,方便大家有针对性的准备和学习,同时会将项目结构设计好,为后面项目的开发做好基础准...

17087075817
05/14
0
0
ViewPager一:结合Fragment使用

平时都是打开一个Word来记笔记,现在发现不如写个博文,又不容易丢失,又方便。所以,本次开始,代码一律用截图上传。 接触android开始,就频繁接触android.support.v4包里面的这个向下兼容类...

熊西西77
06/26
0
0
Android开源控件ViewPager Indicator的使用方法

Android Viewpager Indicator是Android开发中最常用的控件之一,几乎所有的新闻类APP中都有使用,下面介绍其基本使用方法。 1. ViewPager Indicator的Library 查看Viewpager Indicator的Lib...

linsea
2014/03/14
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

expect(spawn) 自动化git提交和scp拷贝---centos(linux)

**在进行SCP文件拷贝中,往往需要进行用户密码的输入,即用户交互。若采用自动化脚本的方式进行,则可用以下方式: ** #!/usr/bin/expect #设置参数 set src [lindex $argv 0] set dest [lin...

helplove
7分钟前
1
0
用Build来构建对象的写法

如果一个类的属性过多,用构造器来构建对象很难写,因此我们时用Build方式来构建对象。写法大致如下。 import java.io.Serializable;import java.util.Date;public class Log impleme...

算法之名
10分钟前
11
0
利用 acme.sh 获取网站证书并配置https访问

acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书.(https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) 主要步骤: 安装 acme.sh 生成证书 copy 证书到 nginx/ap...

haoyuehong
23分钟前
2
0
微擎框架内如何根据media_id获取到微信图片的路径

微擎的框架内,图片选择后,获取的是那个字符串是media_id,相当于你这张图片在微信的图片服务器里面的id 要求是:获取https://mmbiz.qpic.cn/mmbiz_jpg/…… 微信图片的路径 而微信并没有根据m...

老bia同学
27分钟前
1
0
Spring boot中日期的json格式化

Model 在model层中,类的日期属性上面添加如下注解: @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss") 参考 Jackson Date格式化教程...

亚林瓜子
28分钟前
2
0
Eclipse:Failed to load the JNI shared library

1.问题背景: 由于我之前使用jdk1.9学习,当使用Luke的时候发现jdk版本过高,需要向下配置jdk,就向朋友拷了一个安装包。重新配置路径后,便开始报错。 2.问题描述: Failed to load the JNI...

tinder_boy
31分钟前
1
0
少儿学习编程课程是否真的适合七八岁的低龄儿童[图]

少儿学习编程课程是否真的适合七八岁的低龄儿童[图]: 天下熙熙皆为利来,天下攘攘皆为利往。 这几年来,乐高教育机构在国内如同雨后春笋般出现,当然关闭/转手的也很多。从教师角度来看,部...

原创小博客
36分钟前
1
0
ES12-词项查询

1.词项查询介绍 全文查询将在执行之前分析查询字符串,但词项级别查询将按照存储在倒排索引中的词项进行精确操作。这些查询通常用于数字,日期和枚举等结构化数据,而不是全文本字段。 或者,...

贾峰uk
44分钟前
2
0
http状态码与ajax的状态值

ajax状态值 1.1 200 & OK:状态请求成功

litCabbage
47分钟前
2
0
iOS动画效果合集、飞吧企鹅游戏、换肤方案、画板、文字效果等源码

iOS精选源码 动画知识运用及常见动画效果收集 3D卡片拖拽卡片叠加卡片 iFIERO - FLYING PENGUIN 飞吧企鹅SpriteKit游戏(源码) Swift封装的空数据提醒界面EmptyView 沙盒文件浏览与分享调试控...

sunnyaigd
50分钟前
3
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部