如何在运行时直接(无动画)设置 FAB 图标旋转和颜色以及 FAB 背景?
How to directly (without animation) set FAB icon rotation&color and FAB background, at runtime?
背景
我正在制作一个上下滑动 FAB 的 POC,类似于它在 Phone 应用程序上的工作方式,当您接到 phone 电话时:
问题
虽然我已经处理了触摸事件(允许上下移动 fab),并在您停止触摸时恢复动画,但我还需要更改 FAB 的背景颜色和图标的旋转和颜色棒极了
我发现了什么
我只找到了 FAB 背景颜色动画及其图标旋转的解决方案:
不过我没有找到如何更改图标本身的颜色。
但在我的例子中,它不能只使用动画来完成,因为 FAB 的 Y 坐标会根据触摸发生变化,所以值需要立即适应,没有动画。
这是我当前的代码:
activity_main.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/fabTouchingAreaView" android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal" android:layout_margin="@dimen/fab_margin"
android:clipChildren="false" android:clipToPadding="false" tools:background="#33ff0000">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab" android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom" android:layout_marginBottom="20dp"
android:layout_marginTop="50dp" android:tint="#0f0" app:backgroundTint="#fff"
app:srcCompat="@android:drawable/stat_sys_phone_call"/>
</FrameLayout>
</FrameLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val yToResetTo = (fab.layoutParams as ViewGroup.MarginLayoutParams).topMargin.toFloat()
val argbEvaluator = ArgbEvaluator()
fabTouchingAreaView.setOnTouchListener(object : View.OnTouchListener {
val WHITE_COLOR = 0xffffffff.toInt()
val RED_COLOR = 0xffff0000.toInt()
val GREEN_COLOR = 0xff00ff00.toInt()
var startTouchY = Float.MIN_VALUE
var startViewY = Float.MIN_VALUE
var maxToGoTo = Float.MIN_VALUE
var animator: ObjectAnimator? = null
fun updateView() {
val newY = fab.y
val percentDown = if (newY <= yToResetTo) 0.0f else ((newY - yToResetTo) / (maxToGoTo - yToResetTo))
val percentUp = if (newY >= yToResetTo) 0.0f else (1.0f - (newY / yToResetTo))
// need code here to update content
}
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
if (animator != null) {
animator!!.cancel()
animator = null
}
startTouchY = motionEvent.rawY
startViewY = fab.y
maxToGoTo = fabTouchingAreaView.height.toFloat() - fab.height
}
MotionEvent.ACTION_UP -> {
if (animator == null) {
animator = ObjectAnimator.ofFloat(fab, View.Y, yToResetTo)
//TODO use normal animate() when minSdk is at least 19
animator!!.addUpdateListener { animation -> updateView() }
animator!!.start()
}
}
MotionEvent.ACTION_MOVE -> {
val newY = Math.min(Math.max(startViewY + (motionEvent.rawY - startTouchY), 0.0f), maxToGoTo)
fab.y = newY
updateView()
}
}
return true
}
})
}
}
下面是其工作原理的演示:
一种可能的解决方法是使用多个视图而不是单个 FAB,我选择如何在它们之间设置动画,但这只是一种解决方法...
问题
如何在运行时更改 FAB 的背景颜色,类似于 Phone 应用程序,仅使用我到达的距离的百分比?
如何在运行时更改 FAB 图标的旋转和颜色,类似于 Phone 应用程序,仅使用我到达的距离的百分比?
编辑:看到已接受的答案,下一个代码将执行我在 updateView
函数中编写的代码:
val fabBackgroundColor = when {
percentDown > 0f -> argbEvaluator.evaluate(percentDown, WHITE_COLOR, RED_COLOR) as Int
percentUp > 0f -> argbEvaluator.evaluate(percentUp, WHITE_COLOR, GREEN_COLOR) as Int
else -> WHITE_COLOR
}
val fabIconColor = when {
percentDown > 0f -> argbEvaluator.evaluate(percentDown, GREEN_COLOR, WHITE_COLOR) as Int
percentUp > 0f -> argbEvaluator.evaluate(percentUp, GREEN_COLOR, WHITE_COLOR) as Int
else -> GREEN_COLOR
}
fab.setColorFilter(fabIconColor)
fab.backgroundTintList = ColorStateList.valueOf(fabBackgroundColor)
fab.rotation = percentDown * 135
Log.d("appLog", "y:" + fab.y + " percentDown:$percentDown percentUp:$percentUp " +
"fabBackgroundColor:${Integer.toHexString(fabBackgroundColor)} fabIconColor:${Integer.toHexString(fabIconColor)}")
How can I change the background color of the FAB, at runtime, similar
to the Phone app, by using just the percentage of how far I got ?
您可以使用ArgbEvaluator
计算当前位置的颜色,并将evaluate
的return值设置为新背景。
How can I change the rotation of the icon of the FAB, at runtime,
similar to the Phone app, by using just the percentage of how far I
got ?
同上,用Interpolator
计算旋转,用View.setRotation
旋转
背景
我正在制作一个上下滑动 FAB 的 POC,类似于它在 Phone 应用程序上的工作方式,当您接到 phone 电话时:
问题
虽然我已经处理了触摸事件(允许上下移动 fab),并在您停止触摸时恢复动画,但我还需要更改 FAB 的背景颜色和图标的旋转和颜色棒极了
我发现了什么
我只找到了 FAB 背景颜色动画及其图标旋转的解决方案:
不过我没有找到如何更改图标本身的颜色。
但在我的例子中,它不能只使用动画来完成,因为 FAB 的 Y 坐标会根据触摸发生变化,所以值需要立即适应,没有动画。
这是我当前的代码:
activity_main.xml
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:clipChildren="false" android:clipToPadding="false"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/fabTouchingAreaView" android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal" android:layout_margin="@dimen/fab_margin"
android:clipChildren="false" android:clipToPadding="false" tools:background="#33ff0000">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab" android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|bottom" android:layout_marginBottom="20dp"
android:layout_marginTop="50dp" android:tint="#0f0" app:backgroundTint="#fff"
app:srcCompat="@android:drawable/stat_sys_phone_call"/>
</FrameLayout>
</FrameLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val yToResetTo = (fab.layoutParams as ViewGroup.MarginLayoutParams).topMargin.toFloat()
val argbEvaluator = ArgbEvaluator()
fabTouchingAreaView.setOnTouchListener(object : View.OnTouchListener {
val WHITE_COLOR = 0xffffffff.toInt()
val RED_COLOR = 0xffff0000.toInt()
val GREEN_COLOR = 0xff00ff00.toInt()
var startTouchY = Float.MIN_VALUE
var startViewY = Float.MIN_VALUE
var maxToGoTo = Float.MIN_VALUE
var animator: ObjectAnimator? = null
fun updateView() {
val newY = fab.y
val percentDown = if (newY <= yToResetTo) 0.0f else ((newY - yToResetTo) / (maxToGoTo - yToResetTo))
val percentUp = if (newY >= yToResetTo) 0.0f else (1.0f - (newY / yToResetTo))
// need code here to update content
}
override fun onTouch(view: View, motionEvent: MotionEvent): Boolean {
when (motionEvent.action) {
MotionEvent.ACTION_DOWN -> {
if (animator != null) {
animator!!.cancel()
animator = null
}
startTouchY = motionEvent.rawY
startViewY = fab.y
maxToGoTo = fabTouchingAreaView.height.toFloat() - fab.height
}
MotionEvent.ACTION_UP -> {
if (animator == null) {
animator = ObjectAnimator.ofFloat(fab, View.Y, yToResetTo)
//TODO use normal animate() when minSdk is at least 19
animator!!.addUpdateListener { animation -> updateView() }
animator!!.start()
}
}
MotionEvent.ACTION_MOVE -> {
val newY = Math.min(Math.max(startViewY + (motionEvent.rawY - startTouchY), 0.0f), maxToGoTo)
fab.y = newY
updateView()
}
}
return true
}
})
}
}
下面是其工作原理的演示:
一种可能的解决方法是使用多个视图而不是单个 FAB,我选择如何在它们之间设置动画,但这只是一种解决方法...
问题
如何在运行时更改 FAB 的背景颜色,类似于 Phone 应用程序,仅使用我到达的距离的百分比?
如何在运行时更改 FAB 图标的旋转和颜色,类似于 Phone 应用程序,仅使用我到达的距离的百分比?
编辑:看到已接受的答案,下一个代码将执行我在 updateView
函数中编写的代码:
val fabBackgroundColor = when {
percentDown > 0f -> argbEvaluator.evaluate(percentDown, WHITE_COLOR, RED_COLOR) as Int
percentUp > 0f -> argbEvaluator.evaluate(percentUp, WHITE_COLOR, GREEN_COLOR) as Int
else -> WHITE_COLOR
}
val fabIconColor = when {
percentDown > 0f -> argbEvaluator.evaluate(percentDown, GREEN_COLOR, WHITE_COLOR) as Int
percentUp > 0f -> argbEvaluator.evaluate(percentUp, GREEN_COLOR, WHITE_COLOR) as Int
else -> GREEN_COLOR
}
fab.setColorFilter(fabIconColor)
fab.backgroundTintList = ColorStateList.valueOf(fabBackgroundColor)
fab.rotation = percentDown * 135
Log.d("appLog", "y:" + fab.y + " percentDown:$percentDown percentUp:$percentUp " +
"fabBackgroundColor:${Integer.toHexString(fabBackgroundColor)} fabIconColor:${Integer.toHexString(fabIconColor)}")
How can I change the background color of the FAB, at runtime, similar to the Phone app, by using just the percentage of how far I got ?
您可以使用ArgbEvaluator
计算当前位置的颜色,并将evaluate
的return值设置为新背景。
How can I change the rotation of the icon of the FAB, at runtime, similar to the Phone app, by using just the percentage of how far I got ?
同上,用Interpolator
计算旋转,用View.setRotation
旋转