写在前面:
参考文章
这里我用了anko插件:
集成anko步骤:
1:在build.gradle(Project)写入:ext.anko_version ='0.10.8'
2:在build.gradle(app)里面写入以下代码:
implementation "org.jetbrains.anko:anko-sdk25:$anko_version" implementation "org.jetbrains.anko:anko-sdk25-coroutines:$anko_version" implementation "org.jetbrains.anko:anko-appcompat-v7:$anko_version"```
各种样式效果
自定义View(五角星评分样式)
Anko里面的点击事件:
wujiaoxing.onClick {
startActivity<Five_Point_Star>(“name” to “tom”, “age” to 10)
}
Anko里面的页面跳转 :
startActivity< SecondActivity >()
带参数跳转:
startActivity< SecondActivity >(“name” to “tonjie”, “age” to 20)
SecondActivity接受参数:
val intent = intent
val name = intent.getStringExtra(“name”)
val age = intent.getStringExtra(“20”)
Log.d(“tonjies”, “name: " + name + " age:” + 20)
1.自定义属性
在attr.xml文件自定义一下属性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RatinaBar">
<!--星星的大半径-->
<attr name="mR" format="integer"></attr>
<!--星星的小半径-->
<attr name="mr" format="integer"/>
<!--星星是否填充-->
<attr name="mIsFill" format="boolean"/>
<!--星星的填充颜色-->
<attr name="mWuColor" format="color"/>
<!--星星的圆润度-->
<attr name="mWRaduis" format="integer"/>
<!--星星的个数-->
<attr name="mWNumber" format="integer"/>
</declare-styleable>
</resources>
在java里面获取属性值的方法:
int myHight;//整个控件的高度
int myWidth;//整个空间的宽度
int wu_R;//五角星的大半径
int wu_r;//五角星的小半径
boolean isfill;//是否填充
int mcolor;//五角星背景
int mWraduis;//五角星圆润度
int mWNumber;//五角星的数量
TypedArray tya = context.obtainStyledAttributes(attrs, R.styleable.mWujiaoxing);
wu_R = tya.getInt(R.styleable.mWujiaoxing_mR, 20);
wu_r = tya.getInt(R.styleable.mWujiaoxing_mr, 10);
isfill = tya.getBoolean(R.styleable.mWujiaoxing_mIsFill, false);
mcolor = tya.getColor(R.styleable.mWujiaoxing_mWuColor, 0xff00ff);
mWraduis = tya.getInteger(R.styleable.mWujiaoxing_mWRaduis, 0);
mWNumber = tya.getInteger(R.styleable.mWujiaoxing_mWNumber, 5);
tya.recycle();
在Kotlin里面获取属性值的方法:
var tya:TypedArray = context.obtainStyledAttributes(atrs, com.example.all_study_project.R.styleable.RatinaBar)
wu_R = tya.getInt( com.example.all_study_project.R.styleable.RatinaBar_mR,20)
wu_r = tya.getInt( com.example.all_study_project.R.styleable.RatinaBar_mr,10)
isfill = tya.getBoolean( com.example.all_study_project.R.styleable.RatinaBar_mIsFill, false);
mcolor = tya.getColor( com.example.all_study_project.R.styleable.RatinaBar_mWuColor, 0xff00ff);
mWraduis = tya.getInteger( com.example.all_study_project.R.styleable.RatinaBar_mWRaduis, 0);
mWNumber = tya.getInteger( com.example.all_study_project.R.styleable.RatinaBar_mWNumber, 5);
tya.recycle()
2.重载onMeasure方法
int myHight;//整个控件的高度
int myWidth;//整个空间的宽度
int one_width;//一个五角星占据的宽度
int half_width;//一个五角星占据的半个长度
Java代码:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
myWidth = getMySize(100, widthMeasureSpec);
myHight = getMySize(100, heightMeasureSpec);
one_width = myWidth / mWNumber;
half_width = one_width / 2;
setMeasuredDimension(myWidth, myHight);
}
int getMySize(int defaultSize, int meansureSpec) {
int mySize = defaultSize;
int mode = MeasureSpec.getMode(meansureSpec);//获得测量模式
int size = MeasureSpec.getSize(meansureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED:
mySize = defaultSize;
break;
case MeasureSpec.AT_MOST://wrap
mySize = size;
break;
case MeasureSpec.EXACTLY://100dp 或者 Match
mySize = size;
break;
}
return mySize;
}
kotlin代码:
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
Log.i("zjc", "onMeasure执行了")
myWidth = getMySize(1000,widthMeasureSpec)
myHight = getMySize(1000,heightMeasureSpec)
one_width = myWidth / mWNumber
half_width = one_width / 2
setMeasuredDimension(myWidth,myHight)
}
fun getMySize(defaultsize:Int,meansureSpec:Int):Int{
var mySize = defaultsize
var mode = MeasureSpec.getMode(meansureSpec)
var size = MeasureSpec.getSize(meansureSpec)
when (mode) {
View.MeasureSpec.UNSPECIFIED -> mySize = defaultsize;
View.MeasureSpec.AT_MOST -> mySize = size;
View.MeasureSpec.EXACTLY -> mySize = size;
}
return mySize
}
3.画一个五角星
r是小半径 R是大半径 (x,y)是中心点的坐标
java代码
void drawStar(int r, int R, int x, int y) {
mPath.moveTo((float) (Math.cos(Math.PI * (18 + 72 * 0) / 180) * R + x), (float) (Math.sin(Math.PI * (18 + 72 * 0) / 180) * R + y));
mPath.lineTo((float) (Math.cos(Math.PI * (54 + 72 * 0) / 180) * r + x), (float) (Math.sin(Math.PI * (54 + 72 * 0) / 180) * r + y));
for (int i = 1; i < 5; i++) {
mPath.lineTo((float) (Math.cos(Math.PI * (18 + 72 * i) / 180) * R + x), (float) (Math.sin(Math.PI * (18 + 72 * i) / 180) * R + y));
mPath.lineTo((float) (Math.cos(Math.PI * (54 + 72 * i) / 180) * r + x), (float) (Math.sin(Math.PI * (54 + 72 * i) / 180) * r + y));
}
mPath.close();
}
kotlin代码
fun drawStar(r: Int, R: Int, x: Int, y: Int) {
mPath.moveTo(
(Math.cos(Math.PI * (18 + 72 * 0) / 180) * R + x).toFloat(),
(Math.sin(Math.PI * (18 + 72 * 0) / 180) * R + y).toFloat()
)
mPath.lineTo(
(Math.cos(Math.PI * (54 + 72 * 0) / 180) * r + x).toFloat(),
(Math.sin(Math.PI * (54 + 72 * 0) / 180) * r + y).toFloat()
)
for (i in 1..4) {
mPath.lineTo(
(Math.cos(Math.PI * (18 + 72 * i) / 180) * R + x).toFloat(),
(Math.sin(Math.PI * (18 + 72 * i) / 180) * R + y).toFloat()
)
mPath.lineTo(
(Math.cos(Math.PI * (54 + 72 * i) / 180) * r + x).toFloat(),
(Math.sin(Math.PI * (54 + 72 * i) / 180) * r + y).toFloat()
)
}
mPath.close()
}
4.画很多星星
mWNumber是属性里面表示星星个数的属性
java代码:
void drawmany_star() {
mPath.reset();
for (int i = 0; i < mWNumber; i++) {
//第i个
float ss_xxx = (float) ((Math.cos(Math.PI * (18) / 180) * wu_R) + (one_width * i) + half_width);
float ss_yyy = (float) (Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R + myHight / 2);
float ee_xxx = (float) ((one_width * i) + half_width - (Math.cos(Math.PI * (18) / 180) * wu_R));
float ee_yyy = (float) (myHight / 2 - Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R);
drawStar(wu_R, wu_r, (one_width * i) + half_width, myHight / 2);
if(dsa == 1){
if (ee_xxx <= start_x && start_x <= ((one_width * (i+1)) + half_width - (Math.cos(Math.PI * (18) / 180) * wu_R)) && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
} else {
mPaint.setStyle(Paint.Style.STROKE);
}
}else{
if (ee_xxx <= start_x && start_x <= ss_xxx && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
} else {
mPaint.setStyle(Paint.Style.STROKE);
}
}
canvas.drawPath(mPath, mPaint);
}
}
kotlin代码:
fun drawmany_star(){
mPath.reset()
for (i in 0..mWNumber) {
//第i个
var ss_xxx:Float = (Math.cos(Math.PI * 18 / 180) * wu_R + one_width * i + half_width).toFloat()
var ss_yyy:Float = (Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R + myHight / 2).toFloat()
var ee_xxx:Float = (one_width * i + half_width - Math.cos(Math.PI * 18 / 180) * wu_R).toFloat()
var ee_yyy:Float = (myHight / 2 - Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R).toFloat()
drawStar(wu_R, wu_r, one_width * i + half_width, myHight / 2)
if (dsa === 1) {
if (ee_xxx <= start_x && start_x <= one_width * (i + 1) + half_width - Math.cos(Math.PI * 18 / 180) * wu_R && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.style = Paint.Style.FILL_AND_STROKE
} else {
mPaint.style = Paint.Style.STROKE
}
} else {
if (ee_xxx <= start_x && start_x <= ss_xxx && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.style = Paint.Style.FILL_AND_STROKE
} else {
mPaint.style = Paint.Style.STROKE
}
}
canvas?.drawPath(mPath,mPaint)
}
}
6.重写onDraw方法
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
drawmany_star();
}
7.重载onTouchEvent方法,获取手指事件比如点击,滑动
java代码:
int dsa = 1;//滑动
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dsa = 0;
start_x = event.getX();
start_y = event.getY();
//onItemSelectedListener.onItemSelect("星星被点击了");
invalidate();
return true;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
dsa = 1;
Log.i("zjcc",event.getX()+" ");
start_x = event.getX();
start_y = event.getY();
invalidate();
break;
}
return super.onTouchEvent(event);
}
kotlin代码:
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.getAction()) {
MotionEvent.ACTION_DOWN -> {
dsa = 0
start_x = event.getX().toDouble()
start_y = event.getY().toDouble()
//onItemSelectedListener.onItemSelect("星星被点击了");
invalidate()
return true
}
MotionEvent.ACTION_UP -> {
}
MotionEvent.ACTION_MOVE -> {
dsa = 1
Log.i("zjcc", event.getX().toString() + " ")
start_x = event.getX().toDouble()
start_y = event.getY().toDouble()
invalidate()
}
}
return super.onTouchEvent(event)
}
效果:
全部代码:
java代码:
public class CustomView extends View {
Paint mPaint;
Path mPath;
int myHight;//整个控件的高度
int myWidth;//整个空间的宽度
int wu_R;//五角星的大半径
int wu_r;//五角星的小半径
boolean isfill;//是否填充
int mcolor;//五角星背景
int mWraduis;//五角星圆润度
int mWNumber;//五角星的数量
int one_width;//一个五角星占据的宽度
int half_width;//一个五角星占据的半个长度
float start_x, start_y;//按下的坐标
float end_x, end, y;//滑动结束的坐标
//星星点击事件接口
private OnItemSelectedListener onItemSelectedListener;
Canvas canvas;
public CustomView(Context context) {
super(context);
}
public CustomView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(1);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPath = new Path();
TypedArray tya = context.obtainStyledAttributes(attrs, R.styleable.mWujiaoxing);
wu_R = tya.getInt(R.styleable.mWujiaoxing_mR, 20);
wu_r = tya.getInt(R.styleable.mWujiaoxing_mr, 10);
isfill = tya.getBoolean(R.styleable.mWujiaoxing_mIsFill, false);
mcolor = tya.getColor(R.styleable.mWujiaoxing_mWuColor, 0xff00ff);
mWraduis = tya.getInteger(R.styleable.mWujiaoxing_mWRaduis, 0);
mWNumber = tya.getInteger(R.styleable.mWujiaoxing_mWNumber, 5);
tya.recycle();//回收0x
if (isfill) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
mPaint.setColor(mcolor);
mPaint.setPathEffect(new CornerPathEffect(mWraduis));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
this.canvas = canvas;
drawmany_star();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
myWidth = getMySize(100, widthMeasureSpec);
myHight = getMySize(100, heightMeasureSpec);
one_width = myWidth / mWNumber;
half_width = one_width / 2;
setMeasuredDimension(myWidth, myHight);
}
int getMySize(int defaultSize, int meansureSpec) {
int mySize = defaultSize;
int mode = MeasureSpec.getMode(meansureSpec);//获得测量模式
int size = MeasureSpec.getSize(meansureSpec);
switch (mode) {
case MeasureSpec.UNSPECIFIED:
mySize = defaultSize;
break;
case MeasureSpec.AT_MOST://wrap
mySize = size;
break;
case MeasureSpec.EXACTLY://100dp 或者 Match
mySize = size;
break;
}
return mySize;
}
void drawStar(int r, int R, int x, int y) {
mPath.moveTo((float) (Math.cos(Math.PI * (18 + 72 * 0) / 180) * R + x), (float) (Math.sin(Math.PI * (18 + 72 * 0) / 180) * R + y));
mPath.lineTo((float) (Math.cos(Math.PI * (54 + 72 * 0) / 180) * r + x), (float) (Math.sin(Math.PI * (54 + 72 * 0) / 180) * r + y));
for (int i = 1; i < 5; i++) {
mPath.lineTo((float) (Math.cos(Math.PI * (18 + 72 * i) / 180) * R + x), (float) (Math.sin(Math.PI * (18 + 72 * i) / 180) * R + y));
mPath.lineTo((float) (Math.cos(Math.PI * (54 + 72 * i) / 180) * r + x), (float) (Math.sin(Math.PI * (54 + 72 * i) / 180) * r + y));
}
mPath.close();
}
void drawmany_star() {
mPath.reset();
for (int i = 0; i < mWNumber; i++) {
//第i个
float ss_xxx = (float) ((Math.cos(Math.PI * (18) / 180) * wu_R) + (one_width * i) + half_width);
float ss_yyy = (float) (Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R + myHight / 2);
float ee_xxx = (float) ((one_width * i) + half_width - (Math.cos(Math.PI * (18) / 180) * wu_R));
float ee_yyy = (float) (myHight / 2 - Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R);
drawStar(wu_R, wu_r, (one_width * i) + half_width, myHight / 2);
if(dsa == 1){
if (ee_xxx <= start_x && start_x <= ((one_width * (i+1)) + half_width - (Math.cos(Math.PI * (18) / 180) * wu_R)) && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
} else {
mPaint.setStyle(Paint.Style.STROKE);
}
}else{
if (ee_xxx <= start_x && start_x <= ss_xxx && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
} else {
mPaint.setStyle(Paint.Style.STROKE);
}
}
canvas.drawPath(mPath, mPaint);
}
}
int dsa = 1;//滑动
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
dsa = 0;
start_x = event.getX();
start_y = event.getY();
//onItemSelectedListener.onItemSelect("星星被点击了");
invalidate();
return true;
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_MOVE:
dsa = 1;
Log.i("zjcc",event.getX()+" ");
start_x = event.getX();
start_y = event.getY();
invalidate();
break;
}
return super.onTouchEvent(event);
}
//星星的点击事件
public interface OnItemSelectedListener {
public void onItemSelect(String content);
}
public void setOnItemSelectedListener(OnItemSelectedListener onItemSelectedListener) {
this.onItemSelectedListener = onItemSelectedListener;
}
}
kotlin代码:
class Customview @JvmOverloads constructor(context: Context, atrs: AttributeSet? = null, defStyleAttr: Int = 0) :
View(context, atrs, defStyleAttr) {
var mPaint = Paint()
var mPath = Path()
var myHight: Int = 0//整个控件的高度
var myWidth: Int = 0//整个控件的宽度
var wu_R: Int = 0//五角星的大半径
var wu_r: Int = 0//五角星的小半径
var isfill: Boolean = false//是否填充
var mcolor: Int = 0//五角星背景
var mWraduis: Int = 0//五角星圆润度
var mWNumber: Int = 0//五角星的数量
var one_width: Int = 0//一个五角星占据的宽度
var half_width: Int = 0//一个五角星占据的半个长度
var start_x: Double = 0.0 //按下的 x
var start_y: Double = 0.0 //按下的 y
var end_x: Double = 0.0 //滑动结束的 x
var end_y: Double = 0.0 //滑动结束的 y
var dsa = 1//滑动
var onItemSelect: OnItemSelectedListener? = null
var canvas:Canvas?=null;
init {
mPaint.isAntiAlias = true
mPaint.isDither = true
mPaint.style = Paint.Style.STROKE
mPaint.strokeWidth = 1.toFloat()
mPaint.strokeCap = Paint.Cap.ROUND
var tya:TypedArray = context.obtainStyledAttributes(atrs, R.styleable.RatinaBar)
wu_R = tya.getInt( R.styleable.RatinaBar_mR,20)
wu_r = tya.getInt( R.styleable.RatinaBar_mr,10)
isfill = tya.getBoolean( R.styleable.RatinaBar_mIsFill, false);
mcolor = tya.getColor(R.styleable.RatinaBar_mWuColor, 0xff00ff);
mWraduis = tya.getInteger( R.styleable.RatinaBar_mWRaduis, 0);
mWNumber = tya.getInteger( R.styleable.RatinaBar_mWNumber, 5);
tya.recycle()
if(isfill){
mPaint.style = Paint.Style.FILL
}
mPaint.color = mcolor
mPaint.setPathEffect(CornerPathEffect(mWraduis.toFloat()))
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
this.canvas = canvas
drawmany_star();
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
Log.i("zjc", "onMeasure执行了")
myWidth = getMySize(1000,widthMeasureSpec)
myHight = getMySize(1000,heightMeasureSpec)
one_width = myWidth / mWNumber
half_width = one_width / 2
setMeasuredDimension(myWidth,myHight)
}
fun drawmany_star(){
mPath.reset()
for (i in 0..mWNumber) {
//第i个
var ss_xxx:Float = (Math.cos(Math.PI * 18 / 180) * wu_R + one_width * i + half_width).toFloat()
var ss_yyy:Float = (Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R + myHight / 2).toFloat()
var ee_xxx:Float = (one_width * i + half_width - Math.cos(Math.PI * 18 / 180) * wu_R).toFloat()
var ee_yyy:Float = (myHight / 2 - Math.sin(Math.PI * (18 + 72 * 1) / 180) * wu_R).toFloat()
drawStar(wu_R, wu_r, one_width * i + half_width, myHight / 2)
if (dsa === 1) {
if (ee_xxx <= start_x && start_x <= one_width * (i + 1) + half_width - Math.cos(Math.PI * 18 / 180) * wu_R && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.style = Paint.Style.FILL_AND_STROKE
} else {
mPaint.style = Paint.Style.STROKE
}
} else {
if (ee_xxx <= start_x && start_x <= ss_xxx && ee_yyy <= start_y && start_y <= ss_yyy) {
mPaint.style = Paint.Style.FILL_AND_STROKE
} else {
mPaint.style = Paint.Style.STROKE
}
}
canvas?.drawPath(mPath,mPaint)
}
}
fun drawStar(r: Int, R: Int, x: Int, y: Int) {
mPath.moveTo(
(Math.cos(Math.PI * (18 + 72 * 0) / 180) * R + x).toFloat(),
(Math.sin(Math.PI * (18 + 72 * 0) / 180) * R + y).toFloat()
)
mPath.lineTo(
(Math.cos(Math.PI * (54 + 72 * 0) / 180) * r + x).toFloat(),
(Math.sin(Math.PI * (54 + 72 * 0) / 180) * r + y).toFloat()
)
for (i in 1..4) {
mPath.lineTo(
(Math.cos(Math.PI * (18 + 72 * i) / 180) * R + x).toFloat(),
(Math.sin(Math.PI * (18 + 72 * i) / 180) * R + y).toFloat()
)
mPath.lineTo(
(Math.cos(Math.PI * (54 + 72 * i) / 180) * r + x).toFloat(),
(Math.sin(Math.PI * (54 + 72 * i) / 180) * r + y).toFloat()
)
}
mPath.close()
}
fun getMySize(defaultsize:Int,meansureSpec:Int):Int{
var mySize = defaultsize
var mode = MeasureSpec.getMode(meansureSpec)
var size = MeasureSpec.getSize(meansureSpec)
when (mode) {
View.MeasureSpec.UNSPECIFIED -> mySize = defaultsize;
View.MeasureSpec.AT_MOST -> mySize = size;
View.MeasureSpec.EXACTLY -> mySize = size;
}
return mySize
}
interface OnItemSelectedListener {
fun onItemSelect(content: String)
}
fun setOnItemSelectedListener(onItemSelect: OnItemSelectedListener) {
this.onItemSelect = onItemSelect
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.getAction()) {
MotionEvent.ACTION_DOWN -> {
dsa = 0
start_x = event.getX().toDouble()
start_y = event.getY().toDouble()
//onItemSelectedListener.onItemSelect("星星被点击了");
invalidate()
return true
}
MotionEvent.ACTION_UP -> {
}
MotionEvent.ACTION_MOVE -> {
dsa = 1
Log.i("zjcc", event.getX().toString() + " ")
start_x = event.getX().toDouble()
start_y = event.getY().toDouble()
invalidate()
}
}
return super.onTouchEvent(event)
}
}