Передача информации о событии из пользовательского представления в ViewModel - PullRequest
0 голосов
/ 20 мая 2019

По сути, я реализую приложение рисования, поэтому я создал собственный вид для обработки события и рисования на холсте. Теперь я хотел бы отобразить координаты точек, нарисованных на TextView в режиме реального времени. Поэтому я пытаюсь использовать ViewModel с LiveData для обновления. Но я не могу найти способ передать информацию из моего пользовательского представления в модель представления. Как бы Вы это сделали ? Я также пытался использовать BindingAdapter, но не могу найти способ сделать это.

Вот код для моего кастомного просмотра:

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)
    }
}

Вот адаптер привязки, который я нашел после этого поста: Представление привязки данных Android. OnTouchListener . Я могу записать координаты точек, но я не могу отправить их в свою 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
            }
        })
}

Ответы [ 2 ]

1 голос
/ 20 мая 2019

Извините, что поделился этим в JAVA ... Но я думаю, вы можете запечатлеть эту идею.

В 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);
    }
}

Тогда по вашей деятельности:

public class MainActivity {
    ...
    mPaintView.setCoordinatesListener(new PaintView.OnCoordinateUpdate {
        @Override
        void onUpdate(int x, int y) {
            if(mTextView != null) {
                mTextView.setText("X: " + x + " Y: " + y);
            }
        }
    });
}

Таким образом, ваш PaintView может вызывать onUpdate в любое время. Затем в вашей деятельности каждый раз, когда вызывается onUpdate, TextView будет обновлять свое содержимое.

Полагаю, это хороший подход, поскольку вы создаете пользовательский интерфейс (OnCoordinateUpdate), и он имеет смысл только для вашего пользовательского представления.

0 голосов
/ 21 мая 2019

Наконец-то все заработало следующим образом.Я черпал вдохновение из предыдущего поста и просто использовал привязанную модель представления для вызова функции и получения данных.

Вот код 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() }
    }
}

Вот код ViewModel,Задача состоит в том, чтобы вызвать функцию onUpdate прямо в ViewModel.

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
        }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...