app的引导页很多都是用viewpager做的,小面还有一个小圆点,会根据页面切换,但是有些app引导页的小圆点会随着页面的滑动而滑动,而不是机器式的直接跳到下一页.
上图:
简单做法:
- 写布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_height="match_parent">
<!--用一个viewpager来展示滑动效果-->
<android.support.v4.view.ViewPager
android:id="@+id/vp_guide"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<!--开始体验的按钮,刚开始不可见-->
<Button
android:id="@+id/btn_start"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="开始体验"
android:textSize="24dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="60dp"
android:padding="20dp"
android:visibility="invisible"
android:background="@drawable/selector_guidebutton"
/>
<!--控制小点的布局-->
<RelativeLayout
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:layout_width="wrap_content"
android:layout_marginBottom="40dp"
android:layout_height="wrap_content">
<!--用来存放小灰点的布局-->
<LinearLayout
android:gravity="center"
android:id="@+id/ll_guide_point"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
<!--浮在上面的小红圆点-->
<View
android:id="@+id/v_red_point"
android:background="@drawable/shape_guide_point_red"
android:layout_width="10dp"
android:layout_height="10dp"
/>
</RelativeLayout>
</RelativeLayout>
viewpager部分就不写了,很简单,一个适配器搞定,主要是小圆点部分,注意几点
- 动态初始化下面的小白点
//小圆点的数量等于图片的数量
for (int i = 0; i < imageIds.length; i++) {
//初始化小白点
View view = new View(ll_guide_point.getContext());
view.setBackgroundResource(R.drawable.shape_guide_point_darker_gray);
//创建小白点大小,这里注意把 dx 通过工具类转成 dp
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(DensityUtils.dip2px(this,10),DensityUtils.dip2px(this,10));
if (i > 0){
//除了第一个小白点之外,其余都有margin
params.leftMargin = DensityUtils.dip2px(this,8);
}
//将大小设置上去
view.setLayoutParams(params);
//将小圆点加到布局上
ll_guide_point.addView(view);
}
- 设置滑动监听
//滑动监听
/**
* 滑动事件
* @param position 当前位置
* @param positionOffset 百分比
* @param positionOffsetPixels 移动距离
*/
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
//positionOffset 移动的百分比,只需要知道两个点之间的距离,相乘就知道此时小圆点该移动多少距离
//必须加上后面的一部分,不然你滑倒第二个的时候小红点又会回到第一个,因为此时positionOffset归0了
float len = distance * positionOffset + position * distance;
//让小圆点动起来,就是修改 MarginLeft
View view = (View) findViewById(R.id.v_red_point);
//拿到它原本的params
RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
layoutParams.leftMargin = (int) len;
view.setLayoutParams(layoutParams);
}
//被选中时
@Override
public void onPageSelected(int position) {
//最后一个页面被选中时让开始按钮展现出来
if(position == imageIds.length-1){
btn_start.setVisibility(View.VISIBLE);
}else {
btn_start.setVisibility(View.INVISIBLE);
}
}
//滑动状态改变
@Override
public void onPageScrollStateChanged(int state) {
}
- 这里注意测量两个圆点的距离,就是上面的distance,必须要在activity的视图树全部创建完成才能测量,写在onCreate()方法中是没有效的,所以要注册观察者
//算出第一个小圆点和第二个小圆点之间的距离,注意在oncreate方法中不能测量view的位置,因为此时界面还未绘制
//注册一个观察者,当视图树加载完成后,调用此方法
ll_guide_point.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
//当layout执行结束之后,回调次方法
@Override
public void onGlobalLayout() {
//一旦绘制完成,取消这个监听,这个方法已经过时,但是新方法必须在API16以上才能用
ll_guide_point.getViewTreeObserver().removeGlobalOnLayoutListener(this);
//此时就能拿到距离了
distance = ll_guide_point.getChildAt(1).getLeft() - ll_guide_point.getChildAt(0).getLeft();
}
});