码迷,mamicode.com
首页 > 移动开发 > 详细

Android实现用户引导界面

时间:2015-06-17 11:33:30      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:splash   viewpager   indicator   autoscroll   slide   

在众多应用中,几乎每一款应用都有自己的Splash用户引导界面,该界面在用户首次启动展示,之后不会显示,主要向用户展示新功能.

分析

  • 主要使用ViewPager+Indicator实现
  • 主要是实现一个圆形指示器,这个圆形指示器继承LinearLayout,需要有一些属性可以自定义,比如指示器的颜色,大小,边距等
  • 这个指示器也可以自动滚动,比如应用在幻灯片展示的地方
  • 指示器是圆形的,需要我们自己绘制
  • 这个圆形指示器实现了ViewPager.OnPageChangeListener接口

实现

  • 定义自定义属性
    属性的意思见名字就可以知道了
<resources>

    <declare-styleable name="CircleIndicator">
        <attr name="circle_spacing" format="dimension"/>
        <attr name="circle_fill_color" format="color|reference"/>
        <attr name="circle_stroke_color" format="color|reference"/>
        <attr name="circle_radius" format="dimension"/>
        <attr name="circle_auto_scroll" format="boolean"/>
        <attr name="circle_scroll_delay_time" format="integer"/>
        <attr name="circle_scroll_animation" format="boolean"/>
    </declare-styleable>

</resources>
  • 定义自定义变量,从布局文件中解析进来,此外,如果布局文件没有使用,应该有一个默认的常量.
    定义默认常量
 private static final int DEFAULT_CIRCLE_SPACING = 5;
    private static final int DEFAULT_CIRCLE_COLOR=Color.WHITE;
    private static final int DEFAULT_CIRCLE_SIZE=3;
    private static final boolean DEFAULT_CIRCLE_AUTO_SCROLL=false;
    private static final int DEFAULT_CIRCLE_SCROLL_DELAY_TIME=3000;
    private static final boolean DEFAULT_CIRCLE_SCROLL_ANIMATION=true;

定义用于存储自定义属性的变量

    private int mSpacing;
    private int mSize;
    private int mFillColor;
    private int mStrokeColor;
    private boolean mAutoScroll;
    private int mDelayTime;
    private boolean mIsAnimation;

定义其他辅助变量,比如Canvas,Bitmap,Paint等,用于绘制圆形指示器

    private static final int CIRCLE_STROKE_WIDTH =1;
    private static final int BITMAP_PADDING =2;
 private ViewPager mViewPager;
    private int mCount;
    private int mLastIndex = 0;
    private Canvas mCanvas;
    private Paint mPaint;
    private Bitmap mSelectBitmap;
    private Bitmap mUnselectBitmap;

将自定义属性进行解析赋值给对应变量

private void initCustomParams(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircleIndicator);
        try {
            mSpacing = typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_circle_spacing, DEFAULT_CIRCLE_SPACING);
            mFillColor=typedArray.getColor(R.styleable.CircleIndicator_circle_fill_color,DEFAULT_CIRCLE_COLOR);
            mStrokeColor=typedArray.getColor(R.styleable.CircleIndicator_circle_stroke_color,DEFAULT_CIRCLE_COLOR);
            mSize= typedArray.getDimensionPixelSize(R.styleable.CircleIndicator_circle_radius, DEFAULT_CIRCLE_SIZE);
            mAutoScroll= typedArray.getBoolean(R.styleable.CircleIndicator_circle_auto_scroll, DEFAULT_CIRCLE_AUTO_SCROLL);
            mDelayTime=typedArray.getInt(R.styleable.CircleIndicator_circle_scroll_delay_time,DEFAULT_CIRCLE_SCROLL_DELAY_TIME);
            mIsAnimation=typedArray.getBoolean(R.styleable.CircleIndicator_circle_scroll_animation,DEFAULT_CIRCLE_SCROLL_ANIMATION);

        } finally {
            typedArray.recycle();
        }
    }

我们的指示器是自己绘制出来的,接下来绘制圆形指示器

    private void init() {
        setOrientation(HORIZONTAL);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);

        mPaint.setStrokeWidth(dip2px(CIRCLE_STROKE_WIDTH));
        mPaint.setColor(mFillColor);

        int size=dip2px(mSize+ BITMAP_PADDING + BITMAP_PADDING);
        int radius=dip2px(mSize / 2);
        int centerPoint=radius+ BITMAP_PADDING;

        mSelectBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);
        mUnselectBitmap = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888);

        mCanvas = new Canvas();
        mCanvas.setBitmap(mSelectBitmap);


        mCanvas.drawCircle(centerPoint, centerPoint, radius, mPaint);

        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setColor(mStrokeColor);
        mCanvas.setBitmap(mUnselectBitmap);
        mCanvas.drawCircle(centerPoint, centerPoint, radius, mPaint);

    }

实现构造方法,最终调用三个参数的构造方法,并调用相关函数进行初始化

 public CircleIndicator(Context context) {
        this(context, null);
    }

    public CircleIndicator(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleIndicator(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initCustomParams(context, attrs);
        init();
    }

实现指示器相关逻辑

  • 首先需要初始化指示器的位置,应该是ViewPager的第一页,即初始化位置为0,调用initIndicator,并设置指示器的背景图为选中状态.记录上次指示器的位置即当前位置.
  • removeIndicator移出指示器只要移出当前类的所有子View即可
  • updateIndicator需要将上次的位置背景图设置为未选中,当前位置设置未选中,并记录上次位置为当前位置
  • addIndicator需要将圆形指示器的数目传入,其值为ViewPager的页数,并新建ImageView设置背景图为未选中的时候的图,并设置外边距,将其添加到当前类的子View中,如果设置了自动滚动,还需要进行自动滚动
  • setViewPager函数进行一些初始化操作
public void setViewPager(ViewPager viewPager) {
        mViewPager = viewPager;
        mViewPager.addOnPageChangeListener(this);
        if (mViewPager != null) {
            mCount = mViewPager.getAdapter().getCount();
            addIndicator(mCount);
        }

    }

    private void addIndicator(int count) {
        removeIndicator();
        if (count <= 0)
            return;
        for (int i = 0; i < count; i++) {
            ImageView imageView = new ImageView(getContext());
            LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
            params.leftMargin = mSpacing/2;
            params.rightMargin = mSpacing/2;

            imageView.setImageBitmap(mUnselectBitmap);
            addView(imageView, params);
        }
        initIndicator();
        if(mAutoScroll){
            sendScrollMessage(mDelayTime);
        }
    }

    private void initIndicator() {
        ((ImageView) getChildAt(0)).setImageBitmap(mSelectBitmap);
        mLastIndex=0;
    }

    private void removeIndicator() {
        removeAllViews();
    }

    private void updateIndicator(int position) {

        if (position != mLastIndex) {
            ((ImageView) getChildAt(mLastIndex)).setImageBitmap(mUnselectBitmap);
            ((ImageView) getChildAt(position)).setImageBitmap(mSelectBitmap);
        }
        mLastIndex = position;

    }

实现自动滚动,主要通过Handler进行延时实现

 private Handler mHandler=new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case SCROLL_WHAT:
                    scrollOnce();
                    sendScrollMessage(mDelayTime);
                    break;
            }
        }
    };
    public void scrollOnce() {
        PagerAdapter adapter = mViewPager.getAdapter();
        if (adapter == null) {
            return;
        }
        int nextIndex=mViewPager.getCurrentItem();
        ++nextIndex;
        if(nextIndex >=mCount){
            nextIndex =0;
        }
        updateIndicator(nextIndex);
        mViewPager.setCurrentItem(nextIndex, mIsAnimation);


    }

    private void sendScrollMessage(long delayTimeInMills) {
        mHandler.removeMessages(SCROLL_WHAT);
        mHandler.sendEmptyMessageDelayed(SCROLL_WHAT, delayTimeInMills);
    }

实现相关getter和setter函数

 private void setAutoScroll(boolean autoScroll){
        if (autoScroll){
            sendScrollMessage(mDelayTime);
        }else{
            mHandler.removeMessages(SCROLL_WHAT);
        }
        mAutoScroll=autoScroll;

    }
    public boolean isAutoScroll() {
        return mAutoScroll;
    }

    public int getDelayTime() {
        return mDelayTime;
    }

    public void setDelayTime(int delayTime) {
        mDelayTime = delayTime;
    }

    public boolean isAnimation() {
        return mIsAnimation;
    }

    public void setIsAnimation(boolean isAnimation) {
        mIsAnimation = isAnimation;
    }

实现接口相关函数

 @Override
    public void onPageScrolled(int i, float v, int i1) {

    }

    @Override
    public void onPageSelected(int position) {
        updateIndicator(position);
    }


    @Override
    public void onPageScrollStateChanged(int i) {

    }

以及一个单位转换的工具函数

private int dip2px(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getResources().getDisplayMetrics());
    }

使用

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:indicator="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    tools:context=".MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentTop="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        ></android.support.v4.view.ViewPager>

    <cn.edu.zafu.view.CircleIndicator
        android:id="@+id/circle_indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        indicator:circle_spacing="5dp"
        indicator:circle_radius="3dp"
        indicator:circle_fill_color="#728bff"
        indicator:circle_stroke_color="#aaa"
        indicator:circle_auto_scroll="true"
        >

    </cn.edu.zafu.view.CircleIndicator>
</RelativeLayout>
 private void initView() {
        mViewPager= (ViewPager) findViewById(R.id.viewpager);
        mCircleIndicator= (CircleIndicator) findViewById(R.id.circle_indicator);
        mViewPager.setAdapter(new FragmentPagerAdapter(getSupportFragmentManager()) {

            private int[] resId={R.mipmap.ic_help_view_1,R.mipmap.ic_help_view_2,R.mipmap.ic_help_view_3,R.mipmap.ic_help_view_4};
            private Map<Integer,Fragment> mFragments=new HashMap<Integer,Fragment>();
            @Override
            public Fragment getItem(int i) {
                Fragment fragment=mFragments.get(i);
                if(fragment==null){
                    fragment=BlankFragment.newInstance(resId[i],i,resId.length);
                    mFragments.put(i,fragment);
                }
                return fragment;
            }

            @Override
            public int getCount() {
                return resId.length;
            }
        });
        mCircleIndicator.setViewPager(mViewPager);
    }
package cn.edu.zafu.splash;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;


public class BlankFragment extends Fragment {

    private static final String IMAGE_ID = "imageId";
    private static final String CUCRNT = "curcent";
    private static final String TOTAL = "total";
    private int mImageId;
    private int mCurcent;
    private int mTotal;


    public static BlankFragment newInstance(int imageId,int current,int total) {
        BlankFragment fragment = new BlankFragment();
        Bundle args = new Bundle();
        args.putInt(IMAGE_ID, imageId);
        args.putInt(CUCRNT, current);
        args.putInt(TOTAL, total);
        fragment.setArguments(args);
        return fragment;
    }

    public BlankFragment() {

    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mImageId = getArguments().getInt(IMAGE_ID);
            mCurcent = getArguments().getInt(CUCRNT);
            mTotal = getArguments().getInt(TOTAL);

        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view= inflater.inflate(R.layout.fragment_blank, container, false);
        return view;
    }

    @Override
    public void onViewCreated(View view, Bundle savedInstanceState) {
        getActivity().getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        super.onViewCreated(view, savedInstanceState);
        ImageView imageView= (ImageView) view.findViewById(R.id.image);
        imageView.setImageResource(mImageId);
        if(mCurcent==mTotal-1){
            RelativeLayout relativeLayout= (RelativeLayout) view.findViewById(R.id.relativelayout);
            ImageButton button=new ImageButton(getActivity().getApplicationContext());
            button.setBackgroundResource(R.drawable.last_button_selector);

            RelativeLayout.LayoutParams params=new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT);

            params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
            params.addRule(RelativeLayout.CENTER_HORIZONTAL);
            params.bottomMargin=dip2px(80);
            relativeLayout.addView(button,params);
            button.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int versionCode=Util.getAppVersionCode(getActivity());
                    Util.set(getActivity(),Util.FILE_NAME,versionCode+"",true);
                    Intent intent=new Intent(getActivity(),SecondActivity.class);
                    startActivity(intent);
                    getActivity().finish();
                }
            });
        }
    }
    private int dip2px(int dip) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dip, getActivity().getResources().getDisplayMetrics());
    }

}

如果要实现是否首次启动,如果是才显示的话需要加一些逻辑判断,如果当前版本号已经持久化了,则直接跳过,这个数据是在Splash页面最后一个按钮点击事件里处理的

private boolean ignoreSplash() {
        if(Util.contatins(this, Util.FILE_NAME, Util.getAppVersionCode(this) + "")){
            Intent intent=new Intent(MainActivity.this,SecondActivity.class);
            startActivity(intent);
            this.finish();
            return true;
        }
        return false;
    }
public void onClick(View v) {
                    int versionCode=Util.getAppVersionCode(getActivity());
                    Util.set(getActivity(),Util.FILE_NAME,versionCode+"",true);
                    Intent intent=new Intent(getActivity(),SecondActivity.class);
                    startActivity(intent);
                    getActivity().finish();
                }

源码下载

Android实现用户引导界面

标签:splash   viewpager   indicator   autoscroll   slide   

原文地址:http://blog.csdn.net/sbsujjbcy/article/details/46531351

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!