Android开发之ViewPager做新手引导界面
先看一下我们要开发的界面(三张图片,滑到最后一个会出现开始体验的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做新手引导界面的更多相关文章
- Android开发之ViewPager+ActionBar+Fragment实现响应式可滑动Tab
今天我们要实现的这个效果呢,在Android的应用中十分地常见,我们可以看到下面两张图,无论是系统内置的联系人应用,还是AnyView的阅读器应用,我们总能找到这样的影子,当我们滑动屏幕时,Tab可 ...
- Android开发之ViewPager
什么是ViewPager? ViewPager是安卓3.0之后提供的新特性,继承自ViewGroup,专门用以实现左右滑动切换View的效果. 如果想向下兼容就必须要android-support-v ...
- Android开发之ViewPager实现轮播图(轮播广告)效果的自定义View
最近开发中需要做一个类似京东首页那样的广告轮播效果,于是采用ViewPager自己自定义了一个轮播图效果的View. 主要原理就是利用定时任务器定时切换ViewPager的页面. 效果图如下: 主页面 ...
- Android开发之ViewPager实现多页面切换及动画效果(仿Android的Launcher效果)
Android开发中经常会有引导页或者切换页面等效果,本文采用ViewPager结合动画效果来实现仿Launcher以及页面切换的效果.源码地址在文章最后给出下载. 效果图如下: 1.Vi ...
- Android开发之ViewPager的简单使用
ViewPager是V4包中的,如果你的编译器敲不出ViewPager,那么你就需要添加,看下面: 第一步:点击+号 第二步:选择第一个Library 第三步:添加这个包: 然后点击ok-->o ...
- 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 ...
- Android开发之Intent跳转到系统应用中的拨号界面、联系人界面、短信界面
现在开发中的功能需要直接跳转到拨号.联系人.短信界面等等,查找了很多资料,自己整理了一下. 1.跳转到拨号界面,代码如下: 1)直接拨打 Intent intentPhone = new Intent ...
- 【Android UI】Android开发之View的几种布局方式及实践
引言 通过前面两篇: Android 开发之旅:又见Hello World! Android 开发之旅:深入分析布局文件&又是“Hello World!” 我们对Android应用程序运行原理 ...
- Android开发之旅: Intents和Intent Filters(理论部分)
引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...
随机推荐
- 烂泥:高负载均衡学习haproxy之关键词介绍
本文由ilanniweb提供友情赞助,首发于烂泥行天下 上一篇文章我们简单讲解了有关haproxy的安装与搭建,在这篇文章我们把haproxy配置文件中使用到的关键词一一介绍下. 关注我微信ilann ...
- android 利用Path.cubicTo 画 贝塞尔曲线
Path.cubicTo void android.graphics.Path.cubicTo(float x1, float y1, float x2, float y2, float x3, fl ...
- centos6.5编译安装lamp开发环境
一.系统以及软件的准备 系统及编译安装包的下载地址:http://pan.baidu.com/s/1jIjqinc 密码:ghc2 说明:由于centos6.5是分卷压缩的,且压缩为三个压缩包,所 ...
- spring注入静态成员变量提示invalid setter method
果然还是不够细心啊,被坑一晚上.. 一个极其简单的小程序,但是需要通过xml文件配置注入一个值,唯一的特别是要注入的属性是类中的静态成员变量.. 如下,然后自动生成get和set方法..坑就从此开始了 ...
- NServiceBus 更换服务名及队列名称
可以通过起动时的参数处理 NServiceBus.Host.exe /serviceName:”服务名称” /endpointName:”默认队列名称”
- KVM 介绍(5):libvirt 介绍 [ Libvrit for KVM/QEMU ]
学习 KVM 的系列文章: (1)介绍和安装 (2)CPU 和 内存虚拟化 (3)I/O QEMU 全虚拟化和准虚拟化(Para-virtulizaiton) (4)I/O PCI/PCIe设备直接分 ...
- 第15章 设备无关位图_15.3 DIB和DDB的结合
第15章 设备相关位图_15.3 DIB和DDB的结合 15.3.1 从DIB创建DDB (1)hBitmap =CreateDIBitmap(…)——注意这名称会误导,实际上创建的是DDB 参数 说 ...
- QuickFIX/N 动态存储配置信息
Acceptor或者Initiator能够为您维护尽可能多的FIX会话,因而FIX会话标识的唯一性非常重要.在QuickFIX/N中,一个FIX会话的唯一标识是由:BeginString(FIX版本号 ...
- Zookeeper的学习材料
https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/ https://www.zhihu.com/question/351 ...
- php中创建和调用webservice接口示例
php中创建和调用webservice接口示例 这篇文章主要介绍了php中创建和调用webservice接口示例,包括webservice基本知识.webservice服务端例子.webservi ...