App项目之新手引导页

* 很多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};
@Override
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);
    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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值