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

来源:互联网 发布:java 函数形参和实参 编辑:程序博客网 时间:2024/06/11 13:00


一款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;// 用来纪录用户是否安装后的首次启动@Overrideprotected 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;@Overrideprotected void onCreate(Bundle savedInstanceState) {// TODO Auto-generated method stubsuper.onCreate(savedInstanceState);setContentView(R.layout.guidance_layout);relativiveLayout=(RelativeLayout)findViewById(R.id.relativiveLayout);relativiveLayout.setOnClickListener(this);}@Overridepublic 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);}@Overridepublic 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));}@Overridepublic 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


0 0