带箭头的曲线(自定义的贝塞尔曲线和首次启动 app的引导界面)



一款App首次安装启动以后一半会有引导用户使用的提示,下面是一个简单的引导界面,此功能实现效果如图,点击屏幕时候引导界面结束,之后每次启动不会出现,除非重新安装。

实现原理:两个Activity,两个自定义View控件

MainActivity

package com.example.bezierdemo;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

public class MainActivity extends Activity {
private SharedPreferences sharedPreferences;
private Boolean isFirstInstall;// 用来纪录用户是否安装后的首次启动
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		sharedPreferences = this.getSharedPreferences("lidan", Context.MODE_PRIVATE);
		SharedPreferences.Editor s = sharedPreferences.edit();
	
		isFirstInstall=sharedPreferences.getBoolean("isFirstInstall", false);
		if(!isFirstInstall){  
			Toast.makeText(this, "安装后首次启动", 50000).show();
			startActivity(new Intent(MainActivity.this, GuidanceActivity.class));
			s.putBoolean("isFirstInstall", true);
			s.commit();
		}else{
			Toast.makeText(this, "启动", 50000).show();
		}
	}
}

其布局只有一个按钮

GuidanceActivity引导界面

package com.example.bezierdemo;

import android.R.bool;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.RelativeLayout;
/*
 * 引导界面,一般用于App安装后首次启动引导用户操作的提示
 * 此界面由自定义的贝塞尔曲线辅助完成
 * 一定要记得注册
 *         <activity
            android:name=".GuidanceActivity"
            android:theme="@android:style/Theme.Translucent" />
 * */
public class GuidanceActivity  extends Activity implements OnClickListener{
private RelativeLayout relativiveLayout;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		setContentView(R.layout.guidance_layout);
		relativiveLayout=(RelativeLayout)findViewById(R.id.relativiveLayout);	
		relativiveLayout.setOnClickListener(this);

	}

	@Override
	public void onClick(View v) {
		finish();
		
	}

}

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/com.example.bezierdemo"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:id= "@+id/relativiveLayout"
    android:background="#b0000000"
    >
     <!--xmlns:app="http://schemas.android.com/apk/res/com.example.bezierdemo"一定要记得声明,
     因为BezierCircleView和BezierView都用到了自定义的属性,如果不声明自定义属性就会报错
     设置半透明背景,否则看不到圆形的效果-->
      <com.example.bezierdemo.BezierCircleView
        xmlns:aa="http://schemas.android.com/apk/res/com.example.bezierdemo"
        android:id="@+id/bezierCircleView1"
        android:layout_width="100dip"
        android:layout_height="150dip"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />
  <!--BezierView的属性使用:app:center_point="true"设置曲线突出如果是false凹陷
        app:end_point="2"线的起始点,0-9 对应九个不同起始方位
        line:start_point="3"线的终点位置  0-9  同样对应九个不同方位-->
    <com.example.bezierdemo.BezierView
        xmlns:line="http://schemas.android.com/apk/res/com.example.bezierdemo"
        android:id="@+id/bezierView1"
        android:layout_width="30dip"
        android:layout_height="50dip"
        android:layout_alignRight="@+id/bezierCircleView1"
        android:layout_alignTop="@+id/bezierCircleView1"
        android:layout_marginRight="85dp"
        android:layout_marginTop="81dp"
        app:center_point="true"
        app:end_point="2"
        line:start_point="3" />


   <TextView
       android:id="@+id/remain_text"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_alignRight="@+id/bezierCircleView1"
       android:layout_below="@+id/bezierView1"
       android:layout_marginRight="41dp"
       android:text="点击按钮分享给好友" />
  
</RelativeLayout>

自定义的View  带箭头的贝塞尔曲线

<span style="font-size:18px;">package com.example.bezierdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/*
 * 自定义的贝塞尔曲线包含箭头
 * paint1绘制贝塞尔曲线 
 * paint2绘制的是箭头
 * 绘制原理是九个方位
 * */
public class BezierView extends View{
private Paint paint1,paint2;
public static final int LEFT_TOP = 1;
public static final int RIGHT_TOP = 2;
public static final int LEFT_BOTTOM = 3;
public static final int RIGHT_BOTTOM = 4;
public static final int LEFT_CENTER = 5;
public static final int TOP_CENTER = 6;
public static final int RIGHT_CENTER = 7;
public static final int BOTTOM_CENTER = 8;
public static final int CENTER = 9;
private int startPoint = LEFT_TOP;
private int endPiont = RIGHT_BOTTOM;
private boolean centerPoint = true;// 默认向上凸起
	public BezierView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context, attrs);
	}
	
	public BezierView(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	
	public BezierView(Context context) {
		this(context, null, 0);
	}
	
	public void initView(Context context, AttributeSet attrs) {
		if (attrs != null) {
//			设置自定义的属,在values下建立了attr.xml文件在其中设置属性,BezierView_start_point是起始点方位,
//			BezierView_end_point是终点方位,BezierView_center_point是曲线的凹凸设置
			TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BezierView);
			startPoint = a.getInteger(R.styleable.BezierView_start_point, startPoint);
			centerPoint = a.getBoolean(R.styleable.BezierView_center_point, centerPoint);
			endPiont = a.getInteger(R.styleable.BezierView_end_point, endPiont);
		}else{}
		paint1 = new Paint();
		paint1.setAntiAlias(true);
		paint1.setColor(Color.BLACK);
		paint2 = new Paint();
		paint2.setAntiAlias(true);
		paint2.setColor(Color.BLACK);
	}

	@Override
	public void draw(Canvas canvas) {
		if(canvas==null)
		return;
		// 画线-----------
		paint1.setStyle(Paint.Style.STROKE);
		paint1.setColor(Color.BLACK);
		Path path = new Path();
		Path path2 = new Path();
		changerStartPoint(path, path2);// 起点
		changerEndPoint(path, path2);// 终点
		canvas.drawPath(path, paint1);// 画出贝塞尔曲线
		canvas.drawPath(path2, paint2);

	}
	

	
	
	/**
	 * 设置Path的起点
	 * 
	 * @param path
	 */
	private void changerStartPoint(Path path, Path path2) {
		switch (startPoint) {
		case LEFT_TOP:
			path.moveTo(0, 0);
			if (centerPoint) {
				path2.moveTo(getWidth() - getWidth() / 7, getHeight() - getHeight() / 5);
			} else {
				path2.moveTo(getWidth() - getWidth() / 5, getHeight() - getHeight() / 7 * 2);
			}
			break;
		case LEFT_BOTTOM:
			path.moveTo(0, getHeight());
			if (centerPoint) {
				path2.moveTo(getWidth() - getWidth() / 5, getHeight() / 10);
			} else {
				path2.moveTo(getWidth() - getWidth() / 5, getHeight() / 3);
			}
			break;
		case LEFT_CENTER:
			path.moveTo(0, getHeight() / 2);
			break;
		case RIGHT_TOP:
			path.moveTo(getWidth(), 0);
			if (centerPoint) {
				path2.moveTo(getWidth() / 10, getHeight() - getHeight() / 5);
			} else {
				path2.moveTo(getWidth() / 5, getHeight() - getHeight() / 3);
			}
			break;
		case RIGHT_BOTTOM:
			path.moveTo(getWidth(), getHeight());
			break;
		case RIGHT_CENTER:
			path.moveTo(getWidth(), getHeight() / 2);
			break;
		case TOP_CENTER:
			path.moveTo(getWidth() / 2, 0);
			break;
		case BOTTOM_CENTER:
			path.moveTo(getWidth() / 2, getHeight());
			break;
		case CENTER:
			path.moveTo(getWidth() / 2, getHeight() / 2);
			break;
		}
	}
	/**
	 * 设置贝塞尔曲线的控制点坐标和终点坐标
	 * 
	 * @param path
	 */
	private void changerEndPoint(Path path, Path path2) {
		Log.e("", startPoint + "    " + endPiont);
		switch (endPiont) {
		case LEFT_TOP:
			if (centerPoint) {
				path.quadTo(getWidth() / 4, getHeight() / 2, getWidth(), getHeight() / 2);
			} else {
			}
			break;
		case LEFT_BOTTOM:
			if (centerPoint) {
				// 画曲线
				path.quadTo(getWidth() / 2 - getWidth() / 3, getHeight() / 2 - getHeight() / 3, getWidth() / 5, getHeight() - getHeight() / 14);
				// 画箭头
				path2.quadTo(getWidth() / 5, getHeight(), getWidth() / 5 + getWidth() / 12, getHeight() - getHeight() / 5);
			} else {
				// 画曲线
				path.quadTo(getWidth() / 2 + getWidth() / 3, getHeight() / 2 + getHeight() / 3, getWidth() / 10, getHeight() - getHeight() / 5);
				// 画箭头
				path2.quadTo(0, getHeight() - getHeight() / 5, getWidth() / 5, getHeight() - getHeight() / 8);
			}
			break;
		case LEFT_CENTER:
			path.moveTo(0, getHeight() / 2);
			break;
		case RIGHT_TOP:
			if (centerPoint) {
				// 画曲线
				path.quadTo(getWidth() / 2 - getWidth() / 3, getHeight() / 2 - getHeight() / 3, getWidth() - getWidth() / 12, getHeight() / 5);
				// 画箭头
				path2.quadTo(getWidth(), getHeight() / 5, getWidth() - getWidth() / 5, getHeight() / 5 + getHeight() / 10);
			} else {
				// 画曲线
				path.quadTo(getWidth() / 2 + getWidth() / 3, getHeight() / 2 + getHeight() / 3, getWidth() - getWidth() / 12, getHeight() / 5);
				// 画箭头
				path2.quadTo(getWidth() - getWidth() / 12, 0, getWidth(), getHeight() / 5 * 2);
			}
			break;
		case RIGHT_BOTTOM:
			if (centerPoint) {
				// 画曲线
				path.quadTo(getWidth() / 2 + getWidth() / 3, getHeight() / 2 - getHeight() / 3, getWidth() - getWidth() / 5, getHeight()
						- getHeight() / 14);
				// 画箭头
				path2.quadTo(getWidth() - getWidth() / 5, getHeight(), getWidth() - getWidth() / 5 - getWidth() / 14, getHeight() - getHeight() / 5);
			} else {
				// 画曲线
				path.quadTo(getWidth() / 2 - getWidth() / 3, getHeight() / 2 + getHeight() / 3, getWidth() - getWidth() / 12, getHeight()
						- getHeight() / 5);
				// 画箭头
				path2.quadTo(getWidth(), getHeight() - getHeight() / 5, getWidth() - getWidth() / 5, getHeight() - getHeight() / 8);
			}
			break;
		case RIGHT_CENTER:
			path.moveTo(getWidth(), getHeight() / 2);
			break;
		case TOP_CENTER:
			path.moveTo(getWidth() / 2, 0);
			break;
		case BOTTOM_CENTER:
			path.moveTo(getWidth() / 2, getHeight());
			break;
		case CENTER:
			path.moveTo(getWidth() / 2, getHeight() / 2);
			break;
		}
	}

}
</span>
圆形的贝塞尔曲线

<span style="font-size:18px;">package com.example.bezierdemo;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.View;


public class BezierCircleView extends View{
	private Paint paint;
	private boolean isCircle = true;
	private static final int LAYER_FLAGS = Canvas.MATRIX_SAVE_FLAG | Canvas.CLIP_SAVE_FLAG | Canvas.HAS_ALPHA_LAYER_SAVE_FLAG
			| Canvas.FULL_COLOR_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG;

	public BezierCircleView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initView(context, attrs);
	}

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

	public BezierCircleView(Context context) {
		this(context, null, 0);
	}

	public void initView(Context context, AttributeSet attrs) {
		if (attrs != null) {
			TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.BezierCircleView);
			isCircle = a.getBoolean(R.styleable.BezierCircleView_is_circle, isCircle);
		}
		paint = new Paint();
		paint.setAntiAlias(true);
		paint.setColor(Color.BLUE);
		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
	}

	@Override
	public void draw(Canvas canvas) {
		if (canvas == null) {
			return;
		}
		if (isCircle) {
			int r = getWidth() > getHeight() ? getHeight() / 2 : getWidth() / 2;
			canvas.drawCircle(getWidth() / 2, getHeight() / 2, r, paint);
			canvas.saveLayerAlpha(0, 0, 200, 200, 0x20, LAYER_FLAGS);// 新建图层并指定透明度,图层位于栈顶,所以直到restore以前的操作都只作用于此图层
			canvas.restore();// 将新建的图层合并到画布上
		} else {
			canvas.drawColor(Color.TRANSPARENT, Mode.CLEAR);
		}

	}
}
</span>

自定义属性 attrr.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
        <!-- 向导箭头属性 -->
    <declare-styleable name="BezierView">
        <attr name="start_point" format="integer"></attr>
        <attr name="center_point" format="boolean"></attr>
        <attr name="end_point" format="integer"></attr>
    </declare-styleable>
        <!-- 向导圆的半径 -->
    <declare-styleable name="BezierCircleView">
        <attr name="is_circle" format="boolean"></attr>
    </declare-styleable>
    
</resources>



源代码下载地址  http://download.csdn.net/download/xubeiqiannian/8791303


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值