Android---引导界面的制作

一.概述

在我们下载了一个App第一次进入的时候,或者是已有App更新之后第一次进入时,一般都会有一个引导界面,这个界面用于展示本App的基本功能,或者是更新之后版本的重大改进;效果图如下:
这里写图片描述
这里就简单的记录以下这个功能的实现;

二.实现过程

1.布局页面分析
这里写图片描述
布局代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical">

    <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:textColor="@color/selector_txt_guide"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:background="@drawable/selector_btn_guide"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="60dp"
        android:visibility="invisible"
        android:text="开始体验"/>

    <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"
            android:orientation="horizontal">
        </LinearLayout>

        <ImageView
            android:id="@+id/iv_red_point"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/shape_point_red"/>

    </RelativeLayout>


</RelativeLayout>

注意:

 对于布局文件中Button的Visibility设置为false,不可见.在引导页的最后一页的时候,再将其设置为可见.

2.业务逻辑

难点:观察效果图注意到底部的小红点,当引导图滑动时,底部的小红点是跟随着滑动的.

2.1对小红点随页面移动而移动的分析如下:
这里写图片描述

ViewPager有一个监听事件: ViewPager.setOnPageChangeListener,
其中有一个重写的方法是这样的:

public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}

其中positionOffset参数是VIewPager中页面移动的百分比.
这样我们就可以得到一个思路:
小红点移动的距离(小红点的leftMargin值)=两小红点间距离*页面移动百分比(positionOffset)+当前位置的距离

2.2接下来分析两小红点之间的距离
从分析图片中可以看到,两小红点之间的距离(mPointDis)=第二个红点的left值-第一个红点的left值.

mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();

注意:
mPointDis 值必须要在View的位置确定了之后才可以得到(View的绘制有如下几个步骤:measures->layout(确定位置)->draw),所以我们要对小红点设置监听,当其位置确定了之后才拿mPointDis值.

//监听layout方法结束,位置确定好了之后,再计算值
        iv_red_point.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //layout方法执行结束的回调

                //移除监听避免重复回调
                iv_red_point.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                /*计算两个圆点的距离 第二个圆点的left值-第一个圆点的left值
                 * measures->layout(确定位置)->draw Acivity的onCreate方法结束后才会走这个流程
                 * */
                mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();
                Log.d("------>" + "计算两个圆点的距离", mPointDis + "");
            }
        });

2.3监听VIewPager的滑动,小红点随之而动
小红点的移动也就是在底部线性布局中的marginLeft值的改变.
由上诉分析得来的公式:
小红点移动的距离(小红点的leftMargin值)=两小红点间距离*页面移动百分比(positionOffset)+当前位置的距离
可以得到如下代码:

int leftMargin = (int) (mPointDis * positionOffset) + position * mPointDis;

然后将leftMargin的值从新设置给小红点的参数即可:

RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
                        iv_red_point.getLayoutParams(); //拿到小红点的布局参数
                layoutParams.leftMargin = leftMargin; //修改小红点的布局参数
                iv_red_point.setLayoutParams(layoutParams); //重新设置小红点的布局参数

2.4业务逻辑完整代码

package com.example.lenovo.ruizhiapp;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

import com.example.lenovo.utils.PrefUtils;

import java.util.ArrayList;

/**
 * 新手引导界面
 * Created by lenovo on 2016/7/7.
 */
public class GuideActivity extends Activity {

    private ViewPager vp_guide;
    //引导页图片ID数组
    private int[] mImageIds = new int[]{R.drawable.guide_1,
            R.drawable.guide_2,
            R.drawable.guide_3};
    //imageView的集合
    private ArrayList<ImageView> mImageViewList;
    private LinearLayout ll_container;
    private ImageView iv_red_point;
    private int mPointDis;
    private Button btn_start;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_guid);

        initViews();//初始化界面控件
        initData();//先初始化数据,然后再设置数据
        vp_guide.setAdapter(new GuideAdapter());//设置数据

    }


    private void initViews() {
        vp_guide = (ViewPager) findViewById(R.id.vp_guide);
        ll_container = (LinearLayout) findViewById(R.id.ll_container);
        iv_red_point = (ImageView) findViewById(R.id.iv_red_point);
        btn_start = (Button) findViewById(R.id.btn_start);

        //对ViewPager页面滑动的监听
        vp_guide.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

            @Override //页面滑动过程中的回调方法
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                Log.d("------>" + "当前位置:", position + "");
                Log.d("------>" + "偏移百分比:", positionOffset + "");

                //更新小红点的距离=移动百分比*两个原点间的间距+当前位置
                int leftMargin = (int) (mPointDis * positionOffset) + position * mPointDis;
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams)
                        iv_red_point.getLayoutParams(); //拿到小红点的布局参数
                layoutParams.leftMargin = leftMargin; //修改小红点的布局参数
                iv_red_point.setLayoutParams(layoutParams); //重新设置小红点的布局参数

            }

            @Override //某个页面被选中
            public void onPageSelected(int position) {
                //最后一个页面才显示"开始体验的按钮"
                if (position==mImageViewList.size()-1){ //灵活代码
                    //只在引导页面的最后一页显示按钮
                    btn_start.setVisibility(View.VISIBLE);
                }else{
                    //其余引导页面不显示按钮
                    btn_start.setVisibility(View.INVISIBLE);
                }

            }

            @Override //页面状态发生变化 (滑-->不滑)
            public void onPageScrollStateChanged(int state) {
            }
        });


        //监听layout方法结束,位置确定好了之后,再计算值
        iv_red_point.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                //layout方法执行结束的回调

                //移除监听避免重复回调
                iv_red_point.getViewTreeObserver().removeOnGlobalLayoutListener(this);

                /*计算两个圆点的距离 第二个圆点的left值-第一个圆点的left值
                 * measures->layout(确定位置)->draw Acivity的onCreate方法结束后才会走这个流程
                 * */
                mPointDis = ll_container.getChildAt(1).getLeft() - ll_container.getChildAt(0).getLeft();
                Log.d("------>" + "计算两个圆点的距离", mPointDis + "");
            }
        });

        btn_start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                startActivity(new Intent(getApplicationContext(),MainActivity.class));
                //表示已经不是第一次进入,跟新SP
                PrefUtils.setBoolean(getApplicationContext(),ConstantValues.IS_FIRST_ENTER,false);
                //结束引导界面
                finish();

            }
        });


    }

    //初始化数据
    private void initData() {
        mImageViewList = new ArrayList<ImageView>();
        for (int i = 0; i < mImageIds.length; i++) {
            ImageView imageView = new ImageView(this);
            imageView.setBackgroundResource(mImageIds[i]);//通过设置背景,可以让宽高填充布局
            mImageViewList.add(imageView);

            //初始化底部小圆点
            ImageView point = new ImageView(this);
            point.setImageResource(R.drawable.shape_point_gray);//设置图片<shape>

            //初始化布局参数,宽高包裹内容,父控件是谁就申明谁的布局参数
            LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
                    LinearLayout.LayoutParams.WRAP_CONTENT);

            if (i > 0) {
                //从第二个点开始设置原点之间的间隔
                layoutParams.leftMargin = 10;
            }
            point.setLayoutParams(layoutParams);//设置布局参数

            ll_container.addView(point);//给容器添加原点

        }
    }


    class GuideAdapter extends PagerAdapter {

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

        @Override //固定写法
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

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

        }


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

最后说一句:用开源空间ViewPagerIndicator可以很轻松的实现上述功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值