App项目之新手引导页

来源:互联网 发布:java编写的著名游戏 编辑:程序博客网 时间:2024/05/18 06:20

* 很多App第一次打开时都有一个新手引导页,这个引导页看起来很简单,但是做起来还是需要用刀不少知识的 *
这里写图片描述
ListView是非常重要的!!!!
先把布局文件写好:
这里写图片描述

<?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">    <android.support.v4.view.ViewPager        android:id="@+id/vp_guide"        android:layout_width="match_parent"        android:layout_height="match_parent"        />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开始体验"        android:id="@+id/btn_start"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="60dp" />    <LinearLayout        android:id="@+id/ll_container"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="30dp"        android:orientation="horizontal"></LinearLayout></RelativeLayout>

然后在GuideActivity中初始化数据.
(去掉标题:requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题,这个恶搞方法必须在setcontentview之前调用)

private ViewPager mViewPager;//怎样维护这个对象数组?private ArrayList<ImageView> mImageViewList;//imageview的集合//引导页图片id数组private int[] mImageIds = new int[]{R.mipmap.guide_1,R.mipmap.guide_2,R.mipmap.guide_3};@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题,这个恶搞方法必须在setcontentview之前调用    setContentView(R.layout.guide_activity);    mViewPager = (ViewPager) findViewById(R.id.vp_guide);    initData();    mViewPager.setAdapter(new GuideAdapter());//设置数据}//初始化ImageViewer对象.初始化数据private void initData(){    mImageViewList = new ArrayList<ImageView>();    for (int i=0;i<mImageIds.length;i++){        ImageView view = new ImageView(this);        view.setBackgroundResource(mImageIds[i]);//通过设置背景,可以让宽高填充布局        //view.setImageResource(resId);这个方法不一定能填充满        mImageViewList.add(view);    }}

然后开始设置数据

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 view = mImageViewList.get(position);//获取这个ImageViewer,之前通过集合已经把要使用的创建好了,用的时候直接拿过来用        container.addView(view);//把这个对象塞给container容器        return view;    }    @Override    //销毁item布局    public void destroyItem(ViewGroup container, int position, Object object) {       container.removeView((View)object);    }}

这时就完成了一个简单的引导.注意一定要先初始化数据!!!
接下来是页面指示器小圆点的完成,这个功能有助于用户体验.
这三个小圆点属于自定义控件,先初始化线性布局.
这里写图片描述
这里写图片描述

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

因为引导页需要一个小红点覆盖原来的小灰点,所以还要有个xml文件描述小红点.如下代码:

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

根据布局文件来看,需要有个相对布局包裹着一个线性布局.所以修改布局文件的代码如下:黄色部分为修改的代码

<?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">    <android.support.v4.view.ViewPager        android:id="@+id/vp_guide"        android:layout_width="match_parent"        android:layout_height="match_parent"        />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="开始体验"        android:id="@+id/btn_start"        android:layout_alignParentBottom="true"        android:layout_centerHorizontal="true"        android:layout_marginBottom="60dp" />    <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>

然后根据需求开始设置小红点,这里用到了自定义控件.就是关于布局绘制的一个流程.先测量,然后确定位置(layout执行完),最后再进行一个绘制.这三步之后才能把这个控件画在界面上.
计算两个小红点之间的距离
移动距离=第二个圆点left的值-第一个圆点left的值.

还要设置页面滑动的一个监听:

protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    requestWindowFeature(Window.FEATURE_NO_TITLE);//去掉标题,这个恶搞方法必须在setcontentview之前调用    setContentView(R.layout.guide_activity);    mViewPager = (ViewPager) findViewById(R.id.vp_guide);    llContainer = (LinearLayout) findViewById(R.id.ll_container);    ivRedPoint = (ImageView)findViewById(R.id.iv_red_point);    initData();    mViewPager.setAdapter(new GuideAdapter());//设置数据  //设置页面滑动的一个监听    mViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {        @Override        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {        //当页面滑动过程中的回调            System.out.println("当前位置:"+position+";移动偏移百分百:"+positionOffset);            //更新小红点的距离        }        @Override        public void onPageSelected(int position) {        //某个页面被选中        }        @Override        public void onPageScrollStateChanged(int state) {        //页面状态发生变化的回调,暂时不用        }    });    //计算两个小红点之间的距离    //移动距离=第二个圆点left的值-第一个圆点left的值    //measure->layout->draw(activity的 oncreate方法执行结束之后才走此流程,这就解释了为什么打印距离为0)   /* mPointDis = llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();    System.out.println("圆点距离:"+mPointDis); //因为打印距离是0,所以这个方法不能直接这样写*/    //监听layout方法结束的事件.结束之后位置确定好之后再获取圆点间距    //视图树?    ivRedPoint.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {        @Override        public void onGlobalLayout() {            ivRedPoint.getViewTreeObserver().removeOnGlobalLayoutListener(this);//避免重复回调            //layout方法执行结束的回调,这时可以使用这个方法            mPointDis = llContainer.getChildAt(1).getLeft()-llContainer.getChildAt(0).getLeft();            System.out.println("圆点距离:"+mPointDis);        }    });}

这里写图片描述
注意:根据图片可知要想得到小红点的距离,就要拿到移动间距.
//measure->layout->draw(activity的 oncreate方法执行结束之后才走此流程,这就解释了为什么打印距离为0)
直接这样使用是不行的.监听layout方法结束的事件.结束之后位置确定好之后再获取圆点间距.才可以使用
(这里讲了一个视图树的概念,可以看看.)
注意回调的概念.不要不理解啊
最后怎么更新小红点的距离呢?

//更新小红点的距离int dis = (int) (mPointDis * positionOffset);改变小红点的布局参数就可以了.就相当于更新marginleft的值System.out.println("当前位置:"+position+";移动偏移百分百:"+positionOffset);
//更新小红点的距离int leftMargin = (int) (mPointDis * positionOffset + position * mPointDis);//计算小红点当前的左边距RelativeLayout.LayoutParams params =(RelativeLayout.LayoutParams) ivRedPoint.getLayoutParams();//当前的布局参数params.leftMargin = leftMargin;//修改左边距ivRedPoint.setLayoutParams(params);//重新设置布局参数

这里就完成了基本的新手引导.具体代码可以在这里下载https://github.com/ZoeSj/SmartXinHua.git

0 0