前言

常常写自定义View的同学都会知道,当View发生改动时,想要自动的去改写View,无外乎两个办法:主线程调用invalidate(),子线程调用postInvalidate()。调用上述两个办法后,体系会在适合canvassing的时分去改写咱们的View,即回调onDraw办法。带着这样的认知,咱们默许会以为在扫除其他烦扰要素的状况时,只需不调用invaidate()系列办法,咱们的自定义View只会坚持上一次改写时的姿势。可是Android就android平板电脑价格总是会给咱们带来惊喜(ㄒoㄒ),接下来的查验将会改http 404写你的认知。

好戏开始

咱们先来创建两个自定义View:

/**
* 自定义View
*/
class Myandroid/yunosView : Viappleew {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?HTTPS) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Iappearnt) : super(
context,
attrs,
defStyleAttr
)
private var mColor: Int = Coandroid体系lor.BLUE
private var mPaint: Paint = Paint()
private var mTextPaint: Paint = Paiandroidstudio装置教程nt()
init {
mPaint.color = mColor
mPaint.scanvas中文trokeWidth = 10f
mPaint.style = Paint.Stycanvas标签le.SapproachTROKE
mThttps协议extPhttps认证aint.color = Chttpclientolhttps协议or.BLACK
mTextPaint.textSize = 50f
}
override fun onDraw(canvas: Canvashttp://192.168.1.1登录?) {
super.onDraw(canapplevas)
Log.e("MyView", "onDraw")
canvas?.drawRect(100f, 1https安全问题00f, 300f, 300f, mPaint)
canvcanvas中文as?.drawText("MyView", 50f, 50f, mTextPaint)
}
open fun setColor(@ColorInt color: Int) {
this.mapplicationColor = color
mPaint.color = mColor
}
}
/**
* 自定义VieHTTPSw运用双缓冲改写
*/
class MyViewUseBitmap : View {
constructor(contexappeart: Contexappreciatet?) : super(context)
constructor(conapproachtext: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr:Android Int) : super(
context,
atcanvaspsutrs,
defStyleAttr
)
private var mCanvahttp署理s: Canvas? = null
private var mBitmap: Bitmap? = nhttps安全问题ull
private var mColor: Int = Color.BLUE
private var mPaint: Paint =application Paint()
privatcanvas_ide var mTextPaint: Paint = Paint()
init {
mPaint.colorandroid下载 = mColoandroid什么意思r
mPaint.strokeWidth = 10f
mPainthttpwatch.style = Pandroid是什么手机牌子aint.Style.STROKE
mTextPaint.colandroid下载or = Color.BLACcanvas下载K
mTextPaint.textSize = 50f
}
override fucanvas_idn onSizeChanged(w: Inandroid/yunost, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (mBitmap == null)android平板电脑价格 {
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8http://www.baidu.com888)
mCanvas = Canvas(mBitmap!!)
mCanvas?.drawRect(100f, 100f, 300f, 300f, mPaint)
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
Log.e("MyViewUseBihttp署理tmap", "onDraw")
mBitmap?.aphttp 302ply {
canvas?.drawBitmap(this, 0f, 0f, null)
}
canvas?.drawText("MyViewUseBitmap", 50fhttp 404, 50f, mTextPaandroidstudio装置教程int)
}
open fun setColor(@ColorInt color: Int) {
this.mColor = color
mPaint.color = mColor
mBitmap?.eraseColor(Color.TRANSPARENT)
mCanvas?.drawRect(100f, 100f, 300f, 300f, mPaint)
}
}

上述两个自定义View的最大差异便是一个运用了双缓冲改写,一个没有运用。

接下来创建咱们的Activity:

class Mahttp署理inActivity : AppCompatActivity() {
override fun onCreate(savcanvas交大edInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentViecanvas软件w(R.layout.activitandroid是什么手机牌子y_main)
val myView = findViewById<MyView>(R.id.myView)
val myViewUseBitmap = findViewById<MyViewUseBitmap>(R.id.myViewUseBitmappearap)
findViewById<Vhttp协议iew&canvas下载gt;(R.id.changeColor).setOnClickListener {
myView.setColor(Color.RED)
myViewUseBitmap.setColor(Colorappearance.RED)
}
findViewByIdapprove<Viewapproach>(R.icanvassingd.invalidate).setOnClickListenandroidstudio装置教程er {
mAPPyView.invalidate()
myViewUseBitmap.invalidate()
}
}
}

以及layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.wiandroid/yunosdget.ConstraintLappstoreayout xmlns:android="android是什么手机牌子http://schemas.android.com/apk/res/android"
xmlns:android的drawable类app="http://schemas.android.com/canvas中文apAndroidk/res-auto"
xmlns:tools="http://schemas.android.comandroid下载/tools"
andappreciateroid:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.hardwareandinvaandroid下载装置lidate.MyView
android:id="@+id/myVappleiew"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/myViewUseBitmap"
app:layout_constraintLeft_toLeftOfappstore="parent"
app:landroidstudio装置教程ayout_conscanvas_idtraintTop_toTopOf="parent" />
<com.examhttps协议ple.APPhardwareandinvandroid/yunosalidate.MyViewUseBitmap
android:id="@+id/mycanvassedViewUseBitmap"
androicanvasd:layout_width="match_parent"
android:layout_height=Android"0dp"
app:layoucanvassedt_constraintBottom_toTopOf="@id/changeColor"
app:lacanvas标签yout_cappearonstraintLeft_toLeftOf="appointmentpareappearnt"
app:layouhttps域名t_constraintTop_toBottomOf="@id/myView" />
<androidx.appcompat.widget.AppCompandroidstudio装置教程atTextView
android:id="@+id/changeColor"
android:layout_width="150dp"
android:layout_heighhttp://192.168.1.1登录t="60dp"
android:layout_margin="20dp"
android:background="@color/black"
android:text="Change Color"
anhttp://192.168.1.1登录droid:gravity="center"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent" /&gtapp装置下载;
<androidx.appcompat.widget.AppComandroid下载装置patTextView
andrappreciateohttps协议idandroid下载装置:id="@+id/invalidate"
android:layout_width="150dp"
android:layout_height="60dp"
android:layout_margin="20dp"
android:background="@Androidcolor/black"
android:text="Invalidate"
android:gravity="center"
android:textColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layapproachout_constraintRight_toRightOf="parent" />
</androidandroid平板电脑价格x.constraiandroid手机ntlayout.whttps和http的差异idget.ConstraintLayout>

能够看到当时的界面便是把上述两个自定义Vandroid/yunosiew显示出来,【Change Color】按钮做的作业便是改动色彩,【CanvasInvalidate】调用了ViewHTTPS的invalidate()方https安全问题法。

来跑起来看一下正常的作用httpwatch

Android View双缓冲制作下不契合逻辑的改写机制

能够看到我现已点击了好几次的【Change Color】按钮,可是两个自定义View并没有随之发生改变,知道我点击【Invalidate】按钮,两个View才发生了改动,这样的作用与咱们的认知相同。

接下来才开始重头戏:只更改【Change Cohttps协议lappstoreor】按钮的点击款式:

...
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/changeColor"
android:layout_width="150dp"
android:layout_height="60dp"
android:layout_margin="20dp"
android:background="@drawable/selector_press"//修改点
andrandroid手机oid:text=appreciate"Change Color"
android:gravity="center"
android:textColor="@drawable/selector_https认证text_color"//修改点
app:layout_constraintBottomappstore_toBottomOf="papprovearent
app:layout_constraintLeft_toLeftOf="parent" />
...
//selector_press.xml
<?xml version="1.0" ecanvas软件ncoding="utf-8"?>
<https认证selectoappointmentr xmlns:android="http://schemas.android.com/apk/res/androidandroid/yunos">
<item android:drawable="@drawable/shape_press" android:statHTTPe_pressed="true"/>
<item android:drawable="@drawable/shape_normal" anhttps和http的差异droid:state_android下载装置pressed="false"/>
</selector>
//shape_press.xcanvasml
<?xml vAndroidersion="1.0" encoding="utf-8"?>
<shape xmlns:android="http://sappointmentchemas.android.canvas标签com/apk/res/android" andappointmentroid:shape="rectangle" >
<solid andhttps安全问题roid:color="app装置下载#000000" />
<stroke android:width="1dip" android:color="#3F3F3F"/>
<!-- 圆角 -->
<chttp协议orners android:radius="10dp" />
<!--Canvas 边距 -->
<canvassingpaapp装置下载dding
andrHTTPoid:bottom="5dp"
android:left="5dp"
androihttps域名d:right="5dpandroid体系"
android:top="5dp" />
</shape>
//shape_normal.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" androidcanvas_id:shape="rectangle" >
<solid android:chttpwatcholor="#android什么意思FFFFFF" />
<stroke android:width="2dp" android:color="#000000"/>
<!-- 圆角 -->
<cornerandroid下载装置s android:radius="10dp" />
<!-- 边距 -->
<padding
android:bottom="5dp"
android:left="5dp"
android:right="5dp"
android:top="5dp" />
</shape>
// selechttp 302torappear_tHTTPSext_color.xml
<http://192.168.1.1登录?xml version="1.0" encoding="utf-8"?appstore>
<selector xmlnscanvas软件:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/white"canvas_id android:state_pressed="true"/>
<item android:color="@color/black" android:state_pressed="false"/>
</selector>

让咱们看一下作业作用:

Android View双缓冲制作下不契合逻辑的改写机制

仔细的同学现已发现了其间的不同之处,当我点击【Change Color】按钮后,MyView没有任何改变,可是MyViewUseBitmap却直接自动改写了,等我点击【Invalidate】按钮后MyView才进行了改写,MyView的表现是契合咱们的预期的。也便是MyViewUseBitmap在咱们没有自动调用 invalidate() 时自己进行了自动application改写。像我相同猜想斗胆的同学可能https域名会觉得,是按钮的点击款式改写导致了View Tree的改写,进而带动MyViewUseBitmap的改写。可是我能够很负责的奉告你,点击【Change Colorapp装置下载】按钮后,经过调试以android下载装置及日志查看,MyViewUseBitmap的onDraw办法并没有被调用。也便是说在onDraw()没有被android的drawable类回调的状况下,咱们的View进行了改写。

在一些场景下,我appearance需求我的View要approve按照我的改写机会去改写,所以关于上述现象就会变得不可控。一开始碰到这种状况,我也是一脸懵逼的,又第N次发生了我不会Android开发Canvas的主见(ㄒoㄒ)。好在我最后找到了处理计划,又让我打消了转行的主android/yunos意。那便是:

// 翻开View的硬件加approach
setLayerType(LAYER_TYPE_httpclientHARDWARE, null)
或
// 翻开View的软件加快
setLayerhttp署理Type(LAYER_TYPE_SOFTWARE, nHTTPull)
为了兼容性能够运用 LAYER_TYPE_SOFTWARE,为了性能能够运用 LAYER_TYPE_canvassedHARDWhttp 302ARE。

到此问题就完美处理了,再跑一下看看:

Android View双缓冲制作下不契合逻辑的改写机制

开心,又能够愉快的写Android了。

总结

在自定义Viehttp 404w没有运用双缓冲机制https安全问题的状况下,View的改写是可控的;可是一旦运用了双缓冲机制,界面其他部分的改变,可能会带动咱们的Vandroid体系iew进行改写。尽管现在没有找到原因,好在找到了处理办法,那便是需求调用View.setLayerType(),传入的参数能够是LAYER_TYPE_HARDWARE或者LAhttps协议YER_TYPE_SOFTWARE,可是不能是LAYER_TYPE_NONE。

LAYER_TYPE_NONE:是View的默许行为,View会正常烘托,不支持离屏HTTP缓冲区
LAYER_TYPE_HARDWARE:硬件加快,View会以硬件的办法烘托为canvas交大硬件纹路
LAYER_TYPE_http署理SOFTWARE:软http://192.168.1.1登录件加快,View会以软件的办法烘托为位图

以上有什么不对的地方欢迎评论。

转载请注明出处https://juejiapproachn.cn/post/69512981264184443android体系24