android 用户操作引导,Android实现用户引导界面

首先看效果图,盗了超级课程表几张图

70164699_1.gif

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

分析

主要使用ViewPager+Indicator实现

主要是实现一个圆形指示器,这个圆形指示器继承LinearLayout,需要有一些属性可以自定义,比如指示器的颜色,大小,边距等

这个指示器也可以自动滚动,比如应用在幻灯片展示的地方

指示器是圆形的,需要我们自己绘制

这个圆形指示器实现了ViewPager.OnPageChangeListener接口

实现

定义自定义属性

属性的意思见名字就可以知道了

定义自定义变量,从布局文件中解析进来,此外,如果布局文件没有使用,应该有一个默认的常量.

定义默认常量 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());

}

使用

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: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: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"

>

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 mFragments=new HashMap();

@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();

}

源码下载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值