Android进阶——自定义View之自己绘制彩虹圆环调色板
Android开发使用自定义View将圆角矩形绘制在Canvas上的方法

Android开发使⽤⾃定义View将圆⾓矩形绘制在Canvas上的⽅法本⽂实例讲述了Android开发使⽤⾃定义View将圆⾓矩形绘制在Canvas上的⽅法。
分享给⼤家供⼤家参考,具体如下:前⼏天,公司⼀个项⽬中,头像图⽚需要添加圆⾓,这样UI效果会更好看,于是写了⼀个⼩的demo进⾏圆⾓的定义,该处主要是使⽤BitmapShader进⾏了渲染(如果要将⼀张图⽚裁剪成椭圆或圆形显⽰在屏幕上,也可以使⽤BitmapShader来完成).BitmapShader类完成渲染图⽚的基本步骤如下:1、创建BitmapShader类的对象/*** Call this to create a new shader that will draw with a bitmap.** @param bitmap The bitmap to use inside the shader* @param tileX The tiling mode for x to draw the bitmap in.* @param tileY The tiling mode for y to draw the bitmap in.*/public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {......}其中,Shader.TitleMode类型有三种,CALMP、MIRROR、REPEATCALMP:使⽤边界颜⾊来填充剩余空间MIRROR:使⽤镜像⽅式REPEAT:使⽤重复⽅式2、通过Paint的setShader(bitmapShafer)来设置画笔3、使⽤已经setShader(bitmapShafer)的画笔来绘制图形下⾯展⽰绘制圆⾓图⽚的demo1、⾃定义RounderCornerImageView.java类package com.example.test;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.RectF;import android.graphics.Shader;import android.util.AttributeSet;import android.view.View;public class RounderCornerImageView extends View {private Bitmap mImage;// source bitmapprivate Paint mBitmapPaint;//paintprivate RectF mBrounds;//rectprivate float mRadius=20.0f;//roundpublic RounderCornerImageView(Context context) {this(context, null);}public RounderCornerImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RounderCornerImageView(Context context, AttributeSet attrs,int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mBitmapPaint=new Paint(Paint.ANTI_ALIAS_FLAG);mBrounds=new RectF();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {// TODO Auto-generated method stubint height,width;height=width=0;//obtain bitmap sizeint imageHeight,imageWidth;if (null!=mImage) {imageHeight=imageWidth=0;}else{imageHeight=mImage.getHeight();imageWidth=mImage.getWidth();}//obtain best measure data and set on Viewwidth=getMeasurement(widthMeasureSpec,imageWidth);height=getMeasurement(heightMeasureSpec, imageHeight);//set View last sizesetMeasuredDimension(width, height);}/*** measure width and height by specMode**/private int getMeasurement(int measureSpec, int contentSize) {int specSize=MeasureSpec.getSize(measureSpec);switch (MeasureSpec.getMode(measureSpec)) {case MeasureSpec.AT_MOST:return Math.min(specSize, contentSize);case MeasureSpec.UNSPECIFIED:return contentSize;case MeasureSpec.EXACTLY:return specSize;default:return 0;}//switch}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {if (w!=oldw || h!=oldh) {int imageWidth,imageHeight;if (null==mImage) {imageWidth=imageHeight=0;}else{imageWidth=mImage.getWidth();imageHeight=mImage.getHeight();}//center pointint left=(w-imageWidth)/2;int top=(h-imageHeight)/2;mBrounds.set(left, top, left+imageWidth, top+imageHeight);if (null!=mBitmapPaint.getShader()) {Matrix m=new Matrix();m.setTranslate(left, top);mBitmapPaint.getShader().setLocalMatrix(m);}}}public void setImage(Bitmap bitmap) {if (mImage!=bitmap) {mImage=bitmap;if (null!=mImage) {BitmapShader shader=new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); mBitmapPaint.setShader(shader);}else {mBitmapPaint.setShader(null);}requestLayout();//invalidated the layout of this view by onDraw()}}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (null!=mBitmapPaint) {//draw Round Rectcanvas.drawRoundRect(mBrounds, mRadius, mRadius, mBitmapPaint);}}}2、显⽰圆⾓图⽚的RoundActivity.java类package com.example.test;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;public class RoundActivity extends Activity{@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);RounderCornerImageView view=new RounderCornerImageView(this);Bitmap souBitmap=BitmapFactory.decodeResource(getResources(), R.drawable.sun);view.setImage(souBitmap);setContentView(view);}}另外,附注下⾃定义View的⼀些基本步骤和必须实现的⽅法1、继承view2、重写⾃定义View的构造⽅法3、如需要对view进⾏位置进⾏测量和重写布局,则需要重写onMeasure()、onLayout()、onDraw()⽅法onMeasure():view本⾝⼤⼩多少,可以测量出来onLayout():view在ViewGroup中的位置可以决定onDraw():定义了如何绘制该view更多关于Android相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》及《》希望本⽂所述对⼤家Android程序设计有所帮助。
Android自定义View(一、初体验自定义TextView)

Android自定义View(一、初体验自定义TextView)对于一个Android攻城狮来说,自定义控件是一项必须掌握的重要技能点,然而对于大部分人而言,感觉自定义控件并不是那么容易。
在工作过程中难免遇到一些特效需要自己定义控件实现,如果你不会,内心会有强烈的挫败感,这对一个程序员来说是决不能容忍的,接下来我将写一系列博客,和大家一起学习自定义控件,让她赤裸裸的站在我们的面前,让我们为所欲为…:joy:言归正传,接触到一个类,你不太了解他,如果贸然翻阅源码只会让你失去方向,不知从哪里下手;所以我们应该从文档着手,看看它是个什么东西,里面有哪些属性和方法,都是用来干嘛的。
下面我们看看官方文档对View的介绍:View这个类代表用户界面组件的基本构建块。
View在屏幕上占据一个矩形区域,并负责绘制和事件处理。
View是用于创建交互式用户界面组件(按钮、文本等)的基础类。
它的子类ViewGroup是所有布局的父类,它是一个可以包含其他view或者viewGroup并定义它们的布局属性的看不见的容器。
实现一个自定义View,你通常会覆盖一些framework层在所有view上调用的标准方法。
你不需要重写所有这些方法。
事实上,你可以只是重写onDraw(android.graphics.Canvas)。
从上面官方文档介绍我们可以知道,View是所有控件(包括ViewGroup)的父类,它里面有一些常见的方法(上表),如果我们要自定义View,最简单的只需要重写onDraw(android.graphics.Canvas)即可,听起来是不是很简单?那我们就动手自定义一个属于自己的TextView吧。
1. 继承View,重写onDraw方法创建一个类MyTextView继承View,发现报错,因为要覆盖他的构造方法(因为View 中没有参数为空的构造方法),View有四种形式的构造方法,其中四个参数的构造方法是API 21才出现,所以一般我们只需要重写其他三个构造方法即可。
Android自定义View中Paint、Rect、Canvas介绍(一)

Android⾃定义View中Paint、Rect、Canvas介绍(⼀)⾃定义View对于新⼿⽽⾔貌似是⼀个很复杂的东西。
格式,各函数的意义。
对于⼤神经常忘记各函数及⼀些参数的具体写法及意义,刚好在做⼀个风车效果,把过程及遇到的问题都写下来1、如何⾃定义⼀个Viewpublic class LeafView extends View {private String TAG = "--------LeafView";public LeafView(Context context, AttributeSet attrs) {super(context, attrs);Log.i(TAG, "我是⾃定义View: LeafView");}}<LinearLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:orientation="vertical"android:background="@color/colorPrimary"><com.my.LeafViewandroid:id="@+id/leafView"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="center_horizontal"/></LinearLayout>上⾯就是⾃定义了⼀个LeafView最简单的写法。
当然界⾯上什么都不会显⽰,除了LinearLayout的背景⾊2、onDraw(Canvas canvas)⽅法我们现来看下⾯⼀段代码,画出⼀个红⾊的正⽅形public class MyView extends View {private String TAG = "--------MyView";private int width, height;public MyView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {super.onSizeChanged(w, h, oldw, oldh);width = w;height = h;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Rect rect = new Rect(0, 0, width, height);Paint paint = new Paint();paint.setColor(Color.RED);canvas.drawRect(rect, paint);}}通过看上⾯代码,有⼀个onSizeChanged()、onDraw()、canvas.drawRect()⽅法,有⼀个Paint, Rect, Canvas类1、onSizeChanged() 当View的⼤⼩发⽣改变时,会调⽤此⽅法。
Android-解析自定义view之圆形头像的各类方案

Android-解析自定义view之圆形头像的各类方案我们可以看到很多app都采用了圆形头像,那么怎么绘制圆形头像才是性能最好?代码复用性最强?也最方便呢?本博主做了一些探究。
文章结构:1.利用shape来制作圆形头像(一种死方案,要求是美工愿意配合你) 2.结合一个会导致oom的实现圆形头像方案进行性能分析 3.最优的圆形头像方案一、利用shape来制作圆形头像(要求是美工愿意配合你)为什么要求美工配合你呢??因为这个方案是在ImageView直接调用资源文件的,也就是直接用了ImageView的LayoutParams的match_parent模式。
不能按照那个圆的大小来适配。
给出代码讲解:drawable文件的shape标签<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="/apk/res/android"android:shape="oval"><!-- Corner的属性是设置圆角的半径的--><solid android:color="#FFFFFF" /><strokeandroid:width="2dp"android:color="#777777"></stroke><sizeandroid:width="120dp"android:height="120dp" /></shape>在xml文件中的调用:<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context="com.demo.fuzhucheng.someShapesImageview.ImageViewActivity"><!--第一种方案--><ImageViewandroid:id="@+id/shapecircle"android:layout_width="150dp"android:layout_height="150dp"android:background="@drawable/activity_circle_circleimageview"android:src="@drawable/activity_imageview_photo" /><!--最优方案,也就是本文的第三种方案--><com.demo.fuzhucheng.someShapesImageview.CircleImageview android:id="@+id/mycircle"android:layout_width="180dp"android:layout_height="180dp"android:background="@color/white"android:src="@drawable/timg"app:backgroundHeadColor="@color/yellow"app:circleBorderHeadWidth="5dp"app:ringHeadColor="@color/colorAccent" /></LinearLayout>二、对一种容易导致OOM的方案进行分析:给出代码分析:下面这个是别人的代码,由于点评就不给链接的。
Android自定义view制作抽奖转盘

Android⾃定义view制作抽奖转盘本⽂实例为⼤家分享了Android⾃定义view制作抽奖转盘的具体代码,供⼤家参考,具体内容如下效果图TurntableActivitypackage com.bawei.myapplication.turntable;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.MotionEvent;import android.view.View;import android.view.animation.RotateAnimation;import com.bawei.myapplication.R;import com.bawei.myapplication.turntable.CustomTurntableView;/*** 转盘* @author hasee*/public class TurntableActivity extends AppCompatActivity {CustomTurntableView customTurntableView;boolean isTouchInSide = false;float mDownX, mDownY;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_turntable);initView();}private void initView() {customTurntableView = findViewById(R.id.custom);// findViewById(R.id.custom_inside).setOnClickListener(new View.OnClickListener() {// @Override// public void onClick(View v) {// float degrees = (float)(720 + Math.random() * 1000);// RotateAnimation rotateAnimation = new RotateAnimation(0, -degrees, 450, 450); // rotateAnimation.setDuration(5000);// rotateAnimation.setFillAfter(true);// customCircleView.startAnimation(rotateAnimation);// }// });findViewById(R.id.custom_inside).setOnTouchListener(new View.OnTouchListener() { @Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_DOWN &&event.getX() > 200 &&event.getX() < 300 &&event.getY() > 200 &&event.getY() < 300) {isTouchInSide = true;mDownX = event.getX();mDownY = event.getY();return true;}else if(event.getAction() == MotionEvent.ACTION_MOVE && (event.getX() < mDownX -10 ||event.getX() > mDownX + 10 ||event.getY() < mDownY -10 ||event.getY() > mDownY + 10) ){isTouchInSide = false;} else if (event.getAction() == MotionEvent.ACTION_UP &&event.getX() > mDownX -10 &&event.getX() < mDownX + 10 &&event.getY() > mDownY -10 &&event.getY() < mDownY + 10 &&isTouchInSide) {float degrees = (float) (720 + Math.random() * 1000);RotateAnimation rotateAnimation = new RotateAnimation(0, -degrees, 250, 250);rotateAnimation.setDuration(5000);rotateAnimation.setFillAfter(true);customTurntableView.startAnimation(rotateAnimation);}isTouchInSide = false;return false;}});}}对应的布局<?xml version="1.0" encoding="utf-8"?><RelativeLayoutxmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:id="@+id/ll"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:context=".MainActivity"><com.bawei.myapplication.turntable.CustomTurntableViewandroid:id="@+id/custom"android:layout_width="wrap_content"android:layout_height="500dp"/><com.bawei.myapplication.turntable.CustomTurntableInsideViewandroid:id="@+id/custom_inside"android:layout_width="wrap_content"android:layout_height="500dp"app:text="开始"android:background="#3300ff00" /></RelativeLayout>⾃定义CustomTurntableView继承viewpackage com.bawei.myapplication.turntable;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;/*** 这⾥是画转盘的* @author hasee*/public class CustomTurntableView extends View{Paint mPaint;int mCircleCount = 6;float mStartAngle = 0;RectF rectF;public CustomTurntableView(Context context) {super(context);init();}public CustomTurntableView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}private void init(){mPaint = new Paint();mPaint.setColor(Color.BLUE);mPaint.setStrokeWidth(10);mPaint.setTextSize(60);mPaint.setStyle(Paint.Style.FILL);rectF = new RectF();rectF.top = 100;rectF.left = 100;rectF.right = 400;rectF.bottom = 400;}String[] textColor = {"⼀等奖","⼆等奖","三等奖","四等奖","五等奖","六等奖"}; @Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);for(int i = 0; i < mCircleCount; i++){//按⾓标单双号设置扇形颜⾊,if(i % 2 == 0 ){mPaint.setColor(Color.BLUE);}else{mPaint.setColor(Color.GREEN);}canvas.drawArc(rectF, mStartAngle, 60, true, mPaint);//设置转盘上的⽂字mPaint.setColor(Color.BLACK);mPaint.setTextSize(20);Path path = new Path();path.addArc(rectF,mStartAngle+20,60);canvas.drawTextOnPath(textColor[i],path,-10,40,mPaint);mStartAngle += 60;}}}⾃定义CustomTurntableInsideView继承viewpackage com.bawei.myapplication.turntable;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.View;import com.bawei.myapplication.R;/*** 转盘中间开始按钮和指针* @author hasee*/public class CustomTurntableInsideView extends View {/*** 画笔*/Paint mPaint;RectF mRectF;String mStr;public CustomTurntableInsideView(Context context) {super(context);init();}public CustomTurntableInsideView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);//⾃定义属性,如何添加⾃定义属性如下(考点)//第⼀步:在values⽂件夹下创建attrs.xml//第⼆步:详见attrs.xml⽂件内部//第三步:在所在的布局⽂件的根layout中添加xmlns:app="/apk/res-auto"//第四步:在布局⽂件的控件中添加app:"你在attrs中设置的attr name"="你的值"//第五步:调⽤下⾯这句话,最后的为R.styleable.你在attrs中设置的declare-styleable nameTypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomTurntableView);//第六步:调⽤下⾯这句话,根据你在attrs中设置的format,选择getXXX⽅法,//⼊参为 R.styleable. 加上你在attrs中设置的declare-styleable name 加上 _ 加上你在attrs中设置的attr name mStr = typedArray.getString(R.styleable.CustomTurntableView_text);init();}private void init() {//以下注释请看CustomBingView⾥⾯mPaint = new Paint();mPaint.setColor(Color.RED);mPaint.setStrokeWidth(10);mPaint.setTextSize(20);mPaint.setStyle(Paint.Style.FILL);mRectF = new RectF();mRectF.top = 50;mRectF.bottom = 300;mRectF.right = 300;mRectF.left = 200;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);// setMeasuredDimension(300, 300);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//设置画笔颜⾊为⿊⾊,mPaint.setColor(Color.BLACK);//画出指针,⽤⼀个扇形,然后盖住后⾯补分来简单表⽰canvas.drawArc(mRectF, 60, 60, true, mPaint);mPaint.setColor(Color.RED);//画⼀个红⾊的圆形,就是中间的⼤按钮canvas.drawCircle(250, 250, 50, mPaint);mPaint.setColor(Color.BLACK);//添加按钮上的⽂字canvas.drawText(mStr, 230, 260, mPaint);//画三⾓,第⼀步,创建路径// Path path = new Path();//第⼆步,moveTo第⼀个顶点// path.moveTo(300, 300);//后续相继lineTo其他顶点// path.lineTo(300, 400);// path.lineTo(400, 400);//闭合// path.close();// 画// canvas.drawPath(path, mPaint);}}⾃定义属性attrs.xml<?xml version="1.0" encoding="utf-8"?><resources><!-- name为想要调⽤这个属性的类名即可 --><declare-styleable name="CustomTurntableView"><!-- name为属性的名字,可以随意起,只要符合规则看得懂 --><!-- format为属性内容的类型 --><attr name="text" format="string"></attr></declare-styleable></resources>以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持,关注公众号的更多精彩内容。
Android自定义View画圆功能

Android⾃定义View画圆功能本⽂实例为⼤家分享了Android⾃定义View画圆的具体代码,供⼤家参考,具体内容如下引⼊布局<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:id="@+id/activity_main"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="com.bwie.test.xuejian1508a20170928.MainActivity"><com.bwie.test.xuejian1508a20170928.ViViewandroid:layout_width="match_parent"android:layout_height="match_parent"/></RelativeLayout>⾃定义View的java类,继承Viewpublic class ViView extends View{Paint paint;Context context;//构造⽅法public ViView(Context context) {super(context);}public ViView(Context context, AttributeSet attrs) {super(context, attrs);}public ViView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}public ViView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {super(context, attrs, defStyleAttr, defStyleRes);this.context=context;}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);}@Overrideprotected void onLayout(boolean changed, int left, int top, int right, int bottom) {super.onLayout(changed, left, top, right, bottom);}/*绘图*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//得到屏幕宽⾼int width = getWidth();int radius = width - 450/2;int height = getHeight();// 创建画笔Paint paint1 = new Paint();Paint paint2 = new Paint();Paint paint3= new Paint();// 消除锯齿paint1.setAntiAlias(true);paint2.setAntiAlias(true);paint3.setAntiAlias(true);//画笔颜⾊paint1.setColor(Color.RED);paint2.setColor(Color.WHITE);paint3.setColor(Color.BLUE);// 画圆。
Android自定义Drawable实现圆角效果

Android⾃定义Drawable实现圆⾓效果Drawable是⼀种可绘制资源的载体,如图形、图像等。
在实际开发中可以作为view的背景。
主要有静态和动态两种⽅式,静态通过xml描述使⽤,动态即⾃定义Drawable。
本⽂实现⼀个圆形和圆⾓的背景图⽚效果。
效果图:实现⽅式:1.初始化⼀个BitmapShader着⾊器对象;2.将着⾊器对象set给画笔;3.在画布上绘制圆或圆⾓即可;4.使⽤,view.setBackgroundDrawable或者 ImageView.setImageDrawablepackage com.mydrawable.musk;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.ColorFilter;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.Shader;import android.graphics.drawable.Drawable;/*** Created by musk.*/public class CircleDrawable extends Drawable {private Paint mPaint;private int mWidth;private Bitmap mBitmap;public CircleDrawable(Bitmap bitmap) {mBitmap = bitmap;//着⾊器,设置横向和纵向的着⾊模式为平铺BitmapShader bitmapShader = new BitmapShader(mBitmap,Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setDither(true);mPaint.setShader(bitmapShader);mWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());}//绘制@Overridepublic void draw(Canvas canvas) {canvas.drawCircle(mWidth / 2, mWidth / 2, mWidth / 2, mPaint);}//设置透明度值@Overridepublic void setAlpha(int alpha) {mPaint.setAlpha(alpha);}//设置颜⾊过滤器@Overridepublic void setColorFilter(ColorFilter colorFilter) {mPaint.setColorFilter(colorFilter);}//返回不透明度@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}//返回图⽚实际的宽⾼@Overridepublic int getIntrinsicWidth() {return mWidth;}@Overridepublic int getIntrinsicHeight() {return mWidth;}}⾃定义Drawable有五个⽅法必须覆写,draw()、setAlpha()、setColorFilter()、getOpacity(),另外的getIntrinsicWidth()和getIntrinsicHeight()是在view设置wrap_content时设置drawable的宽度和⾼度。
Android中TextView显示圆圈背景或设置圆角的方法

Android中TextView显⽰圆圈背景或设置圆⾓的⽅法前⾔在我们学习android这么久,⽽且使⽤TextView那么长时间,我们⼀直没有⽤过给TextView添加背景,或者是给TextView添加添加边框,以及怎么样设置TextView的形状。
今天在写代码的时候就⽤到了,怎么在java代码部分设置TextView的背景,和TextView的形状及边框。
⽅法如下:接下来我们来看⼀下,怎么在Java代码部分怎么设置TextView的背景颜⾊,其实很简单的就⼀句话。
tvTemp.setBackgroundColor(Color.parseColor("#00FF00"));我们在xml布局⽂件中就可以直接调⽤drawable⽂件代码如下:android:background="@drawable/textview"在我们设置背景的时候,我们都知道使⽤setBackgroundColor()⽅法,但是,⽅法⾥⾯的参数,必须是RGB HTML格式的值,如果我们⽤drawable,它会提⽰drawable是int类型的。
(其实如果可以的话我们不妨使⽤ImageView组件,这个组件相对TextView更好⽤)。
我们接下来就来看看怎么给让TextView显⽰边框,并且怎么样让其显⽰圆形。
这⾥我们就需要在drawable⾥⾯,新建⼀个.xml⽂件。
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="/apk/res/android"android:shape="oval"android:useLevel="false"><solid android:color="#00FF00" /><stroke android:width="1dip" android:color="#000000" /><sizeandroid:width="15dp"android:height="15dp" /></shape>这只是⼀个圆形,其中, stroke属性,是设置的他的边框颜⾊和宽度,在xml布局中显⽰的是如图所⽰的样式:xml样式最后我们就可以在xml⽂件中利⽤drawable调⽤。
Android中自定义View的应用

</com.example.viewdemo.MyView>
</LinearLayout>
3.运行效果:
Android中自定义View的应用
1.建立自己的View.
packagecom.example.viewdemo;
importandroid.content.Context;
importandroid.graphics.Canvas;
importandroid.graphics.Color;
importandroid.graphics.Paint;
}
}
2.添加到布局文件中.
<LinearLayoutxmlns:android="/apk/res/android"
xmlns:tools="/tools"
android:layout_width="match_parent"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.viewdemo.MainActivity" >
super(context,attr);
}
protectedvoidonDraw(Canvas canvas) {
super.onDraw(canvas);
Android进阶——自定义View之自己绘制彩虹圆环调色板

Android进阶——自定义View之自己绘制彩虹圆环调色板引言前面几篇文章都是关于通过继承系统View和组合现有View来实现自定义View的,刚好由于项目需要实现一个滑动切换LED彩灯颜色的功能,所以需要一个类似调色板的功能,随着手在调色板有效区域滑动,LED彩灯随即显示相应的颜色,也可以通过左右的按钮,按顺序切换显示一组颜色,同时都随着亮度的改变LED彩灯的亮度随即变化,这篇基本上把继承View重绘实现自定义控件的大部分知识总结了下(当然还有蛮多没有涉及到,比如说自适应布局等),源码在Github上一、继承View绘制自定义控件的通用步骤自定义属性和继承View重写onDraw方法实现构造方法,其中public RainbowPalette(Context context, AttributeSet attrs) 必须实现,否则无法通过xml引用,public RainbowPalette(Context context) ,public RainbowPalette(Context context, AttributeSet attrs, int defStyleAttr)可选,通常在构造方法中完成属性和其他成员变量的初始化重写onMeasure方法,否则在xml中有些设置布局参数无效@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(width, height);//重新设置View的位置,若不重写的话,则不会布局,即使设置centerInParent为true也无效//setMeasuredDimension(width,height);}手动调用invalidate或者postInvalidateon方法完成界面刷新重写onTouchEvent方法实现基本的交互定义回调接口供外部调用二、彩虹圆环调色板设计思想1、UI构成首先从整个形状来看是个圆环,系统自有的控件明显没具有这个功能,只能是继承View重写OnDraw来完成绘制工作。
Android自定义View圆形图片控件代码详解

Android⾃定义View圆形图⽚控件代码详解前⾔在⽇常开发中,圆形的图⽚效果还是很常见的。
可以通过给Paint设置Xfermode来实现,这⾥简单记录如下。
实现实现圆形效果的核⼼是PorterDuffXfermode,对于PorterDuffXfermode,这⾥不展开,可以查询相关资料。
核⼼代码//绘制背景canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mPaint);//设置模式为:显⽰背景层和上层的交集,且显⽰上层图像mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//绘制要显⽰的图像canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);//重置XfermodemPaint.setXfermode(null);⾃定义属性<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="CircleView"><!--定义资源--><attr name="src" format="reference" /><!--定义类型--><attr name="type" format="enum"><!--圆形--><enum name="round" value="1" /><!--矩形--><enum name="rect" value="2" /></attr></declare-styleable></resources>⾃定义控件public class CircleView extends View {private static final int DEFAULT_SIZE = 200;private static final int DEFAULT_RADIUS = 20;private static final int TYPE_ROUND = 1;private static final int TYPE_RECT = 2;private int mSize;private int mResourceId;private int mType;private Paint mPaint;private Bitmap mSrcBitmap;public CircleView(Context context) {this(context, null);}public CircleView(Context context, AttributeSet attrs) {this(context, attrs, 0);}public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CircleView);mResourceId = ta.getResourceId(R.styleable.CircleView_src, R.mipmap.ic_launcher);mType = ta.getInt(R.styleable.CircleView_type, TYPE_ROUND);ta.recycle();init();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = getMeasureSize(widthMeasureSpec);int height = getMeasureSize(heightMeasureSpec);mSize = Math.min(width, height);setMeasuredDimension(mSize, mSize);}@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//绘制背景if (mSrcBitmap == null) {mSrcBitmap = getScaleBitmap();}if (mType == TYPE_ROUND) {canvas.drawCircle(mSize / 2, mSize / 2, mSize / 2, mPaint);} else if (mType == TYPE_RECT) {canvas.drawRoundRect(0, 0, mSize, mSize, DEFAULT_RADIUS, DEFAULT_RADIUS, mPaint); }//设置模式为:显⽰背景层和上层的交集,且显⽰上层图像mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));//绘制要显⽰的图像canvas.drawBitmap(mSrcBitmap, 0, 0, mPaint);//重置XfermodemPaint.setXfermode(null);}private void init() {//禁⽤硬件加速,否则可能⽆法绘制圆形setLayerType(LAYER_TYPE_HARDWARE, null);mPaint = new Paint();mPaint.setAntiAlias(true);mPaint.setStyle(Paint.Style.FILL);}private int getMeasureSize(int measureSpec) {int mode = MeasureSpec.getMode(measureSpec);int size = MeasureSpec.getSize(measureSpec);return mode == MeasureSpec.EXACTLY ? size : DEFAULT_SIZE;}/*** 获取缩放后的Bitmap** @return*/private Bitmap getScaleBitmap() {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeResource(getResources(), mResourceId, options);options.inSampleSize = calcSampleSize(options, mSize, mSize);options.inJustDecodeBounds = false;return BitmapFactory.decodeResource(getResources(), mResourceId, options);}/*** 计算缩放⽐例** @param option* @param width* @param height* @return*/private int calcSampleSize(BitmapFactory.Options option, int width, int height) {int originWidth = option.outWidth;int originHeight = option.outHeight;int sampleSize = 1;while ((originWidth = originWidth >> 1) > width && (originHeight = originHeight >> 1) > height) { sampleSize = sampleSize << 1;}return sampleSize;}}注意:如果没有圆形的效果,那么可能需要禁⽤硬件加速:setLayerType(LAYER_TYPE_HARDWARE, null)布局<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:app="/apk/res-auto"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_horizontal"android:orientation="vertical"tools:context=".MainActivity"><com.wangyz.custom.CircleViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="10dp"app:src="@drawable/image" /><com.wangyz.custom.CircleViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_margin="10dp"app:src="@drawable/image" /><com.wangyz.custom.CircleViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_margin="10dp"app:src="@drawable/image"app:type="rect" /></LinearLayout>效果以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
详解Android如何自定义view实现圆形进度条

详解Android如何⾃定义view实现圆形进度条Android中实现进度条有很多种⽅式,⾃定义进度条⼀般是继承progressBar或继承view来实现,本篇中讲解的是第⼆种⽅式。
先上效果图:实现圆形进度条总体来说并不难,还是跟往常⼀样继承view,初始化画笔,按下⾯的步骤⼀步步来就好了。
对初学者来说动画效果可能⽐较陌⽣,我们可以使⽤属性动画中的valueAnimator来实现动画效果。
实现步骤:1、画出⼀个灰⾊的圆环作为背景。
2、画出上层的圆环覆盖下⽅的圆环。
3、加⼊动画效果值得注意的是怎么设置圆环和⽂字的位置。
画出矩形只需要传⼊矩形对⾓线的坐标即可,如果不加以处理的话画出来的圆环的边缘是不完整的,刚开始接触⾃定义view 的同学们⼀定要先好好看看Android坐标系相关内容,不然很难理解位置参数为什么这样设置。
完整代码:package com.example.floatingwindow.widget;import android.animation.ValueAnimator;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.util.TypedValue;import android.view.View;import android.view.animation.DecelerateInterpolator;import androidx.annotation.Nullable;import com.example.floatingwindow.R;public class ProgressBarView extends View {private Paint mPaintBack;private Paint mPaint;private Paint mPaintText;private float process;private int strokeWidth = 15;private int textSize = 20;private long duration = 3000;private float startDegree = 0;private float endDegree = 360;private String text = "完成";private String defaultText = "0%";public ProgressBarView(Context context) {super(context);init();}public ProgressBarView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);init();}public ProgressBarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}private void init() {mPaintBack = new Paint();mPaintBack.setColor(getResources().getColor(R.color.gray));mPaintBack.setStyle(Paint.Style.STROKE);mPaintBack.setAntiAlias(true);mPaintBack.setStrokeCap(Paint.Cap.ROUND);mPaintBack.setStrokeWidth(strokeWidth);mPaint = new Paint();mPaint.setColor(getResources().getColor(R.color.purple_200));mPaint.setStyle(Paint.Style.STROKE);mPaint.setAntiAlias(true);mPaint.setStrokeCap(Paint.Cap.ROUND);mPaint.setStrokeWidth(strokeWidth);mPaintText = new Paint();mPaintText.setAntiAlias(true);mPaintText.setStyle(Paint.Style.STROKE);mPaintText.setColor(Color.BLACK);mPaintBack.setStrokeCap(Paint.Cap.ROUND);mPaintText.setTextSize(sp2px(textSize));}public void setStrokeWidth(int width) {strokeWidth = width;}public void setTextSize(int textSize) {this.textSize = textSize;}public void setDuration(long duration) {this.duration = duration;}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//创建圆环矩形RectF rectF = new RectF(strokeWidth, strokeWidth, getWidth() - strokeWidth, getHeight() - strokeWidth); //画出灰⾊进度条作为背景canvas.drawArc(rectF, 0, 360, false, mPaintBack);//画进度条canvas.drawArc(rectF, 0, process, false, mPaint);//计算进度int percent = (int) (process / 360 * 100);//设置⽂字在canvas中的位置Paint.FontMetrics fm = mPaintText.getFontMetrics();int mTxtWidth = (int) mPaintText.measureText(text, 0, defaultText.length());int mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);int x = getWidth() / 2 - mTxtWidth / 2;int y = getHeight() / 2 + mTxtHeight / 4;if (percent < 100) {canvas.drawText(percent + "%", x, y, mPaintText);} else {canvas.drawText(text, x, y, mPaintText);}}/*** 设置动画效果*/public void start() {ValueAnimator valueAnimator = ValueAnimator.ofFloat(startDegree, endDegree);valueAnimator.setDuration(duration);valueAnimator.setInterpolator(new DecelerateInterpolator());valueAnimator.addUpdateListener(animation -> {process = (float) animation.getAnimatedValue();invalidate();});valueAnimator.start();}private int sp2px(int sp) {return (int) TypedValue.applyDimension(PLEX_UNIT_SP, sp,getResources().getDisplayMetrics());}}最后就是动画效果了,使⽤valueanimator,传⼊开始和结束的进度以及执⾏时间。
Android绘图机制(二)——自定义View绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解

Android绘图机制(二)——自定义View 绘制形, 圆形, 三角形, 扇形, 椭圆, 曲线,文字和图片的坐标讲解我们要想画好一些炫酷的View,首先我们得知道怎么去画一些基础的图案,比如矩形,圆形,三角形,多边形等….新建一个项目然后我们创建一个listview,每个图案一个Activity,这样看起来是不是很顺眼<ListViewandroid:id="@+id/listview"android:layout_width="wrap_content"android:layout_height="wrap_content" />编写ListViewprivate ListView listview;//item上的数据源private String[] name = {"矩形", "圆形", "三角形", "扇形", "椭圆", "曲线","文字和图片"};//listview的adapterprivate ArrayAdapter<String>adapter;private void initView() {//实例化listviewlistview = (ListView) findViewById(R.id.listview);//实例化数据源adapter = new ArrayAdapter<String>(this, yout.simple_list_item_1, name);//listview设置adapterlistview.setAdapter(adapter);//listview设置点击事件listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position, long id) {//判断点击了第几个if (id == 0) {//矩形startActivity(new Intent(MainActivity.this, RectActivity.class));} else if (id == 1) {//圆形startActivity(new Intent(MainActivity.this, CircleActivity.class));} else if (id == 2) {//三角形startActivity(new Intent(MainActivity.this, TrigonActivity.class));} else if (id == 3) {//扇形startActivity(new Intent(MainActivity.this, SectorActivity.class));} else if (id == 4) {//椭圆startActivity(new Intent(MainActivity.this, OvalActivity.class));} else if (id == 5) {//曲线startActivity(new Intent(MainActivity.this, PathActivity.class));}else if (id == 6) {//曲线startActivity(new Intent(MainActivity.this, TvIvActivity.class));}}});}效果是这样的后续可以添加1.矩形——RectActivity好的,上面写ListView的代码是不是很简单?拿我们新建一个RectActivity去画点了,首先我们要新建一个RectView继承Viewpackage com.lgl.view.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;/*** 矩形* Created by LGL on 2016/1/7.*/public class RectView extends View {//无参public RectView(Context context) {super(context);}//有参public RectView(Context context, AttributeSet attrs) { super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 创建画笔Paint p = new Paint();//设置实心p.setStyle(Paint.Style.FILL);// 设置红色p.setColor(Color.BLACK);// 设置画笔的锯齿效果p.setAntiAlias(true);//绘制canvas.drawRect(50, 100, 300, 300, p);}}截图1.圆形——CircleActivity我们还是新建一个CircleActivity去画点了,首先我们要新建一个CircleView继承View package com.lgl.view.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet;import android.view.View;import android.view.WindowManager;/*** 圆* Created by LGL on 2016/1/7.*/public class CircleView extends View {int width;int height;//无参public CircleView(Context context) {super(context);init();}//有参public CircleView(Context context, AttributeSet attrs) {super(context, attrs);init();}private void init() {//获取屏幕的宽高//Android绘图机制(一)——自定义View的基础属性和方法里面有讲WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);width = wm.getDefaultDisplay().getWidth();height = wm.getDefaultDisplay().getHeight();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint p = new Paint();p.setColor(Color.BLACK);// 设置画笔的锯齿效果p.setAntiAlias(true);canvas.drawCircle(width / 2, height / 2, width / 2, p);}}截图3.三角形——TrigonActivity我们还是新建一个TrigonActivity去画点了,首先我们要新建一个trigonView继承View package com.lgl.view.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet;import android.view.View;/*** 三角形* Created by LGL on 2016/1/7.*/public class TrigonView extends View {//无参public TrigonView(Context context) {super(context);}//有参public TrigonView(Context context, AttributeSet attrs) { super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint p = new Paint();p.setColor(Color.BLACK);//实例化路径Path path = new Path();path.moveTo(80, 200);// 此点为多边形的起点path.lineTo(120, 250);path.lineTo(80, 250);path.close(); // 使这些点构成封闭的多边形canvas.drawPath(path, p);}}4.扇形——SectorActivitypackage com.lgl.view.view;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color;import android.graphics.Paint;import android.graphics.RectF;import android.util.AttributeSet;import android.view.View;/*** 扇形* Created by LGL on 2016/1/8.*/public class SectorView extends View {public SectorView(Context context) {super(text);}public SectorView(Context context, AttributeSet attrs) { super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 创建画笔Paint p = new Paint();p.setColor(Color.BLACK);RectF rectF = new RectF(60, 100, 200, 240);canvas.drawArc(rectF, 200, 130, true, p);}}5.椭圆——OvalActivitypackage com.lgl.view.view;import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.RectF; import android.util.AttributeSet; import android.view.View;/*** 椭圆* Created by LGL on 2016/1/8.*/public class OvalView extends View {public OvalView(Context context) {super(context);}public OvalView(Context context, AttributeSet attrs) { super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 创建画笔Paint p = new Paint();p.setColor(Color.BLACK);RectF rectF = new RectF(60, 100, 200, 240);rectF.set(210,100,250,130);canvas.drawOval(rectF, p);}}椭圆的思路和扇形是一样的,这里就不演示了截图6.曲线——PathActivitypackage com.lgl.view.view;import android.content.Context;import android.graphics.Canvas; import android.graphics.Color;import android.graphics.Paint;import android.graphics.Path;import android.util.AttributeSet; import android.view.View;/*** Created by LGL on 2016/1/8.*/public class PathView extends View {public PathView(Context context) {super(context);}public PathView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);// 创建画笔Paint p = new Paint();p.setColor(Color.BLACK);p.reset();//设置空心p.setStyle(Paint.Style.STROKE);Path path = new Path();path.moveTo(100, 320);//设置Path的起点path.quadTo(150, 310, 170, 400); //设置路径点和终点canvas.drawPath(path, p);}}截图7.文字和图片——TvIvActivitypackage com.lgl.view.view;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color;import android.graphics.Paint;import android.util.AttributeSet; import android.view.View;import com.lgl.view.R;/*** Created by LGL on 2016/1/8.*/public class TvIvView extends View {public TvIvView(Context context) {super(context);}public TvIvView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint p = new Paint();p.setColor(Color.RED);//文本canvas.drawText("自定义文本", 250, 330, p);Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);//图片canvas.drawBitmap(bitmap, 250, 360, p);}}文字和图片感觉不用多说,图片加载需要一个bitmap,而加载bitmap又需要一个工厂类,就是这样大致的坐标思维截图相信看到这里,一些基础的图案都是可以绘制了。
Android自定义View实现圆形进度条

Android⾃定义View实现圆形进度条本⽂实例为⼤家分享了Android⾃定义View实现圆形进度条的具体代码,供⼤家参考,具体内容如下效果如下:主要代码CircularProgressView.javapublic class CircularProgressView extends View {private Paint mBackPaint, mProgPaint; // 绘制画笔private RectF mRectF; // 绘制区域private int[] mColorArray; // 圆环渐变⾊private int mProgress; // 圆环进度(0-100)/*** 绘制弧线的画笔*/private Paint progressPaint;/*** 圆弧圆⼼位置*/private int centerX, centerY;/*** 圆弧的半径*/private int circleRadius;public CircularProgressView(Context context) {this(context, null);}public CircularProgressView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);}public CircularProgressView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);@SuppressLint("Recycle")TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CircularProgressView);// 初始化背景圆环画笔mBackPaint = new Paint();mBackPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充mBackPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆⾓mBackPaint.setAntiAlias(true); // 设置抗锯齿mBackPaint.setDither(true); // 设置抖动mBackPaint.setStrokeWidth(typedArray.getDimension(R.styleable.CircularProgressView_backWidth, 5));mBackPaint.setColor(typedArray.getColor(R.styleable.CircularProgressView_progbgColor, Color.LTGRAY));// 初始化进度圆环画笔mProgPaint = new Paint();mProgPaint.setStyle(Paint.Style.STROKE); // 只描边,不填充mProgPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆⾓mProgPaint.setAntiAlias(true); // 设置抗锯齿mProgPaint.setDither(true); // 设置抖动mProgPaint.setStrokeWidth(typedArray.getDimension(R.styleable.CircularProgressView_progWidth, 10));mProgPaint.setColor(typedArray.getColor(R.styleable.CircularProgressView_progColor, Color.BLUE));//初始化结束位置⼩圆点progressPaint = new Paint();progressPaint.setStyle(Paint.Style.FILL); // 填充progressPaint.setStrokeCap(Paint.Cap.ROUND); // 设置圆⾓progressPaint.setAntiAlias(true); // 设置抗锯齿progressPaint.setDither(true); // 设置抖动progressPaint.setStrokeWidth(typedArray.getDimension(R.styleable.CircularProgressView_progWidth, 10));progressPaint.setColor(Color.WHITE);// 初始化进度圆环渐变⾊int startColor = typedArray.getColor(R.styleable.CircularProgressView_progStartColor, -1);int firstColor = typedArray.getColor(R.styleable.CircularProgressView_progFirstColor, -1);if (startColor != -1 && firstColor != -1) mColorArray = new int[]{startColor, firstColor};else mColorArray = null;// 初始化进度mProgress = typedArray.getInteger(R.styleable.CircularProgressView_progress, 0);typedArray.recycle();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int viewWide = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();int viewHigh = getMeasuredHeight() - getPaddingTop() - getPaddingBottom();int mRectLength = (int) ((viewWide > viewHigh ? viewHigh : viewWide) - (mBackPaint.getStrokeWidth() > mProgPaint.getStrokeWidth() ? mBackPaint.getStrokeWidth() : mProgPaint.getStrokeWidth())); int mRectL = getPaddingLeft() + (viewWide - mRectLength) / 2;int mRectT = getPaddingTop() + (viewHigh - mRectLength) / 2;mRectF = new RectF(mRectL, mRectT, mRectL + mRectLength, mRectT + mRectLength);centerX = getMeasuredWidth() / 2;centerY = getMeasuredHeight() / 2;//计算圆弧半径和圆⼼点circleRadius = Math.min(getMeasuredWidth(), getMeasuredHeight()) / 2;circleRadius-=8;// 设置进度圆环渐变⾊if (mColorArray != null && mColorArray.length > 1)mProgPaint.setShader(new LinearGradient(0, 0, 0, getMeasuredWidth(), mColorArray, null, Shader.TileMode.MIRROR));}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawArc(mRectF, 0, 360, false, mBackPaint);canvas.drawArc(mRectF, 270, 360 * mProgress / 100, false, mProgPaint);//绘制结束位置⼩圆形progressPaint.setStrokeWidth(10);progressPaint.setStyle(Paint.Style.FILL);float swipe = 360 * mProgress / 100;Log.d("=================", swipe + " mProgress");float radians = (float) (((swipe - 90) / 2) / 180 * 2 * Math.PI);float endX;float endY;endX = centerX + circleRadius * (float) Math.cos(radians);endY = centerY + circleRadius * (float) Math.sin(radians);if (mProgress!=0) {canvas.drawCircle(endX, endY, 8, progressPaint);}}/*** 获取当前进度** @return 当前进度(0-100)*/public int getProgress() {return mProgress;}/*** 设置当前进度** @param progress 当前进度(0-100)*/public void setProgress(int progress) {this.mProgress = progress;invalidate();}/*** 设置当前进度,并展⽰进度动画。
自定义view的绘制流程

自定义view的绘制流程自定义View的绘制流程。
在Android开发中,自定义View是非常常见的需求,通过自定义View可以实现各种炫酷的效果,满足各种个性化的设计需求。
但是,自定义View的绘制流程并不是那么简单,需要我们对View的绘制机制有一定的了解,才能够高效地实现自定义View的绘制。
本文将从自定义View的基本概念开始,逐步介绍自定义View的绘制流程。
1. 自定义View的基本概念。
自定义View是指在Android开发中,通过继承View或者ViewGroup来创建自定义的UI控件。
通过自定义View,我们可以实现各种各样的UI效果,比如自定义的按钮样式、进度条样式、图表样式等。
自定义View的核心就是重写View或者ViewGroup的绘制方法,以实现我们所需的UI效果。
2. 自定义View的绘制流程。
自定义View的绘制流程可以分为以下几个步骤:(1)onMeasure,测量View的大小。
在onMeasure方法中,我们需要通过调用setMeasuredDimension方法来设置View的大小。
在这个方法中,我们需要考虑View的宽度和高度,以及View的测量模式。
通常情况下,我们需要根据View的内容和父容器的大小来计算View的大小,并根据测量模式来确定View的最终大小。
(2)onLayout,确定View的位置。
在onLayout方法中,我们需要通过调用layout方法来确定View在父容器中的位置。
在这个方法中,我们需要考虑View的左上右下四个位置,以及父容器的大小和布局方式,来确定View的最终位置。
(3)onDraw,绘制View的内容。
在onDraw方法中,我们需要通过Canvas来绘制View的内容。
在这个方法中,我们可以使用各种绘制方法来绘制文字、图形、图片等内容,以实现我们所需的UI效果。
在绘制过程中,我们还可以通过Paint来设置绘制的样式、颜色、字体等属性,以实现更加丰富的UI效果。
自定义控件:绘制圆环的实现过程

⾃定义控件:绘制圆环的实现过程使⽤⾃定义控件绘制⼀个圆环,需要重现的⽅法是OnDraw()实现对view 的绘制,从⽽输出符合⾃⼰需求的view 控件观察圆环的组成部分:外层圆+中间百分⽐⽂字+不断变化进度的弧形圈--->分析:每⼀个组成部分需要的属性,构成⼏个关键的⾃定义属性1:外层圆的颜⾊2:弧形进度圈的颜⾊3:中间百分⽐⽂字的颜⾊4:中间百分⽐⽂字的⼤⼩5:圆环的宽度(作为进度弧形圈的宽度)6:*⾸页当中也有⼀个圆环进度,为了兼容使⽤⾸页的圆环进度,增加⼀个⾃定义属性,绘制进度弧形圈的风格(实⼼[Fill],空⼼[Stroken])分析完毕-->绘制步骤:1:构造⽅法当中初始化画笔对象,获取⾃定义的属性值.2:重写Ondraw ⽅法---2.1:绘制最外层的圆-关键⽅法canvas.drawCircle(center, center, radius, paint); //画出圆环*:计算半径、中⼼点坐标、画笔设置paint.setColor(roundColor); //设置圆环的颜⾊paint.setStyle(Paint.Style.STROKE); //设置空⼼paint.setStrokeWidth(roundWidth); //设置圆环的宽度---这个宽度也是提供给进度弧形圈绘制的时候覆盖的宽度paint.setAntiAlias(true); //消除锯齿中⼼点坐标int center = getWidth() / 2; //获取圆⼼的x 坐标半径int radius = (int) (center - roundWidth/2) ---画图说明最容易理解---2.2:绘制中间的百分⽐⽂字--关键⽅法:canvas.drawText(percent + "%", center - textWidth / 2,center + textSize / 2, paint); //画出进度百分⽐测量画笔上的⽂本宽度float textWidth = paint.measureText(percent + "%");画笔设置paint.setStrokeWidth(0);paint.setColor(textColor);paint.setTextSize(textSize);paint.setTypeface(Typeface.DEFAULT_BOLD); //设置字体绘制的⽂字的位置,由参数2,3 的X,Y 坐标值决定--圆环的中⼼点位置显⽰X:表⽰从哪开始绘制,如果你直接中⼼点开始绘制-->画图说明最容易理解-->正确的X=center - textWidth / 2;Y = center + textSize / 2 --(因为android 坐标系与数学坐标系Y 轴值是相反的,也可以画图说明,这⾥的textsize 就可以代表⾼度,paint.measureText 测量⽅法执⾏之后,默认的⽂字⾼度就是根据⽂字⼤⼩计算的,相当于wrap_content,所以textSize 就是本⾝⽂字所占的⾼度值)*:绘制的进度要转换为百分⽐形式:int percent = (int) (((float) progress /(float) max) * 100);---2.3:绘制进度弧形圈---关键⽅法:canvas.drawArc(oval, 0, 360 * progress / max, false, paint);//根据进度画圆弧参数解释:oval:绘制的弧形的范围轮廓0:从多少⾓度开始绘制360 * progress / max:绘制弧形扫过的⾓度对应的区域false:不包含圆⼼,如果是true,表⽰包含圆⼼paint:绘制使⽤的画笔画笔设置paint.setStrokeWidth(roundWidth); //设置进度弧形圈的宽度,必须保持和外层圆的StrokeWidth ⼀致,确保弧形圈绘制的时候覆盖的范围就是外层圆的宽度paint.setColor(roundProgressColor); //设置进度的颜⾊弧形范围计算RectF oval = new RectF(center - radius, center - radius, center+ radius, center + radius); --->画图说明最容易理解left:center - radiustop:center-radiusright:center+radius传智播客武汉校区就业部出品务实、创新、质量、分享、专注、责任bottom:center+radius*:注意,因为progress 是相对于100 当中占⽐多少,⽽弧形总共是按照⾓度分成360 分的,所以绘制弧形圈指定参数扫过的区域⾓度需要计算转换⼀下=360 * progress / max(max=100)*:对应⾃定义属性中的最后⼀个属性是实⼼还是空⼼,绘制的时候需要判断⼀下,兼容⾸页的圆环进度处理switch (style) {case STROKE:{paint.setStyle(Paint.Style.STROKE);canvas.drawArc(oval, 0, 360 *progress / max, false, paint); //根据进度画圆弧break;}case FILL:{paint.setStyle(Paint.Style.FILL_AND_STROKE);if(progress !=0)canvas.drawArc(oval, 0, 360 *progress / max, true, paint); //根据进度画圆弧break;}}最后提供⼀个设置进度,根据进度重新绘制圆环的⽅法public void setProgress(int progress) {if(progress < 0){throw newIllegalArgumentException("progress not less than0");}if(progress > max){progress = max;}if(progress <= max){this.progress = progress;postInvalidate();}}。
Android使用自定义ImageView实现圆形图片效果

Android使⽤⾃定义ImageView实现圆形图⽚效果android中的ImageView只能显⽰矩形的图⽚,这样⼀来不能满⾜我们其他的需求,⽐如要显⽰圆形的图⽚,这个时候,我们就需要⾃定义ImageView了,其原理就是⾸先获取到图⽚的Bitmap,然后进⾏裁剪圆形的bitmap,然后在onDraw()进⾏绘制圆形图⽚输出。
效果图如下:⾃定义的圆形的ImageView类的实现代码如下:package com.xc.xcskin.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Bitmap.Config;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PorterDuff.Mode;import android.graphics.PorterDuffXfermode;import android.graphics.Rect;import android.graphics.drawable.BitmapDrawable;import android.graphics.drawable.Drawable;import android.util.AttributeSet;import android.widget.ImageView;/*** ⾃定义的圆形ImageView,可以直接当组件在布局中使⽤。
* @author caizhiming**/public class XCRoundImageView extends ImageView{private Paint paint ;public XCRoundImageView(Context context) {this(context,null);}public XCRoundImageView(Context context, AttributeSet attrs) {this(context, attrs,0);}public XCRoundImageView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);paint = new Paint();}/*** 绘制圆形图⽚* @author caizhiming*/@Overrideprotected void onDraw(Canvas canvas) {Drawable drawable = getDrawable();if (null != drawable) {Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();Bitmap b = getCircleBitmap(bitmap, 14);final Rect rectSrc = new Rect(0, 0, b.getWidth(), b.getHeight());final Rect rectDest = new Rect(0,0,getWidth(),getHeight());paint.reset();canvas.drawBitmap(b, rectSrc, rectDest, paint);} else {super.onDraw(canvas);}}/*** 获取圆形图⽚⽅法* @param bitmap* @param pixels* @return Bitmap* @author caizhiming*/private Bitmap getCircleBitmap(Bitmap bitmap, int pixels) {Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),bitmap.getHeight(), Config.ARGB_8888);Canvas canvas = new Canvas(output);final int color = 0xff424242;final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());paint.setAntiAlias(true);canvas.drawARGB(0, 0, 0, 0);paint.setColor(color);int x = bitmap.getWidth();canvas.drawCircle(x / 2, x / 2, x / 2, paint);paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));canvas.drawBitmap(bitmap, rect, rect, paint);return output;}}完成这个⾃定义类后,就可以使⽤这个类了,就是把这个当组件在布局中使⽤即可,⽐如:<RelativeLayout xmlns:android="/apk/res/android"xmlns:tools="/tools"android:layout_width="match_parent"android:layout_height="match_parent" ><com.xc.xcskin.view.XCRoundImageViewandroid:id="@+id/roundImageView"android:layout_centerInParent="true"android:layout_width="200dp"android:layout_height="200dp"android:src="@drawable/roundimageview"/></RelativeLayout>以上就是这篇⽂章的全部内容了,希望本⽂的内容对⼤家的学习或者⼯作具有⼀定的参考学习价值,如果有疑问⼤家可以留⾔交流,谢谢⼤家对的⽀持。
Android开发使用Drawable绘制圆角与圆形图案功能示例

Android开发使⽤Drawable绘制圆⾓与圆形图案功能⽰例本⽂实例讲述了Android开发使⽤Drawable绘制圆⾓与圆形图案功能。
分享给⼤家供⼤家参考,具体如下:1. 创建类RoundCircleDrawable继承Drawable/*** 圆⾓矩形* @Project App_View* @Package com.android.view.drawable* @author chenlin* @version 1.0* @Date 2016年4⽉21⽇* @Note TODO*/public class RoundCircleDrawable extends Drawable{private Paint mPaint;//画笔private int mWidth;//图⽚宽与长度的最⼩值private int mRadius;//半径private int mRound;//圆⾓private RectF mRectF;//矩形private Bitmap mBitmap;//图⽚private Type mType = Type.TYPE_ROUND;//默认是矩形//设置类型enum Type{TYPE_ROUND, TYPE_CICLE;}public RoundCircleDrawable(Bitmap bitmap){this.mBitmap = bitmap;//初始化画笔mPaint = new Paint();mPaint.setAntiAlias(true);BitmapShader shader = new BitmapShader(mBitmap, TileMode.CLAMP, TileMode.CLAMP);mPaint.setShader(shader);mWidth = Math.min(mBitmap.getWidth(), mBitmap.getHeight());mRadius = mWidth / 2;}/*** 向外提供设置图⽚类型的⽅法* @param type*/public void setType(Type type){this.mType = type;}/*** 暴露给外⾯设置圆⾓的⼤⼩** @param round*/public void setRound(int round) {this.mRound = round;}@Overridepublic void setBounds(int left, int top, int right, int bottom) {super.setBounds(left, top, right, bottom);mRectF = new RectF(left, top, right, bottom);}@Overridepublic void draw(Canvas canvas) {if (mType == Type.TYPE_ROUND) {canvas.drawRoundRect(mRectF, mRound, mRound, mPaint);}else {canvas.drawCircle(mWidth / 2, mWidth / 2, mRadius, mPaint);}}@Overridepublic int getIntrinsicWidth() {if (mType == Type.TYPE_CICLE) {return mWidth;}else {return mBitmap.getWidth();}}@Overridepublic int getIntrinsicHeight() {if (mType == Type.TYPE_CICLE) {return mWidth;}else {return mBitmap.getHeight();}}@Overridepublic void setAlpha(int alpha) {mPaint.setAlpha(alpha);}@Overridepublic void setColorFilter(ColorFilter cf) {mPaint.setColorFilter(cf);}@Overridepublic int getOpacity() {return PixelFormat.TRANSLUCENT;}}2. 实现⽅法public class RoundActivity extends Activity {private ImageView mImageView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_round_drawable);mImageView = (ImageView) findViewById(R.id.iv_round);Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.aa);//RoundImageDrawable drawable = new RoundImageDrawable(bitmap);//drawable.setRound(30);RoundCircleDrawable drawable = new RoundCircleDrawable(bitmap);drawable.setRound(50);mImageView.setImageDrawable(drawable);}}更多关于Android相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》及《》希望本⽂所述对⼤家Android程序设计有所帮助。
Android自定义ImageView实现圆角功能

Android⾃定义ImageView实现圆⾓功能使⽤⾃定义ImageView,实现圆⾓功能,供⼤家参考,具体内容如下1.⾃定义属性attrs.xml<?xml version="1.0" encoding="utf-8"?><resources><declare-styleable name="RoundCornerImageView"><attr name="radius" format="dimension" /><attr name="left_top_radius" format="dimension" /><attr name="right_top_radius" format="dimension" /><attr name="right_bottom_radius" format="dimension" /><attr name="left_bottom_radius" format="dimension" /></declare-styleable></resources>2.⾃定义RoundCornerImageView,继承AppCompatImageViewpublic class RoundCornerImageView extends AppCompatImageView {private float width, height;private int defaultRadius = 0;private int radius;private int leftTopRadius;private int rightTopRadius;private int rightBottomRadius;private int leftBottomRadius;public RoundCornerImageView(Context context) {this(context, null);init(context, null);}public RoundCornerImageView(Context context, AttributeSet attrs) {this(context, attrs, 0);init(context, attrs);}public RoundCornerImageView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init(context, attrs);}private void init(Context context, AttributeSet attrs) {if (Build.VERSION.SDK_INT < 18) {setLayerType(YER_TYPE_SOFTWARE, null);}// 读取配置TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundCornerImageView);radius = array.getDimensionPixelOffset(R.styleable.RoundCornerImageView_radius, defaultRadius);leftTopRadius = array.getDimensionPixelOffset(R.styleable.RoundCornerImageView_left_top_radius, defaultRadius);rightTopRadius = array.getDimensionPixelOffset(R.styleable.RoundCornerImageView_right_top_radius, defaultRadius);rightBottomRadius = array.getDimensionPixelOffset(R.styleable.RoundCornerImageView_right_bottom_radius, defaultRadius); leftBottomRadius = array.getDimensionPixelOffset(R.styleable.RoundCornerImageView_left_bottom_radius, defaultRadius); //如果四个⾓的值没有设置,那么就使⽤通⽤的radius的值。
Android自定义view绘制圆环占比动画

Android⾃定义view绘制圆环占⽐动画本⽂实例为⼤家分享了Android⾃定义view绘制圆环占⽐动画的具体代码,供⼤家参考,具体内容如下⼀、实现效果图⼆、核⼼代码1.⾃定义MyProgressView.javapackage com.czhappy.effectdemo.view;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Paint.FontMetrics;import android.graphics.Rect;import android.graphics.RectF;import android.os.Handler;import android.os.Message;import android.text.TextUtils;import android.util.AttributeSet;import android.view.View;import com.czhappy.effectdemo.R;import com.czhappy.effectdemo.utils.ScreenUtil;public class MyProgressView extends View {// 画实⼼圆的画笔private Paint mCirclePaint;// 画圆环的画笔private Paint mRingDefaultPaint;// 已⽤环的画笔private Paint mUsePaint;// 画圆环的画笔private Paint mRingPaint;// 画⽩线的画笔private Paint mLinePaint;// 画字体的画笔private Paint mTextPaint;// 圆形颜⾊private int mCircleColor;// 圆环颜⾊private int mRingColor;// 半径private float mRadius;// 圆环半径private float mRingRadius;// 圆环宽度private float mStrokeWidth;// 圆⼼x坐标private int mXCenter;// 圆⼼y坐标private int mYCenter;// 字的长度private float mTxtWidth;// 字的⾼度private float mTxtHeight;// 总进度private int mTotalProgress = 100;// 当前进度private int mProgress;// 实际展⽰总进度private int mShowProgress;// 已⽤流量private String usedFlow;private Context mContext;private Handler circleHandler = new Handler(){public void handleMessage(Message msg) {super.handleMessage(msg);if(msg.what == 1){int temp = (Integer)msg.obj;setProgress(temp);}};};public MyProgressView(Context context, AttributeSet attrs) {super(context, attrs);mContext = context;// 获取⾃定义的属性initAttrs(context, attrs);initVariable();}private void initAttrs(Context context, AttributeSet attrs) {TypedArray typeArray = context.getTheme().obtainStyledAttributes(attrs,R.styleable.TasksCompletedView, 0, 0);mRadius = typeArray.getDimension(R.styleable.TasksCompletedView_radius, 80);mStrokeWidth = typeArray.getDimension(R.styleable.TasksCompletedView_strokeWidth, 10); mCircleColor = typeArray.getColor(R.styleable.TasksCompletedView_circleColor, 0xFFFFFFFF); mRingColor = typeArray.getColor(R.styleable.TasksCompletedView_ringColor, 0xFFFFFFFF); mRingRadius = mRadius + mStrokeWidth / 2;}private void initVariable() {//画圆画笔设置mCirclePaint = new Paint();mCirclePaint.setAntiAlias(true);//防锯齿mCirclePaint.setColor(mCircleColor);mCirclePaint.setStyle(Paint.Style.FILL);//“使⽤”字画笔设置mUsePaint = new Paint();mUsePaint.setAntiAlias(true);mUsePaint.setStyle(Paint.Style.FILL);mUsePaint.setColor(getResources().getColor(R.color.ticket_color));mUsePaint.setTextSize(ScreenUtil.sp2px(mContext, 10));//圆环画笔设置mRingDefaultPaint = new Paint();mRingDefaultPaint.setAntiAlias(true);mRingDefaultPaint.setColor(getResources().getColor(R.color.default_ring_color));mRingDefaultPaint.setStyle(Paint.Style.STROKE);mRingDefaultPaint.setStrokeWidth(mStrokeWidth);//已使⽤多少圆环画笔设置mRingPaint = new Paint();mRingPaint.setAntiAlias(true);mRingPaint.setColor(mRingColor);mRingPaint.setStyle(Paint.Style.STROKE);mRingPaint.setStrokeWidth(mStrokeWidth);mTextPaint = new Paint();mTextPaint.setAntiAlias(true);mTextPaint.setStyle(Paint.Style.FILL);mTextPaint.setColor(Color.BLACK);mTextPaint.setTextSize(ScreenUtil.sp2px(mContext, 22));mLinePaint = new Paint();mLinePaint.setColor(Color.WHITE);//获取字体⾼度FontMetrics fm = mTextPaint.getFontMetrics();mTxtHeight = (int) Math.ceil(fm.descent - fm.ascent);}@Overrideprotected void onDraw(Canvas canvas) {mXCenter = getWidth() / 2;mYCenter = getHeight() / 2;//画圆canvas.drawCircle(mXCenter, mYCenter, mRadius, mCirclePaint);RectF oval = new RectF();oval.left = (mXCenter - mRingRadius);oval.top = (mYCenter - mRingRadius);oval.right = mRingRadius * 2 + (mXCenter - mRingRadius);oval.bottom = mRingRadius * 2 + (mYCenter - mRingRadius);//画整圆弧canvas.drawArc(oval, -90, 360, false, mRingDefaultPaint);//已使⽤多少圆弧canvas.drawArc(oval, -90, ((float) mProgress / mTotalProgress) * 360, false, mRingPaint);//⽂字绘制String txt = mProgress + "%";//⽂字的长度mTxtWidth = mTextPaint.measureText(txt, 0, txt.length());canvas.drawText(txt, mXCenter - mTxtWidth / 2, mYCenter + mTxtHeight / 9, mTextPaint);Rect _pb = new Rect();String sup = "已⽤";mUsePaint.getTextBounds(sup, 0, sup.length(), _pb);int perX = mXCenter - _pb.width() / 2;canvas.drawText(sup, perX, mYCenter / 2, mUsePaint);if (!TextUtils.isEmpty(usedFlow)) {mUsePaint.getTextBounds(usedFlow, 0, usedFlow.length(), _pb);perX = mXCenter - _pb.width() / 2;canvas.drawText(usedFlow, perX, (float) (mYCenter + mYCenter / 1.7), mUsePaint);}//画横线图⽚Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.circle_bottom_bg); perX = mXCenter - bitmap.getWidth() / 2;canvas.drawBitmap(bitmap, perX, (float) (mYCenter + mYCenter / 5), mLinePaint);}/*** 设置当前进度* @param progress*/public void setProgress(int progress) {mProgress = progress;postInvalidate();}/*** 实际展⽰总进度* @param progress*/public void setmShowProgress(int progress) {mShowProgress = progress;new Thread(new CircleThread()).start();}public void setUsedFlow(String usedFlow) {edFlow = usedFlow;}private class CircleThread implements Runnable{int m=0;int i=0;@Overridepublic void run() {// TODO Auto-generated method stubwhile(!Thread.currentThread().isInterrupted()){try {Thread.sleep(50);m++;Message msg = new Message();msg.what = 1;if(i < mShowProgress){i += m;}else{i = mShowProgress;return;}msg.obj = i;circleHandler.sendMessage(msg);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}}2.FlowActivity.javapackage com.czhappy.effectdemo.activity;import android.os.Bundle;import android.support.annotation.Nullable;import android.support.v7.app.AppCompatActivity;import android.view.View;import com.czhappy.effectdemo.R;import com.czhappy.effectdemo.view.MyProgressView;/*** Description:* User: chenzheng* Date: 2017/1/21 0021* Time: 17:17*/public class FlowActivity extends AppCompatActivity {private MyProgressView mTasksView;@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);setContentView(yout.activity_flow);initView();}private void initView() {mTasksView = (MyProgressView) findViewById(R.id.flow_prgress_view);}public void beginAnim(View view){mTasksView.setUsedFlow("200.0M");mTasksView.setmShowProgress(60);}}3.activity_flow.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="/apk/res/android"xmlns:tc="/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="10dp"android:background="#fff"android:gravity="center_horizontal"android:orientation="vertical"><Buttonandroid:layout_width="match_parent"android:layout_height="wrap_content"android:onClick="beginAnim"android:text="开始动画"/><com.czhappy.effectdemo.view.MyProgressViewandroid:id="@+id/flow_prgress_view"android:layout_width="100dp"android:layout_height="100dp"tc:circleColor="@color/circle_color"tc:radius="44dp"tc:ringColor="@color/ring_color"tc:strokeWidth="6dp"android:layout_marginTop="10dp"/></LinearLayout>以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
Android进阶——自定义View之自己绘制彩虹圆环调色板引言前面几篇文章都是关于通过继承系统View和组合现有View来实现自定义View的,刚好由于项目需要实现一个滑动切换LED彩灯颜色的功能,所以需要一个类似调色板的功能,随着手在调色板有效区域滑动,LED彩灯随即显示相应的颜色,也可以通过左右的按钮,按顺序切换显示一组颜色,同时都随着亮度的改变LED彩灯的亮度随即变化,这篇基本上把继承View重绘实现自定义控件的大部分知识总结了下(当然还有蛮多没有涉及到,比如说自适应布局等),源码在Github上一、继承View绘制自定义控件的通用步骤自定义属性和继承View重写onDraw方法实现构造方法,其中public RainbowPalette(Context context, AttributeSet attrs) 必须实现,否则无法通过xml引用,public RainbowPalette(Context context) ,public RainbowPalette(Context context, AttributeSet attrs, int defStyleAttr)可选,通常在构造方法中完成属性和其他成员变量的初始化重写onMeasure方法,否则在xml中有些设置布局参数无效@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(width, height);//重新设置View的位置,若不重写的话,则不会布局,即使设置centerInParent为true也无效//setMeasuredDimension(width,height);}手动调用invalidate或者postInvalidateon方法完成界面刷新重写onTouchEvent方法实现基本的交互定义回调接口供外部调用二、彩虹圆环调色板设计思想1、UI构成首先从整个形状来看是个圆环,系统自有的控件明显没具有这个功能,只能是继承View重写OnDraw来完成绘制工作。
前面Android入门——利用Canvas完成绘制点、圆、直线、路径、椭圆、多边形等2D图形可以知道通过Paint可以在Canvas绘制任何图形,包括圆环,于是整体的结构就出来了,中心实体小圆作为指示当前颜色的标记,外圈渐变色圆环作为调色板的取色区域(可以通过给Paint传入Shader shader = new SweepGradient(0, 0, gradientColors, null)来绘制渐变色),最外圈的光环可以绘制多个圆环,而作为指示器标记的小圆点(也可以传入图片资源)也是一个圆形,如此一来UI方面的结构基本明了。
2、交互设计一般来说自定义View的人机交互都是通过回调的方式的来实现的。
滑动选择颜色:自定义控件的滑动自然是重写onTouchEvent,然后调用invalidate手动触发View重绘(即重新调用onDraw)颜色指示器的显示的位置:手动触发invalidate重新调用onDraw绘制中心圆形自动同步选中的颜色:手动触发invalidate重新调用onDraw绘制仅在圆环处滑动选择颜色:如果面积小于外圆大于内圆的就认为是有效滑动/*** 是否是有效Touch即是否是按在圆环之上的* @return*/private boolean isEfectiveTouch(float x, float y, float outRadius, float inRadius){ double outCircle = Math.PI * outRadius * outRadius;double inCircle = Math.PI * inRadius * inRadius;double fingerCircle = Math.PI * (x * x + y * y);if(fingerCircle < outCircle && fingerCircle > inCircle) {return true;}else {return false;}}三、实现彩虹圆环调色板1、自定义属性attr.xml<declare-styleable name="rainbow_palette"><attr name="palette_color" format="color"/><!-- 可滑动小球的颜色--><attr name="indicator_color" format="color" /><!--中间指示当前选中颜色值的圆--><attr name="center_circle_defcolor" format="color"/><!-- 外圈圆环的半径--><attr name="out_circle_radius" format="dimension" /><!-- 调色环的外圈圆环的半径--><attr name="palette_radius" format="dimension" /><!-- 中心圆环的半径--><attr name="center_radius" format="dimension" /><!-- 调色环的宽度--><attr name="palette_width" format="dimension" /><!-- 可滑动小球的半径--><attr name="indicator_radius" format="dimension" /><!--用其他图片来代替绘制的指示器的小圆--><attr name="ic_indicator" format="reference"/></declare-styleable>2、重写Viewimport com.xiaoi.app.zkSmartHome.R;/*** auther: Crazy.Mo* Date: 2016/12/13* Time:10:27* Des:自定义的调色板,可以绘制圆形指示器,也可以自定义图标指示器,但是指示器会超出边界*/public class RainbowPalette extends View {private Context context;private Paint borderPaint;//色环外圈的彩虹圆环private Paint palettePaint;//渐变色环的画笔private Paint centerPaint;//中间圆画笔,用于显示当前选中的颜色private Paint indictorPaint; // 可移动小球画笔private int indictorColor;private int[] gradientColors;//渐变色环颜色private int centerCircleColor;private int width;//当前调色板的宽度private int height;//当前调色板的高度private float paletteRadius;//色环半径,整个环形外径,直接决定这个调色板的整体的大小,画渐变环可以看成画一个完整的圆形再挖掉一个小圆private float centerRadius;//中心圆半径private float paletteWidth;//色环的宽度private float indictorRadius;//小球的半径private Point indictorPosition;// 小球当前位置private Point centerPosition;//圆心的位置,色环圆心的位置private Bitmap indicatorBitmap; // 指示器小球的图标private int indictorResId;//指示器图标的idprivate RainbowPalette.OnColorChangedListen listen;private static boolean isShowIndictor=true;private final static int BORDER_WIDTH=2;private final static int PALETTE_WIDTH=100;private final static int CENTER_CIRCLE_WIDTH=5;private final static int INDICTOR_WIDTH=5;private final static int DEF_INDICTOR_COLOR=0xFFc9f5f1;//设置指示小圆形的颜色private final static int DEF_CIRCLE_COLOR=0xFF0511FB;//设置中间圆的默认颜色public RainbowPalette(Context context) {super(context);}public RainbowPalette(Context context, AttributeSet attrs) {super(context, attrs);this.context = context;init(attrs);}public RainbowPalette(Context context, AttributeSet attrs, int defStyleAttr){super(context, attrs, defStyleAttr);this.context=context;init(attrs);}private void init(AttributeSet attrs){setPaletteSize();initAttrColor(attrs);initPaint();initPosition();initRadiusWidth(attrs);}/*** 用于设置中间圆的颜色* @param color*/public void setCenterPaint(int color){centerPaint.setColor(color);}/*** 设置调色板的尺寸*/private void setPaletteSize(){WindowManager manager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);//获取WM对象int height = (int) (manager.getDefaultDisplay().getHeight() * 0.5f);//获取屏幕的高度*0.5int width = (int) (manager.getDefaultDisplay().getWidth() * 0.7f);//获取屏幕宽度的0.7this.height = height - 36;this.width = width;setMinimumHeight(height - 36);setMinimumWidth(width);}/*** 设置颜色指示器的位置* @param point*/public void setIndictorPosition(Point point){if(point!=null) {this.indictorPosition.x = point.x;this.indictorPosition.y = point.y;}}/*** 设置是否显示颜色指示器* @param isShow*/public static void setIndictorShow(boolean isShow){RainbowPalette.isShowIndictor=isShow;}/*** 设置指示器小球Color的默认值* @param color*/public void setBallColor(int color){this.indictorColor=color;}/*** 初始化各种Paint对象*/private void initPaint(){setGradientColors();Shader shader = new SweepGradient(0, 0, gradientColors, null);//SweepGradient渐变//外层彩虹光环borderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);//在画图的时候,图片如果旋转或缩放之后,总是会出现那些华丽的锯齿。