[英]Passing Event Information from Custom View to ViewModel
Basically I am implementing a paint app, so I made a custom View to handle event and draw on canvas. 基本上,我正在实现绘画应用程序,因此我制作了一个自定义视图来处理事件并在画布上绘制。 Now I would like to display the coordinate of the points being drawn on a TextView in real time.
现在,我想实时显示在TextView上绘制的点的坐标。 So I am trying to use a ViewModel with LiveData to do the updating.
因此,我尝试将ViewModel与LiveData一起使用来进行更新。 But I can't figure out a way to give the information from my custom View to the ViewModel.
但是我想不出一种方法,可以将自定义View中的信息提供给ViewModel。 How would you do that ?
你会怎么做? I also tried to use BindingAdapter but I can't find a way to do that.
我也尝试使用BindingAdapter,但是我找不到方法。
Here the code for my custom View: 这是我的自定义视图的代码:
class PaintView(context: Context, attrs: AttributeSet): View(context,attrs) {
var params: LayoutParams
private val path : Path = Path()
private val brush: Paint = Paint()
init {
params = LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT)
brush.isAntiAlias = true
brush.color = Color.BLACK
brush.style = Paint.Style.STROKE
brush.strokeJoin = Paint.Join.ROUND
brush.strokeWidth = 8f
}
override fun onTouchEvent(event: MotionEvent): Boolean {
val pointX = event.x
val pointY = event.y
when (event.action) {
MotionEvent.ACTION_DOWN -> {
path.moveTo(pointX, pointY)
return true
}
MotionEvent.ACTION_MOVE -> {
path.lineTo(pointX, pointY)
}
else -> return false
}
postInvalidate()
return false
}
fun clearPath(){
path.reset()
invalidate()
}
public override fun onDraw(canvas: Canvas) {
canvas.drawPath(path, brush)
}
}
Here is a binding adapter that I found following this post: Android data binding view.onTouchListener . 这是我在本文后找到的绑定适配器: Android数据绑定view.onTouchListener 。 I can Log the points coordinate, but I cant't send them to my ViewModel, so it is quite empty right now.
我可以记录点的坐标,但是无法将其发送到我的ViewModel,所以现在它非常空。
@BindingAdapter("touchListener")
fun setTouchListener(self: View, bool: Boolean) {
self.setOnTouchListener(
object : View.OnTouchListener {
override fun onTouch(view: View, event: MotionEvent): Boolean {
val pointX = event.x
val pointY = event.y
when (event.action) {
MotionEvent.ACTION_DOWN -> {
Log.i("Points", " ($pointX, $pointY)")
}
MotionEvent.ACTION_MOVE -> {
Log.i("Points", " ($pointX, $pointY)")
}
MotionEvent.ACTION_UP -> {
Log.i("Points", " ($pointX, $pointY)")
}
}
return false
}
})
}
Sorry for sharing this in JAVA... But I guess you can capture the ideia. 很抱歉在JAVA中分享此内容...但是我想您可以抓住这个想法。
On CustomView, create a custom interface: 在CustomView上,创建一个自定义界面:
public class PaintView {
private OnCoordinateUpdate mCoordinatesListener;
override fun onTouchEvent(event: MotionEvent): Boolean {
val pointX = event.x
val pointY = event.y
....
if(listener != null) {
listener.onUpdate(pointX, pointY);
}
}
...
public void setCoordinatesListener(OnCoordinateUpdate listener) {
mCoordinatesListener = listener;
}
public interface OnCoordinateUpdate {
void onUpdate(int x, int y);
}
}
Then, on your activity: 然后,关于您的活动:
public class MainActivity {
...
mPaintView.setCoordinatesListener(new PaintView.OnCoordinateUpdate {
@Override
void onUpdate(int x, int y) {
if(mTextView != null) {
mTextView.setText("X: " + x + " Y: " + y);
}
}
});
}
This way, your PaintView
can invoke the onUpdate
whenever you want. 这样,您的
PaintView
可以随时调用onUpdate
。 Then, in your activity, everytime the onUpdate
is called, the TextView will have its content updated. 然后,在您的活动中,每次调用
onUpdate
,TextView的内容都会更新。
I guess this is a good a approach because you create a custom interface ( OnCoordinateUpdate
) and it only makes sense to your custom view only. 我猜这是一个好方法,因为您创建了一个自定义界面(
OnCoordinateUpdate
),它仅对您的自定义视图有意义。
Finally it worked the following way. 最终,它按照以下方式工作。 I took inspiration from the previous post and just used the binded viewmodel to call a function and then get the data.
我从前一篇文章中汲取了灵感,只是使用绑定的viewmodel调用一个函数然后获取数据。
here is the MainActivity code: 这是MainActivity代码:
class MainActivity : AppCompatActivity () {
private lateinit var binding: ActivityMainBinding
private lateinit var viewModel: PaintViewModel
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
viewModel = ViewModelProviders.of(this).get(PaintViewModel::class.java)
binding.viewmodel = viewModel
binding.paintView.setCoordinatesListener(object :
PaintView.OnCoordinateUpdate {
override fun onUpdate(x: Float, y: Float) {
binding.textView.text = "X: $x \nY: $y"
binding.viewmodel?.onUpdateCoordinate(x,y)
}
})
binding.clearButton.setOnClickListener { binding.paintView.clearPath() }
}
}
Here is the ViewModel code, the challenge is to call the onUpdate function right in the ViewModel. 这是ViewModel代码,面临的挑战是在ViewModel中直接调用onUpdate函数。
class PaintViewModel : ViewModel() {
private val _pointX = MutableLiveData<Float>()
private val _pointY = MutableLiveData<Float>()
val pointX : LiveData<Float> = _pointX
val pointY : LiveData<Float> = _pointY
init {
_pointX.value = 0f
_pointY.value = 0f
}
fun onUpdateCoordinate(x: Float, y: Float) {
_pointX.value = x
_pointY.value = y
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.