文档章节

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

Mr_Nice
 Mr_Nice
发布于 2016/05/22 20:00
字数 2082
阅读 32
收藏 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(003):使用TextView类构造文本控件

基础: TextView是无法供编辑的。 当我们新建一个项目MyTextView时候,默认的布局(/res/layout/activity_main.xml)中已经有了一个TextView: <TextView 运行效果如下: 修改其文本内容...

樂天
2014/03/22
636
1
SQLServer实现split分割字符串到列

网上已有人实现sqlserver的split函数可将字符串分割成行,但是我们习惯了split返回数组或者列表,因此这里对其做一些改动,最终实现也许不尽如意,但是也能解决一些问题。 先贴上某大牛写的s...

cwalet
2014/05/21
9.6K
0
我的架构演化笔记 功能1: 基本的用户注册

“咚咚”,一阵急促的敲门声, 我从睡梦中惊醒,我靠,这才几点,谁这么早, 开门一看,原来我的小表弟放暑假了,来南京玩,顺便说跟我后面学习一个网站是怎么做出来的。 于是有了下面的一段...

强子哥哥
2014/05/31
976
3
beego API开发以及自动化文档

beego API开发以及自动化文档 beego1.3版本已经在上个星期发布了,但是还是有很多人不了解如何来进行开发,也是在一步一步的测试中开发,期间QQ群里面很多人都问我如何开发,我的业余时间实在...

astaxie
2014/06/25
2.7W
22
Nutch学习笔记4-Nutch 1.7 的 索引篇 ElasticSearch

上一篇讲解了爬取和分析的流程,很重要的收获就是: 解析过程中,会根据页面的ContentType获得一系列的注册解析器, 依次调用每个解析器,当其中一个解析成功后就返回,否则继续执行下一个解...

强子哥哥
2014/06/26
712
0

没有更多内容

加载失败,请刷新页面

加载更多

AI复原上海民国名媛影像!1929年的小姐姐,时装精致不输现在

萧箫 发自 凹非寺 量子位 报道 | 公众号 QbitAI 中国最早的时装秀,是什么样的? 自修复100年前的北京影像后,微博博主@大谷Spitzer这次又用AI工具,复原了民国时期的这场「花生骚」(Fashi...

视学算法
今天
18
0
【脑电硬件】教育相关的商业可穿戴脑电设备概览

脑电是一门古老的脑成像技术,但迄今为止也依然是最具生命力的主流脑成像技术之一。这主要得益于相比其他脑成像技术,脑电设备具有便携性好,使用成本低,无创,高时间分辨率,和丰富的频率信...

好未来技术
10分钟前
13
0
米菲云仓系统开发(米菲系统)

本章阐述持续集成系统的发展历程、持续集成系统的原理,以及持续集成系统的实现过程,目的是让大家全面了解持续集成系统,更加深入的学习持续集成系统的原理,为后续章节的学习做好准备。我会...

薇fzb246724
18分钟前
37
0
传统租车服务企业,拥抱Docker,K8s,微服务之路!

走进台湾双北市的民营停车场,现在有机会看到贴有Smart2go字样的车辆停在停车场,供租用,而无论预约、取车、还车到付款,使用一站式App都能完成。这是格上汽车租赁(简称格上)从今年4月开始...

Kubernetes
今天
23
0
2020年7月Github上最热门的开源项目

7月份GitHub上最热门的开源项目排行已经出炉啦,一起来看看上榜详情吧 1 tsunami-security-scanner https://github.com/google/tsunami-security-scannerStar 5830 tsunami-security-scanne...

不卖萌的邓肯
今天
10
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部