先看一下我们要开发的界面(三张图片,滑到最后一个会出现开始体验的Button,下面的小红点会跟着一起滑动):

首先看一下布局文件:

 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/activity_guide"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context="com.coderwei.a71_zhbj.activity.GuideActivity">

     <android.support.v4.view.ViewPager
         android:id="@+id/vp_guide"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         />
     <Button
         android:layout_centerHorizontal="true"
         android:layout_alignParentBottom="true"
         android:layout_marginBottom="70dp"
         android:padding="10dp"
         android:id="@+id/start_btn"
         android:textColor="#f1eaea"
         android:background="#e71616"
         android:text="开始体验"
         android:visibility="invisible"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content" />

     <RelativeLayout
         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_container"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content">

         </LinearLayout>
         <ImageView
             android:id="@+id/iv_red"
             android:src="@drawable/shap_red"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content" />

     </RelativeLayout>

 </RelativeLayout>

然后就是代码了:

 public class GuideActivity extends Activity {

     private ViewPager mViewPager;
     private int[] mImageIds = new int[]{R.drawable.guide_1,R.drawable.guide_2,R.drawable.guide_3};
     private ArrayList<ImageView> mImageViewList;
     private LinearLayout llContainer;
     private ImageView ivRedPoint;
     private int mPaintDis;
     private Button start_btn;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         setContentView(R.layout.activity_guide);
         mViewPager = (ViewPager)findViewById(R.id.vp_guide);
         llContainer = (LinearLayout) findViewById(R.id.ll_container);
         ivRedPoint = (ImageView) findViewById(R.id.iv_red);
         start_btn = (Button) findViewById(R.id.start_btn);
         initData();
         GuideAdapter adapter = new GuideAdapter();
         mViewPager.setAdapter(adapter);

         //监听布局是否已经完成  布局的位置是否已经确定
         ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
             @Override
             public void onGlobalLayout() {
                 //避免重复回调        出于兼容性考虑,使用了过时的方法
                 ivRedPoint.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                 //布局完成了就获取第一个小灰点和第二个之间left的距离
                 mPaintDis =   llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();
                 System.out.println("距离:"+mPaintDis);
             }
         });

         //ViewPager滑动Pager监听
         mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
             //滑动过程中的回调
             @Override
             public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                 //当滑到第二个Pager的时候,positionOffset百分比会变成0,position会变成1,所以后面要加上position*mPaintDis
                 int letfMargin = (int)(mPaintDis*positionOffset)+position*mPaintDis;
                 //在父布局控件中设置他的leftMargin边距
                 RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)ivRedPoint.getLayoutParams();
                 params.leftMargin = letfMargin;
                 ivRedPoint.setLayoutParams(params);
             }

             @Override
             public void onPageSelected(int position) {
                 System.out.println("position:"+position);
                 if (position==mImageViewList.size()-1){
                     start_btn.setVisibility(View.VISIBLE);
                 }

             }

             @Override
             public void onPageScrollStateChanged(int state) {
                 System.out.println("state:"+state);
             }
         });
     }

     private void initData(){
         mImageViewList = new ArrayList<>();
         for (int i=0; i<mImageIds.length; i++){
             //创建ImageView把mImgaeViewIds放进去
             ImageView view = new ImageView(this);
             view.setBackgroundResource(mImageIds[i]);
             //添加到ImageView的集合中
             mImageViewList.add(view);

             //小圆点    一个小灰点是一个ImageView
             ImageView pointView = new ImageView(this);
             pointView.setImageResource(R.drawable.shape);
             //初始化布局参数,父控件是谁,就初始化谁的布局参数
             LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
             if (i>0){
                 //当添加的小圆点的个数超过一个的时候就设置当前小圆点的左边距为10dp;
                 params.leftMargin=10;
             }
             //设置小灰点的宽高包裹内容
             pointView.setLayoutParams(params);
             //将小灰点添加到LinearLayout中
             llContainer.addView(pointView);
         }
     }

     class GuideAdapter extends PagerAdapter{

         //item的个数
         @Override
         public int getCount() {
             return mImageViewList.size();
         }

         @Override
         public boolean isViewFromObject(View view, Object object) {
             return view == object;
         }

         //初始化item布局
         @Override
         public Object instantiateItem(ViewGroup container, int position) {
             ImageView view = mImageViewList.get(position);
             container.addView(view);
             return view;
         }

         //销毁item
         @Override
         public void destroyItem(ViewGroup container, int position, Object object) {
             container.removeView((View)object);
         }
     }
 }

小灰点:

 <?xml version="1.0" encoding="utf-8"?>
 <shape
     android:shape="oval"
     xmlns:android="http://schemas.android.com/apk/res/android">
     <!--小灰点-->
     <solid android:color="#cccccc"/>
     <size android:width="10dp" android:height="10dp"/>

 </shape>

小红点:

 <?xml version="1.0" encoding="utf-8"?>
 <shape
     android:shape="oval"
     xmlns:android="http://schemas.android.com/apk/res/android">

     <solid android:color="#f00"/>
     <size android:width="10dp" android:height="10dp"/>
 </shape>

ViewPage都很简单,上一个博文也详细介绍了的,这里就不细说了,主要是下面的小红点跟着Pager一起走。

上面其实是三个小灰点,然后小灰点的上面有一个小红点,通过计算出第一个小灰点与第二个小灰点之间的距离,我们就可以用设置ViewPager的滑动监听,然后让小红点跟着pager一起动(改变的是父控件中的内边距)。

计算小灰点之间的距离时需要注意的是,必须等到布局位置确定下来的才能的到小灰点之间的距离(界面生成的过程 measure->layout(确定位置)->draw(activity的onCreate方法执行结束之后才会走此流程)),所以要设置layout的监听:

ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()

然后的到小灰点之间的距离:
mPaintDis =   llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();

需要注意的是这句代码:
int letfMargin = (int)(mPaintDis*positionOffset)+position*mPaintDis;
positionOffset是当前滑动的百分比,当进入第二个page的时候,值为0,
position代表当前是第几个page,从0开始,也就是说当我滑到第二个page的时候 mPaintDis*0+1*mPaintDis;

PS:思路总结:

  1、页面由 ViewPager + Button + RelativeLayout(LinearLayout + TextView)组成,
  2、LinearLayout放的是小灰点,小灰点的个数由ViewPager的个数觉得,所以LinearLayout添加小灰点的时候是与VIewPager的图片资源添加到集合是一起的。
  3、然后小红点就是一个TextView因为相对布局的原因,小红点的初始位置会和小灰点的第一个点重合,
  4、然后监听ViewPager的滑动事件,通过计算第一个和第二个小灰点的左边到LinearLayout的左边的边距差,来移动小红点的位置,但是确定位置的查体须  是布局的位置已经确定,所以我们就要监听布局是否已经确定,等确定后再去计算位置差。



 


Android开发之ViewPager做新手引导界面的更多相关文章

  1. Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab

     今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...

  2. Android开发之ViewPager

    什么是ViewPager? ViewPager是安卓3.0之后提供的新特性,继承自ViewGroup,专门用以实现左右滑动切换View的效果. 如果想向下兼容就必须要android-support-v ...

  3. Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View

    最近开发中需要做一个类似京东首页那样的广告轮播效果,于是采用ViewPager自己自定义了一个轮播图效果的View. 主要原理就是利用定时任务器定时切换ViewPager的页面. 效果图如下: 主页面 ...

  4. Android开发之ViewPager实现多页面切换及动画效果(仿Android的Launcher效果)

    Android开发中经常会有引导页或者切换页面等效果,本文采用ViewPager结合动画效果来实现仿Launcher以及页面切换的效果.源码地址在文章最后给出下载. 效果图如下:       1.Vi ...

  5. Android开发之ViewPager的简单使用

    ViewPager是V4包中的,如果你的编译器敲不出ViewPager,那么你就需要添加,看下面: 第一步:点击+号 第二步:选择第一个Library 第三步:添加这个包: 然后点击ok-->o ...

  6. Android开发之viewpager导报错误解决方法:错误代码 Caused by: java.lang.ClassNotFoundException: Didn't find class

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 Caused by: java.lang.ClassNotFoundException: Didn't ...

  7. Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面

    现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 1.跳转到拨号界面,代码如下: 1)直接拨打 Intent intentPhone = new Intent ...

  8. 【Android UI】Android开发之View的几种布局方式及实践

    引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...

  9. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

随机推荐

  1. TCP校验和的原理和实现

        http://blog.csdn.net/zhangskd/article/details/11770647 分类: Linux TCP/IP Linux Kernel 2013-09-24 ...

  2. ELF Format 笔记(二)—— ELF Header

    ilocker:关注 Android 安全(新入行,0基础) QQ: 2597294287 以 32 位的 ELF header 数据结构为例: #define EI_NIDENT 16 typede ...

  3. Python地址簿

    #!/usr/bin/python #coding=UTF-8 # FileName:address.py # Python地址簿 import cPickle as p; import os; im ...

  4. html5移动端Meta设置

    1.   强制让文档的宽度与设备的宽度保持1:1,并且文档最大的宽度比例是1.0,且不允许用户点击屏幕放大浏览. <meta name="viewport" content= ...

  5. MySQL Database on Azure 参数设置

    在使用MySQL过程中,经常会根据需要对MySQL的参数进行一些设置和调整.作为PaaS版本的MySQL,MySQL Database on Azure在参数设置方面有一些限制,客户不能像使用on-p ...

  6. [转]js函数式变成之函数柯里化

    本文转自:https://segmentfault.com/a/1190000003733107 函数柯里化是指参数逐渐求值的过程. 我觉得它是:降低通用性,提高专用性. 通常,柯里化是这样的过程,“ ...

  7. NYOJ-取石子(六)

    取石子(六) 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 最近TopCoder的PIAOYI和HRDV很无聊,于是就想了一个游戏,游戏是这样的:有n堆石子,两个人轮流 ...

  8. EditText限制输入字符类型的几种方式

    最近的项目上需要限制EditText输入字符的类型,就把可以实现这个功能的方法整理了一下: 1.第一种方式是通过EditText的inputType来实现,可以通过xml或者Java文件来设置.假如我 ...

  9. HTML 学习笔记 CSS(列表)

    CSS列表属性允许你放置 改变列表项标志 或者将图像作为列表项标志. CSS列表 从某中意义上讲 不是描述性的文本的任何内容都可以认为是列表.人口普查.太阳系.家谱.参观菜单,甚至你的所有朋友都可以表 ...

  10. MVC HTTP 错误 403.14 - Forbidden

    HTTP 错误 403.14 - Forbidden Web 服务器被配置为不列出此目录的内容. 最可能的原因: 没有为请求的 URL 配置默认文档,并且没有在服务器上启用目录浏览. 可尝试的操作: ...