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开发,导航)