簡述: 關注個人Kotlin淺談系列文章的小夥伴就知道關於Kotlin語法篇的內容已經發布了一些。而後就會有小夥伴問了一直都在講語法是否來一波實戰了,畢竟一切一切的學習都是爲了解決實際問題的,因此準備來一波Kotlin實戰篇,主要是用Kotlin來實現一些常見的功能和需求。實現同一個功能相比Java實現你也許會更鐘愛於使用kotlin。php
針對這個問題的回答通常是給正在學習Kotlin或者Kotlin學習的新手而言,若是是剛剛學習Kotlin的時候,讓你去用Kotlin實現一個自定義View,可能會有些不習慣,好比在Kotlin定義View的構造器重載怎麼實現?是否要像Java暴露不少的set方法屬性給外部調用,而後重繪頁面呢?因爲這是第一篇Kotlin實戰篇,也就比較簡單主要針對新手。java
實現圖片圓形和圓角這個需求有不少種方式,通過開發試驗最終比較穩的仍是自定義View來實現。圖片圓形或者圓角在一些圖片加載框架中就集成好了,好比Glide中就有BitmapTransformation,開發者能夠去繼承BitmapTransformation,而後去實現Bitmap繪製邏輯在圖片層面來達到圖片圓角或者圓形的效果。有兩點緣由讓我放棄使用它:git
第一,單從面向對象的角度,庫單一職責來講,圖片加載庫就是負責從網絡源加載圖片的,至於這個ImageView長得什麼形狀,則是經過ImageView來呈現的。github
第二, 使用自定義BitmapTransformation來定義形狀發現有bug,就是一張來自網絡端的圖片當它沒有加載完成的時候是沒法拿到圖片尺寸的,而在BitmapTransformation中須要拿到圖片寬和高。因此用post,Runnable機制等待加載完畢後就去定義形狀,這樣的實如今大部分場景是能夠知足的。可是在一個須要刷新的列表中就會明顯發現,每次刷新圖片去加載,圖片會有空白的過程很影響體驗。canvas
這個自定義View實現原理很簡單,主要有三個比較重要的點,第一就是構建定義圓角矩形的Path;第二是利用Matrix矩陣變換按比例縮小或放大使得圖片大小和ImageView大小保持一致;第三就是使用BitmapShader對已經定義好的path,用帶shader的畫筆進行渲染。網絡
java實現,這樣的寫法是java實現自定義View經常使用套路app
public class PrettyImageView extends ImageView {
public PrettyImageView(Context context) {
this(context, null);
}
public PrettyImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PrettyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
}
複製代碼
kotlin實現,使用到了以前博客講過的默認值參數實現函數重載以及使用@JvmOverloads註解是爲了在Java中能夠調用Kotlin中定義重載構造器方法。(這兩個知識點都是以前博客有專門分析包括其原理)框架
class PrettyImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
: ImageView(context, attributeSet, defAttrStyle) {
}
複製代碼
java實現,須要實現對應屬性的setter方法,而後內部調用invalidate重繪ide
public class PrettyImageView extends ImageView {
private boolean mIsShowBorder;
private float mBorderWidth;
private int mBorderColor;
private boolean mIsShowDot;
private float mDotRadius;
private int mDotColor;
public PrettyImageView(Context context) {
this(context, null);
}
public PrettyImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public PrettyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setmIsShowBorder(boolean mIsShowBorder) {
this.mIsShowBorder = mIsShowBorder;
invalidate();
}
public void setmBorderWidth(float mBorderWidth) {
this.mBorderWidth = mBorderWidth;
invalidate();
}
public void setmBorderColor(int mBorderColor) {
this.mBorderColor = mBorderColor;
invalidate();
}
public void setmIsShowDot(boolean mIsShowDot) {
this.mIsShowDot = mIsShowDot;
invalidate();
}
public void setmDotRadius(float mDotRadius) {
this.mDotRadius = mDotRadius;
invalidate();
}
public void setmDotColor(int mDotColor) {
this.mDotColor = mDotColor;
invalidate();
}
}
複製代碼
Kotlin實現則不須要定義那麼多setter方法,由於Kotlin中var變量就自帶setter和getter方法,能夠咱們又想達到當從新改變值後須要調用invalidate函數。這是就須要用以前講過自定義變量訪問器。函數
class PrettyImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
: ImageView(context, attributeSet, defAttrStyle) {
private var mBorderWidth: Float = 20f
set(value) {
field = value
invalidate()
}
private var mBorderColor: Int = Color.parseColor("#ff9900")
set(value) {
field = value
invalidate()
}
private var mShowBorder: Boolean = true
set(value) {
field = value
invalidate()
}
private var mShowCircleDot: Boolean = false
set(value) {
field = value
invalidate()
}
private var mCircleDotColor: Int = Color.RED
set(value) {
field = value
invalidate()
}
private var mCircleDotRadius: Float = 20f
set(value) {
field = value
invalidate()
}
}
複製代碼
開放屬性name | 開放屬性含義 |
---|---|
shape_type | 形狀類型,目前只有圓角和圓形兩種類型 |
left_top_radiusX | 左上角X軸方向半徑 |
left_top_radiusY | 左上角Y軸方向半徑 |
right_top_radiusX | 右上角X軸方向半徑 |
right_top_radiusY | 右上角Y軸方向半徑 |
right_bottom_radiusX | 右下角X軸方向半徑 |
right_bottom_radiusY | 右下角Y軸方向半徑 |
left_bottom_radiusX | 左下角X軸方向半徑 |
left_bottom_radiusY | 左下角Y軸方向半徑 |
show_border | 是否顯示邊框 |
border_width | 邊框寬度 |
border_color | 邊框顏色 |
show_circle_dot | 是否顯示右上角圓點 |
circle_dot_color | 右上角圓點顏色 |
circle_dot_radius | 右上角圓點半徑 |
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="PrettyImageView">
<attr name="shape_type">
<enum name="SHAPE_CIRCLE" value="0"></enum>
<enum name="SHAPE_ROUND" value="1"></enum>
</attr>
<attr name="border_width" format="dimension"/>
<attr name="border_color" format="color"/>
<attr name="left_top_radiusX" format="dimension"/>
<attr name="left_top_radiusY" format="dimension"/>
<attr name="right_top_radiusX" format="dimension"/>
<attr name="right_top_radiusY" format="dimension"/>
<attr name="right_bottom_radiusX" format="dimension"/>
<attr name="right_bottom_radiusY" format="dimension"/>
<attr name="left_bottom_radiusX" format="dimension"/>
<attr name="left_bottom_radiusY" format="dimension"/>
<attr name="show_border" format="boolean"/>
<attr name="show_circle_dot" format="boolean"/>
<attr name="circle_dot_color" format="color"/>
<attr name="circle_dot_radius" format="dimension"/>
</declare-styleable>
</resources>
複製代碼
class PrettyImageView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defAttrStyle: Int = 0)
: ImageView(context, attributeSet, defAttrStyle) {
enum class ShapeType {
SHAPE_CIRCLE,
SHAPE_ROUND
}
//defAttr var
private var mShapeType: ShapeType = ShapeType.SHAPE_CIRCLE
set(value) {
field = value
invalidate()
}
private var mBorderWidth: Float = 20f
set(value) {
field = value
invalidate()
}
private var mBorderColor: Int = Color.parseColor("#ff9900")
set(value) {
field = value
invalidate()
}
private var mLeftTopRadiusX: Float = 0f
set(value) {
field = value
invalidate()
}
private var mLeftTopRadiusY: Float = 0f
set(value) {
field = value
invalidate()
}
private var mRightTopRadiusX: Float = 0f
set(value) {
field = value
invalidate()
}
private var mRightTopRadiusY: Float = 0f
set(value) {
field = value
invalidate()
}
private var mLeftBottomRadiusX: Float = 0f
set(value) {
field = value
invalidate()
}
private var mLeftBottomRadiusY: Float = 0f
set(value) {
field = value
invalidate()
}
private var mRightBottomRadiusX: Float = 0f
set(value) {
field = value
invalidate()
}
private var mRightBottomRadiusY: Float = 0f
set(value) {
field = value
invalidate()
}
private var mShowBorder: Boolean = true
set(value) {
field = value
invalidate()
}
private var mShowCircleDot: Boolean = false
set(value) {
field = value
invalidate()
}
private var mCircleDotColor: Int = Color.RED
set(value) {
field = value
invalidate()
}
private var mCircleDotRadius: Float = 20f
set(value) {
field = value
invalidate()
}
//drawTools var
private lateinit var mShapePath: Path
private lateinit var mBorderPath: Path
private lateinit var mBitmapPaint: Paint
private lateinit var mBorderPaint: Paint
private lateinit var mCircleDotPaint: Paint
private lateinit var mMatrix: Matrix
//temp var
private var mWidth: Int = 200//View的寬度
private var mHeight: Int = 200//View的高度
private var mRadius: Float = 100f//圓的半徑
init {
initAttrs(context, attributeSet, defAttrStyle)//獲取自定義屬性的值
initDrawTools()//初始化繪製工具
}
private fun initAttrs(context: Context, attributeSet: AttributeSet?, defAttrStyle: Int) {
val array = context.obtainStyledAttributes(attributeSet, R.styleable.PrettyImageView, defAttrStyle, 0)
(0..array.indexCount)
.asSequence()
.map { array.getIndex(it) }
.forEach {
when (it) {
R.styleable.PrettyImageView_shape_type ->
mShapeType = when {
array.getInt(it, 0) == 0 -> ShapeType.SHAPE_CIRCLE
array.getInt(it, 0) == 1 -> ShapeType.SHAPE_ROUND
else -> ShapeType.SHAPE_CIRCLE
}
R.styleable.PrettyImageView_border_width ->
mBorderWidth = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 4f, resources.displayMetrics))
R.styleable.PrettyImageView_border_color ->
mBorderColor = array.getColor(it, Color.parseColor("#ff0000"))
R.styleable.PrettyImageView_left_top_radiusX ->
mLeftTopRadiusX = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_left_top_radiusY ->
mLeftTopRadiusY = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_left_bottom_radiusX ->
mLeftBottomRadiusX = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_left_bottom_radiusY ->
mLeftBottomRadiusY = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_right_bottom_radiusX ->
mRightBottomRadiusX = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_right_bottom_radiusY ->
mRightBottomRadiusY = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_right_top_radiusX ->
mRightTopRadiusX = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_right_top_radiusY ->
mRightTopRadiusY = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0f, resources.displayMetrics))
R.styleable.PrettyImageView_show_border ->
mShowBorder = array.getBoolean(it, false)
R.styleable.PrettyImageView_show_circle_dot ->
mShowCircleDot = array.getBoolean(it, false)
R.styleable.PrettyImageView_circle_dot_color ->
mCircleDotColor = array.getColor(it, Color.parseColor("#ff0000"))
R.styleable.PrettyImageView_circle_dot_radius ->
mCircleDotRadius = array.getDimension(it, TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5f, resources.displayMetrics))
}
}
array.recycle()
}
private fun initDrawTools() {
mBitmapPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {//最終繪製圖片的畫筆,須要設置BitmapShader着色器,從而實現把圖片繪製在不一樣形狀圖形上
style = Paint.Style.FILL
}
mBorderPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {//繪製邊框畫筆
style = Paint.Style.STROKE
color = mBorderColor
strokeCap = Paint.Cap.ROUND
strokeWidth = mBorderWidth
}
mCircleDotPaint = Paint(Paint.ANTI_ALIAS_FLAG).apply {//繪製右上角圓點畫筆
style = Paint.Style.FILL
color = mCircleDotColor
}
mShapePath = Path()//描述形狀輪廓的path路徑
mBorderPath = Path()//描述圖片邊框輪廓的path路徑
mMatrix = Matrix()//用於縮放圖片的矩陣
scaleType = ScaleType.CENTER_CROP
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {//View的測量
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (mShapeType == ShapeType.SHAPE_CIRCLE) {
mWidth = Math.min(measuredWidth, measuredHeight)
mRadius = mWidth / 2.0f
setMeasuredDimension(mWidth, mWidth)
} else {
mWidth = measuredWidth
mHeight = measuredHeight
setMeasuredDimension(mWidth, mHeight)
}
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {//肯定了最終View的尺寸
super.onSizeChanged(w, h, oldw, oldh)
mBorderPath.reset()
mShapePath.reset()
when (mShapeType) {
ShapeType.SHAPE_ROUND -> {
mWidth = w
mHeight = h
buildRoundPath()
}
ShapeType.SHAPE_CIRCLE -> {
buildCirclePath()
}
}
}
private fun buildCirclePath() {//構建圓形類型的Path路徑
if (!mShowBorder) {//繪製不帶邊框的圓形實際上只須要把一個圓形扔進path便可
mShapePath.addCircle(mRadius, mRadius, mRadius, Path.Direction.CW)
} else {//繪製帶邊框的圓形須要把內部圓形和外部圓形邊框都要扔進path
mShapePath.addCircle(mRadius, mRadius, mRadius - mBorderWidth, Path.Direction.CW)
mBorderPath.addCircle(mRadius, mRadius, mRadius - mBorderWidth / 2.0f, Path.Direction.CW)
}
}
private fun buildRoundPath() {//構建圓角類型的Path路徑
if (!mShowBorder) {//繪製不帶邊框的圓角實際上只須要把一個圓角矩形扔進path便可
floatArrayOf(mLeftTopRadiusX, mLeftTopRadiusY,
mRightTopRadiusX, mRightTopRadiusY,
mRightBottomRadiusX, mRightBottomRadiusY,
mLeftBottomRadiusX, mLeftBottomRadiusY).run {
mShapePath.addRoundRect(RectF(0f, 0f, mWidth.toFloat(), mHeight.toFloat()), this, Path.Direction.CW)
}
} else {//繪製帶邊框的圓角實際上只須要把一個圓角矩形和一個圓角矩形的變量都扔進path便可
floatArrayOf(mLeftTopRadiusX - mBorderWidth / 2.0f, mLeftTopRadiusY - mBorderWidth / 2.0f,
mRightTopRadiusX - mBorderWidth / 2.0f, mRightTopRadiusY - mBorderWidth / 2.0f,
mRightBottomRadiusX - mBorderWidth / 2.0f, mRightBottomRadiusY - mBorderWidth / 2.0f,
mLeftBottomRadiusX - mBorderWidth / 2.0f, mLeftBottomRadiusY - mBorderWidth / 2.0f).run {
mBorderPath.addRoundRect(RectF(mBorderWidth / 2.0f, mBorderWidth / 2.0f, mWidth.toFloat() - mBorderWidth / 2.0f, mHeight.toFloat() - mBorderWidth / 2.0f), this, Path.Direction.CW)
}
floatArrayOf(mLeftTopRadiusX - mBorderWidth, mLeftTopRadiusY - mBorderWidth,
mRightTopRadiusX - mBorderWidth, mRightTopRadiusY - mBorderWidth,
mRightBottomRadiusX - mBorderWidth, mRightBottomRadiusY - mBorderWidth,
mLeftBottomRadiusX - mBorderWidth, mLeftBottomRadiusY - mBorderWidth).run {
mShapePath.addRoundRect(RectF(mBorderWidth, mBorderWidth, mWidth.toFloat() - mBorderWidth, mHeight.toFloat() - mBorderWidth),
this, Path.Direction.CW)
}
}
}
override fun onDraw(canvas: Canvas?) {//因爲通過以上根據不一樣邏輯構建了boderPath和shapePath,path中已經儲存相應的形狀,如今只須要把相應shapePath中形狀用帶BitmapShader畫筆繪製出來,boderPath用普通畫筆繪製出來便可
drawable ?: return
mBitmapPaint.shader = getBitmapShader()//得到相應的BitmapShader着色器對象
when (mShapeType) {
ShapeType.SHAPE_CIRCLE -> {
if (mShowBorder) {
canvas?.drawPath(mBorderPath, mBorderPaint)//繪製圓形圖片邊框path
}
canvas?.drawPath(mShapePath, mBitmapPaint)//繪製圓形圖片形狀path
if (mShowCircleDot) {
drawCircleDot(canvas)//繪製圓形圖片右上角圓點
}
}
ShapeType.SHAPE_ROUND -> {
if (mShowBorder) {
canvas?.drawPath(mBorderPath, mBorderPaint)//繪製圓角圖片邊框path
}
canvas?.drawPath(mShapePath, mBitmapPaint)//繪製圓角圖片形狀path
}
}
}
private fun drawCircleDot(canvas: Canvas?) {
canvas?.run {
drawCircle((mRadius + mRadius * (Math.sqrt(2.0) / 2.0f)).toFloat(), (mRadius - mRadius * (Math.sqrt(2.0) / 2.0f)).toFloat(), mCircleDotRadius, mCircleDotPaint)
}
}
private fun getBitmapShader(): BitmapShader {
val bitmap = drawableToBitmap(drawable)
return BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP).apply {
var scale = 1.0f
if (mShapeType == ShapeType.SHAPE_CIRCLE) {
scale = (mWidth * 1.0f / Math.min(bitmap.width, bitmap.height))
} else if (mShapeType == ShapeType.SHAPE_ROUND) {
// 若是圖片的寬或者高與view的寬高不匹配,計算出須要縮放的比例;縮放後的圖片的寬高,必定要大於咱們view的寬高;因此咱們這裏取大值;
if (!(width == bitmap.width && width == bitmap.height)) {
scale = Math.max(width * 1.0f / bitmap.width, height * 1.0f / bitmap.height)
}
}
// shader的變換矩陣,咱們這裏主要用於放大或者縮小
mMatrix.setScale(scale, scale)
setLocalMatrix(mMatrix)
}
}
private fun drawableToBitmap(drawable: Drawable): Bitmap {
if (drawable is BitmapDrawable) {
return drawable.bitmap
}
return Bitmap.createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight, Bitmap.Config.ARGB_8888).apply {
drawable.setBounds(0, 0, drawable.intrinsicWidth, drawable.intrinsicHeight)
drawable.draw(Canvas(this@apply))
}
}
companion object {
private const val STATE_INSTANCE = "state_instance"
private const val STATE_INSTANCE_SHAPE_TYPE = "state_shape_type"
private const val STATE_INSTANCE_BORDER_WIDTH = "state_border_width"
private const val STATE_INSTANCE_BORDER_COLOR = "state_border_color"
private const val STATE_INSTANCE_RADIUS_LEFT_TOP_X = "state_radius_left_top_x"
private const val STATE_INSTANCE_RADIUS_LEFT_TOP_Y = "state_radius_left_top_y"
private const val STATE_INSTANCE_RADIUS_LEFT_BOTTOM_X = "state_radius_left_bottom_x"
private const val STATE_INSTANCE_RADIUS_LEFT_BOTTOM_Y = "state_radius_left_bottom_y"
private const val STATE_INSTANCE_RADIUS_RIGHT_TOP_X = "state_radius_right_top_x"
private const val STATE_INSTANCE_RADIUS_RIGHT_TOP_Y = "state_radius_right_top_y"
private const val STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_X = "state_radius_right_bottom_x"
private const val STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_Y = "state_radius_right_bottom_y"
private const val STATE_INSTANCE_RADIUS = "state_radius"
private const val STATE_INSTANCE_SHOW_BORDER = "state_radius_show_border"
}
//View State Save
override fun onSaveInstanceState(): Parcelable = Bundle().apply {
putParcelable(STATE_INSTANCE, super.onSaveInstanceState())
putInt(STATE_INSTANCE_SHAPE_TYPE, when (mShapeType) {
ShapeType.SHAPE_CIRCLE -> 0
ShapeType.SHAPE_ROUND -> 1
})
putFloat(STATE_INSTANCE_BORDER_WIDTH, mBorderWidth)
putInt(STATE_INSTANCE_BORDER_COLOR, mBorderColor)
putFloat(STATE_INSTANCE_RADIUS_LEFT_TOP_X, mLeftTopRadiusX)
putFloat(STATE_INSTANCE_RADIUS_LEFT_TOP_Y, mLeftTopRadiusY)
putFloat(STATE_INSTANCE_RADIUS_LEFT_BOTTOM_X, mLeftBottomRadiusX)
putFloat(STATE_INSTANCE_RADIUS_LEFT_BOTTOM_Y, mLeftBottomRadiusY)
putFloat(STATE_INSTANCE_RADIUS_RIGHT_TOP_X, mRightTopRadiusX)
putFloat(STATE_INSTANCE_RADIUS_RIGHT_TOP_Y, mRightTopRadiusY)
putFloat(STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_X, mRightBottomRadiusX)
putFloat(STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_Y, mRightBottomRadiusY)
putFloat(STATE_INSTANCE_RADIUS, mRadius)
putBoolean(STATE_INSTANCE_SHOW_BORDER, mShowBorder)
}
//View State Restore
override fun onRestoreInstanceState(state: Parcelable?) {
if (state !is Bundle) {
super.onRestoreInstanceState(state)
return
}
with(state) {
super.onRestoreInstanceState(getParcelable(STATE_INSTANCE))
mShapeType = when {
getInt(STATE_INSTANCE_SHAPE_TYPE) == 0 -> ShapeType.SHAPE_CIRCLE
getInt(STATE_INSTANCE_SHAPE_TYPE) == 1 -> ShapeType.SHAPE_ROUND
else -> ShapeType.SHAPE_CIRCLE
}
mBorderWidth = getFloat(STATE_INSTANCE_BORDER_WIDTH)
mBorderColor = getInt(STATE_INSTANCE_BORDER_COLOR)
mLeftTopRadiusX = getFloat(STATE_INSTANCE_RADIUS_LEFT_TOP_X)
mLeftTopRadiusY = getFloat(STATE_INSTANCE_RADIUS_LEFT_TOP_Y)
mLeftBottomRadiusX = getFloat(STATE_INSTANCE_RADIUS_LEFT_BOTTOM_X)
mLeftBottomRadiusY = getFloat(STATE_INSTANCE_RADIUS_LEFT_BOTTOM_Y)
mRightTopRadiusX = getFloat(STATE_INSTANCE_RADIUS_RIGHT_TOP_X)
mRightTopRadiusY = getFloat(STATE_INSTANCE_RADIUS_RIGHT_TOP_Y)
mRightBottomRadiusX = getFloat(STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_X)
mRightBottomRadiusY = getFloat(STATE_INSTANCE_RADIUS_RIGHT_BOTTOM_Y)
mRadius = getFloat(STATE_INSTANCE_RADIUS)
mShowBorder = getBoolean(STATE_INSTANCE_SHOW_BORDER)
}
}
}
複製代碼
運行效果截圖:
歡迎關注Kotlin開發者聯盟,這裏有最新Kotlin技術文章,每週會不按期翻譯一篇Kotlin國外技術文章。若是你也喜歡Kotlin,歡迎加入咱們~~~