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软件编程有所帮助。

时间: 2024-09-25 01:48:47

Android ViewPager制作新手导航页(动态加载)的相关文章

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

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

android viewpager根据数组的长度动态加载布局,隐藏控件无效。

问题描述 android viewpager根据数组的长度动态加载布局,隐藏控件无效. 布局文件 android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <android.support.v4.view.ViewPager android:id="@+id/viewpag

携程Android App的插件化和动态加载框架

携程Android App的插件化和动态加载框架已上线半年,经历了初期的探索和持续的打磨优化,新框架和工程配置经受住了生产实践的考验.本文将详细介绍Android平台插件式开发和动态加载技术的原理和实现细节,回顾携程Android App的架构演化过程,期望我们的经验能帮助到更多的Android工程师. 需求驱动 2014年,随着业务发展需要和携程无线部门的拆分,各业务产品模块归属到各业务BU,原有携程无线App开发团队被分为基础框架.酒店.机票.火车票等多个开发团队,从此携程App的开发和发布

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

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

Android ViewPager动态加载问题

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

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

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

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

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

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

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

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

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