1. 前语
今天来试一个色彩改变的作用,有个控件点击后,背景的色彩就逐步变成另一个色彩。相似这样的一个作用
这个假如用自界说View是有一万种方法去完成,可是咱们要考虑到期望一切控件都能做到,所以就不必自界说View的方式去完成这种作用,比方之前你的同事做了一个控件,你的产品让你给这个控件的点击事情加个酷炫的作用,大概上边演示的作用。
2. 场景剖析
能够先剖析一下怎样去完成这个作用,首要,色彩的改变,是一个进程,那这个进程中,两个色彩之间联接,不能太僵硬,比方你x方位仍是色彩A,x+1的方位立刻变成色彩B,那这样的改变就太僵硬了,要做一个色彩改变的进程,我想到的便是用突变做。
突变又分3种类型,线性、放射、扫描,具体用哪种,根据你的需求,比方我想改变从左到右,那就用线性,假如想像水波纹一样从右下角去改变,那就用放射,抱愧不是你想,是产品想[狗头]。这儿做演示就用线性来演示吧。
色彩联接的问题是处理了,用突变能让色彩的改变进程看起来不会很突兀,那怎样去完成色彩改变的进程,怎样去完成色彩A到色彩B的改变。色彩是这个控件的一个特点,所以是不是就能立刻想到能够用特点动画来完成。
3. 完成作用
ok,经过上面的剖析,咱们要做两个技术点,一个是突变,一个是特点动画。
(1)突变的完成
首要突变咱们平时做,都是用xml去做,这儿由于要合作特点动画,所以咱们要动态去写代码,动态完成突变色的作用能够运用GradientDrawable
咱们先写一个demo看看作用,这儿就用两种色彩来演示,基佬紫和猛男粉
private fun setBg(){
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
drawable.colors = colors
tvTest?.background = drawable
}
能够看到代码很简略,终究完成的作用(我就不贴全代码了,控件就一个TextView)
ok,咱们要做的是中心突变的那段区域从左面屏幕外移动到右边的屏幕外,那就能完成一个色彩改变的进程,这个思路应该能不难理解吧。
那么要怎样移动呢,GradientDrawable我也不熟,不要紧,那就去看官方文档嘛,能发现有个方法level,咱们试着写个轮询去试试这个level的作用,官方有说这个Level的规模是0-10000(这儿开端上动画也行,为了便利也能够先用轮询测作用)
var level = 0
private fun startLooper() {
handler.postDelayed({
if (level < 10000) {
level += 100
setBg()
startLooper()
}
}, 10)
}
private fun setBg(){
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
drawable.useLevel = true
drawable.level = level
drawable.colors = colors
tvTest?.background = drawable
}
看最后的作用
看得出这色彩改变只能变一半,没方法全部变完,level为0的作用便是单色的作用,终究的1000的level作用便是原始的姿态。那我尝试把level设超过10000会怎样,我设个10W
能看出好像是完成了这个作用。其实不然,首要这个终究也并没有完全是单色(只需你把其中一个色彩换成白色就能很容易看出),其次后半段的速度和前面的不同
所以不能牵强用这个方法去做,那为什么要写这个失利的demo出来呢,由于我觉得用Level应该也能有方法完成这个作用的,只是我没时间去认真研究,就简略的运用的话是做不到,可是经过一些奇技淫巧必定仍是能做到的。
已然level完成不了咱们想要的作用,不要紧,咱们再看看文档,发现其实setColors方法是有一个参数的,也有两个参数的,双参的方法中是一个offsets数组,那我感觉这个便是我要找的方法了,把代码改一下。
var x = 0f
private fun startLooper() {
handler.postDelayed({
if (x < 1.1f) {
x += 0.1f
setBg()
startLooper()
}
}, 1000)
}
private fun setBg() {
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val offsets = floatArrayOf(
x - 0.1f,
x
)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
drawable.setColors(colors, offsets)
}
// drawable.colors = colors
tvTest?.background = drawable
}
看看终究的作用
有点意思,怎样搞得像个进度条一样,无所谓,总归这样就能完成色彩突变的这个功用,完成榜首个目标。
(2)色彩改变进程的完成
让上面的作用愈加丝滑,咱们运用特点动画。按理来说这个进程也应该要用特点动画来完成,这样才符合特点动画的界说。
咱们写一个动画
private var mValueAnimator1: ValueAnimator? = null
fun startToStopChange() {
if (mValueAnimator1 == null) {
mValueAnimator1 = ValueAnimator.ofFloat(0f, 1.1f)
mValueAnimator1?.addUpdateListener {
x = it.animatedValue as Float
setBg()
}
}
mValueAnimator1?.setDuration(1000)?.start()
}
整体的代码结合起来便是
var tvTest: TextView? = null
var x = 0f
private var mValueAnimator1: ValueAnimator? = null
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.test_main)
tvTest = findViewById(R.id.tv_test)
setBg()
tvTest?.setOnClickListener {
startToStopChange()
}
}
private fun setBg() {
val colors = intArrayOf(
Color.parseColor("#9932CC"),
Color.parseColor("#FF69B4")
)
val offsets = floatArrayOf(
x - 0.1f,
x
)
val drawable = GradientDrawable()
drawable.gradientType = GradientDrawable.LINEAR_GRADIENT
drawable.orientation = GradientDrawable.Orientation.LEFT_RIGHT
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
drawable.setColors(colors, offsets)
}
// drawable.colors = colors
tvTest?.background = drawable
}
fun startToStopChange() {
if (mValueAnimator1 == null) {
mValueAnimator1 = ValueAnimator.ofFloat(0f, 1.1f)
mValueAnimator1?.addUpdateListener {
x = it.animatedValue as Float
setBg()
}
}
mValueAnimator1?.setDuration(2000)?.start()
}
加了个点击事情,看看终究的作用
ok,看得出终究的作用非常的丝滑。当然我这个是demo,所以这样简略写,主要是为了说明怎样完成,但真实要运用到项目中的话了,必定仍是需求在这代码的基础上做些优化、封装操作的。
4. 总结
简略来说,完成这样的一个动画突变的作用很简略,只需求两步,榜首步用GradientDrawable完成两个色彩之间的突变作用,第二步用特点动画完成色彩改变的进程。
这其实也便是一些很简略的基础知识,基础知识便是你的武器库,一个杂乱的作用,假如你基础牢固的话,你会把这个杂乱的作用去拆分红粒度更小的作用,你知道用哪些基础知识能完成这样的作用,这才是一个真实的开发进程,而不是说产品让你完成一个你没做过的作用,你榜首反应便是去搜索抄他人的代码,榜首反应应该是看看你的武器库,有没有能完成这个目标的武器。我有时也会看他人的代码,但也主要是为了看完成的思路。
再杂乱的作用,也是由很多个很简略的原理去完成的。比方这儿的作用假如放到recyclerView的item中,还要从recyclerView的那块角度加点东西,才干兼容。