Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Data Binding onClick not working

I am getting started for using DataBinding and something is wrong with my onClick.

GameViewModel.java

public void onClickItem(int row, int col){
    Log.d("click","row: "+row+" col: "+col);
}
@BindingAdapter("load_image")
public static void loadImage(ImageView view,int imageId) {
    view.setImageResource(getDrawable(imageId));
}

GameFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    //View view=inflater.inflate(R.layout.fragment_game, container, false);
    FragmentGameBinding binding = DataBindingUtil.inflate(inflater, R.layout.fragment_game, container, false);
    View view = binding.getRoot();
    ButterKnife.bind(this,view);
    binding.setGameViewModel(gameViewModel);
    gameViewModel= ViewModelProviders.of(getActivity()).get(GameViewModel.class);
    gameViewModel.init();
return view;
}

fragment_game.xml

<?xml version="1.0" encoding="utf-8"?>
<layout 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"

tools:context=".view.GameFragment">

<data>
     <import type="android.support.v4.app.Fragment"/>
    <import type="android.view.View"/>

    <variable
        name="gameViewModel"
        type="harkor.addus.viewmodel.GameViewModel" />
</data>


<android.support.constraint.ConstraintLayout
   (...)>

    <TextView
        (...)>

    <android.support.constraint.ConstraintLayout
        (...)>

        <ImageView
            android:id="@+id/image_puzzle11"
            android:src="@android:color/holo_green_dark"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_marginEnd="1dp"
            android:layout_marginRight="1dp"
            android:onClick="@{() -> gameViewModel.onClickItem(1,1)}"
            app:load_image="@{0}"
            app:layout_constraintBottom_toTopOf="@+id/image_puzzle21"
            app:layout_constraintDimensionRatio="w,1:1"
            app:layout_constraintEnd_toStartOf="@+id/image_puzzle12"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
(...)

load_image is working, but onClick do nothing... No error in compilation, no crash when button is clicking on device, no result in console...

like image 863
Harkor Avatar asked Jul 19 '18 09:07

Harkor


1 Answers

The easiest way is to set the view model and calling the proper method in the View's onClick from the layout: Your xml:

<data>
    <variable
        name="viewModel"
        type="co.package.MyViewModel" />
</data>

<com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/my_id"
                        android:layout_width="@dimen/full_width"
                        android:layout_height="wrap_content"
                        android:onClick="@{() -> viewModel.doSomething()}" />

But if for any reason you need to call a method from your fragment or activity, the best suggestion is to create an interface to handle the method, implement the method and set it to the layout as follows: Your xml

<data>
    <variable
        name="myHandlers"
        type="co.package.MyHandlersListener" />
</data>

<com.google.android.material.textfield.TextInputEditText
                        android:id="@+id/my_id"
                        android:layout_width="@dimen/full_width"
                        android:layout_height="wrap_content"
                        android:onClick="@{() -> myHandlers.doSomething()}" />

And within your Fragment or Activity you create the interface and then implement it: Your activity/fragment:

/* My Handler Methods */

interface MyHandlersListener {
    fun doSomething()
}

Then implement the listener, taking into consideration that the method something is defined and implemented within your activity/fragment class:

private val myHandlersListener: MyHandlersListener = object : MyHandlersListener {
    override fun doSomething() {
        something()
    }
}

And using databinding, you can set the handler into your layout class (this can be done within the onCreate or onCreateView method depending if you are using and activity or fragment respectively):

myBinding.myHandlers = myHandlersListener

In this way it works perfectly and you follow the guide given by Android's team: https://developer.android.com/topic/libraries/data-binding/expressions#method_references

like image 140
Carlos Daniel Avatar answered Sep 20 '22 11:09

Carlos Daniel