I would like to create a gridview of movie posters images with using bindings.
My viewmodel looks like that:
public class PopularMoviesViewModel extends BaseObservable {
Movie movie;
Context context;
MovieServiceComponent movieServiceComponent = DaggerMovieServiceComponent.builder()
.contextModule(new ContextModule(context))
.build();
Picasso getPicasso = movieServiceComponent.getPicasso();
public PopularMoviesViewModel(Movie movie, Context context) {
this.movie = movie;
this.context = context;
}
#Bindable
public String getImageUrl(){
return movie.posterPath();
}
#Bindable
public String getTitle(){
return movie.originalTitle();
}
#BindingAdapter({"imageUrl"})
public void setImageUrl(ImageView view, String poserPath){
getPicasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+ poserPath).into(view);
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data class="PopularMoviesBinding">
<variable
name="pmvm"
type="com.hartyandi.oviesm.modelviews.PopularMoviesViewModel"></variable>
</data>
<LinearLayout
android:id="#+id/row"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FFFFFF"
android:paddingBottom="0dp"
android:paddingTop="5dp"
android:paddingRight="2.5dp"
android:paddingLeft="5dp"
android:orientation="vertical">
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
android:id="#+id/popular_movies_grid_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="0dp"
android:adjustViewBounds="true"
android:elevation="20dp">
</ImageView>
<TextView
android:id="#+id/popular_movies_grid_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#{pmvm.title}"
android:textColor="#000000"
android:textSize="12sp"
android:background="#FFFFFF"
>
</TextView>
</LinearLayout>
</layout>
Adapter:
public class PopularMoviesAdapter extends RecyclerView.Adapter<PopularMoviesAdapter.BindingHolder> {
private List<Movie> movies;
private Context context;
public PopularMoviesAdapter(List<Movie> movies, Context context) {
this.movies = movies;
this.context = context;
}
public void add(Movie movie){
movies.add(movie);
}
#Override
public BindingHolder onCreateViewHolder(ViewGroup parent, int viewType) {
PopularMoviesBinding popularMoviesBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.popular_movies_gridview_row, parent,false);
return new BindingHolder(popularMoviesBinding);
}
#Override
public void onBindViewHolder(PopularMoviesAdapter.BindingHolder holder, int position) {
PopularMoviesBinding popularMoviesBinding = holder.popularMoviesBinding;
popularMoviesBinding.setPmvm(new PopularMoviesViewModel(movies.get(position), context));
}
#Override
public int getItemCount() {
return movies.size();
}
public class BindingHolder extends RecyclerView.ViewHolder{
private PopularMoviesBinding popularMoviesBinding;
public BindingHolder(PopularMoviesBinding popularMoviesBinding) {
super(popularMoviesBinding.getRoot());
this.popularMoviesBinding = popularMoviesBinding;
}
}
}
I get the following error:
java.lang.IllegalStateException: Required DataBindingComponent is null in class PopularMoviesBinding.A BindingAdapter in modelviews.PopularMoviesViewModel is not static and requires an object to use, retrieved from the DataBindingComponent.
I tried to change my implementation just like this stackoverflow post suggest and I got the same error message.
I also used the following code as example.
Could someone explain what the problem with the code, and how to solve it?
You probably didn't intend to use an instance method for the BindingAdapter.
If you do, you must provide a DataBindingComponent so that the generated Binding class knows which instance to use.
You have two options -- provide a DataBindingComponent or just pass the required context as an attribute to a static binding adapter method. The second is a bit easier to understand, so I'll start with that:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android">
<data class="PopularMoviesBinding">
<variable name="pmvm"
type="com.hartyandi.oviesm.modelviews.PopularMoviesViewModel"/>
<variable name="picasso" type="com.whatever.Picasso"/>
</data>
<!-- ... -->
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
app:picasso="#{picasso}"
... />
</ImageView>
</layout>
Then in your BindingAdapter:
#BindingAdapter({"imageUrl", "picasso"})
public static void setImageUrl(ImageView view, String poserPath, Picasso picasso){
picasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+ poserPath).into(view);
}
Note that setImageUrl is now static.
Alternatively, since your the Picasso instance is also on the ViewModel, you can just pass the instance by adding a getter for the picasso:
<ImageView
app:imageUrl="#{pmvm.imageUrl}"
app:picasso="#{pmvm.picasso}"
... />
and the method in your ViewModel:
public Picasso getPicasso() { return this.getPicasso; }
The other way means that you implement a DataBindingComponent. When you create an instance BindingAdapter method, the generated interface will have a getter for your class. You'll need to create a class to implement that interface:
public class MyDataBindingComponent implements DataBindingComponent {
public PopularMoviesViewModel getPopularMoviesViewModel() {
return whateverIDoToCreateOrGetThisBindingAdapterInstance();
}
}
Then you pass the instance when you inflate or bind:
PopularMoviesBinding popularMoviesBinding =
DataBindingUtil.inflate(LayoutInflater.from(parent.getContext()),
R.layout.popular_movies_gridview_row, parent,false,
new MyDataBindingComponent());
just make the setImageUrl() method static to be like this code
#BindingAdapter({"imageUrl"})
public void setImageUrl(ImageView view, String poserPath){
getPicasso.with(view.getContext()).load("http://image.tmdb.org/t/p/w185"+
poserPath).into(view);
}
Related
Can someone suggest me the best way to call a fragment function from the RecyclerView without causing any memmory leaks
My fragment code is given below
<androidx.constraintlayout.widget.ConstraintLayout
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"
tools:context=".ui.auth.AuthActivity">
<com.google.android.exoplayer2.ui.PlayerView
android:id="#+id/videoID"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/black"
app:resize_mode="fill"
app:controller_layout_id="#layout/player_control_view"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/materialList"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/videoID">
</androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout>
My recycler view layout is
<androidx.constraintlayout.widget.ConstraintLayout
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="wrap_content"
android:orientation="vertical"
android:padding="#dimen/_10sdp">
<androidx.cardview.widget.CardView
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:cardBackgroundColor="#color/circle_color_light"
app:layout_constraintVertical_bias="0.6">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
/>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Please ignore any error on the above layouts since my issue lies on java code
My fragment code is given below
public class MaterialFragment extends DaggerFragment implements View.OnClickListener {
SimpleExoPlayer player;
PlayerView playerView;
#Inject
MaterialAdapter adapter;
#Inject
ViewModelProviderFactory providerFactory;
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
makeVideo("https://samplevideo.com/test.mp4");
materialList = view.findViewById(R.id.materialList);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(),3,GridLayoutManager.VERTICAL,false);
materialList.setLayoutManager(gridLayoutManager);
materialList.setAdapter(adapter);
// The above code succesfully load the grid view using recycler adapter(Code for adapter is given below)
}
public void makeVideo(){
// Video loading code goes here : Loads video on findViewById(R.id.videoID)
}
}
Finally my Recycler Adapter view
public class MaterialAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "MaterialAdapter";
private List<Material> materials = new ArrayList<>();
private Context context;
public MaterialAdapter(){
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.material_grid_layout, parent, false);
PlayerView playerView = ((Activity)parent.getContext()).getWindow().getDecorView().findViewById(R.id.matVideo);
SimpleExoPlayer player = new SimpleExoPlayer.Builder(((Activity)parent.getContext()).getApplicationContext()).build();
context = parent.getContext();
return new MaterialAdapter.MaterialViewHolder(view,parent.getContext(),playerView,player);
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
((MaterialAdapter.MaterialViewHolder)holder).bind(materials.get(position),context);
}
#Override
public int getItemCount() {
return materials.size();
}
public void setMaterials(List<Material> materials){
this.materials = materials;
notifyDataSetChanged();
}
public class MaterialViewHolder extends RecyclerView.ViewHolder {
TextView name,letter;
public Context cxt;
private SimpleExoPlayer player;
private PlayerView playerView;
public MaterialViewHolder(#NonNull View itemView, Context cxt, final PlayerView playerView, SimpleExoPlayer player) {
super(itemView);
this.cxt = cxt;
this.playerView = playerView;
this.player = player;
name = itemView.findViewById(R.id.name);
clayout = (ConstraintLayout) itemView.findViewById(R.id.card_layout);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// I need to change the video of the fragment on click of each block.
//The below code will work by implementing full makevideo function on this file
//But I need the bes method without repeting this function and call the methods of he fragment by passing video url or setting view contents of the outer fragment
//makeVideo("https://samplevideo.com/test.mp4"); // Not think this is he best solution as I need fullscreen function also.
// How to trigger button click of fragment, eg full screen
}
});
}
public void bind(Material material, Context context){
name.setText(material.getName());
}
}
}
Adapter is injected using module as given below
#Provides
static MaterialAdapter provideMaterialAdapter(){
return new MaterialAdapter();
}
After referring, I got some suggestion by using my own interface as a bridge between adapter and fragment , But It didn't work may be my dagger is causing some injection error,
Can someone give me a best solution to get rid of this issue
Screenshot of my screen is given below
Use this adapter = new MaterialAdapter(); in your fragment rather than injecting it. Just remove the #Inject annotation and add the above adapter creation statement in onViewCreated of your fragment. By this way your get more control on your adapter creation and you can pass an interface through the constructor.
I'm beginner to data binding.I'm trying to get spinner items from my view model using data binding and set the values in android:entries ,But the thing is my spinner didn't showing items.
Here is my layout
<layout>
<data>
<import type="com.saddan.sanidadvegetalsyscomed.viewmodel.TableDataViewModel"/>
<variable
name="model"
type="TableDataViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="#ffffff"
android:layout_margin="20dp"
android:padding="5dp"
tools:context=".Fragment.First_Form_Fragment">
<Spinner
style="#android:style/Widget.TextView.SpinnerItem"
android:id="#+id/ext_tipo_inspection"
android:layout_width="320dp"
android:layout_height="#dimen/EditTextFieldHeight"
android:entries="#{model.spinerInspecion}"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Here is my view model class
public class TableDataViewModel extends AndroidViewModel
{
private String TAG=getClass().getSimpleName();
private UserAccessToken userAccessToken;
private SanidadDAO sanidadDAO;
private Context context;
private LiveData<List<String>> spinnerItem;
private LiveData<List<String>> spinerInspecion;
public TableDataViewModel(#NonNull Application application)
{
super(application);
userAccessToken=new UserAccessToken(application);
SanidadVegetalDatabase database = SanidadVegetalDatabase.getDatabase(application);
sanidadDAO = database.getDao();
context=application;
spinerInspecion=getmCommonData("tipoinspeccion");
if(spinerInspecion!=null)
{
Log.d(TAG, "TableDataViewModel: yrs");
}
}
public LiveData<List<String>> getmCommonData(String queryType)
{
spinnerItem=sanidadDAO.getType(queryType);
//Toast.makeText(context, ""+mCommonData, Toast.LENGTH_SHORT).show();
return spinnerItem;
}
public LiveData<List<String>> getSpinerInspecion()
{
return spinerInspecion;
}
public void setSpinerInspecion(LiveData<List<String>> spinerInspecion)
{
this.spinerInspecion = spinerInspecion;
}
#Override
protected void onCleared()
{
super.onCleared();
}
}
and here is my Fragment's onViewCreated method where I initialize the binding
tableDataViewModel= new ViewModelProvider(getActivityNonNull()).get(TableDataViewModel.class);
binding.setModel(tableDataViewModel);
Problem here is you are not setting value to spinerInspecion you are assigning it a new LiveData. This is why observer never get called on the instance. Modify your method as:-
public List<String> getmCommonData(String queryType) {
spinnerItem=sanidadDAO.getType(queryType);
return spinnerItem;
}
and then set value as :-
spinerInspecion.setValue(getmCommonData("tipoinspeccion"));
Trying to run method in a layout file from my view model but, I keep getting error: cannot find symbol class ViewModels from my layout file. The layout file is a fragment. I tried invalidating the cache and resyncing but, it did not help. Do i need to add anything to the fragment itself? I seen people use data binding to launch the fragment but, I've read its optional.
Update: Took out OnClick method to test and it is still throwing error. I guess the problem is with my deceleration but, idk why. When i am editing the layout the path shows up when I type the view model name in.
Update2: Tried setting type in variable equal to path of activity that launches fragment for testing and it built just fine. There must be a way to add an import that is not my activity.
Layout file
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="viewTest"
type="rangers.socmanv2.ViewModels.BattleRhythmViewModel" />
</data>
<android.support.constraint.ConstraintLayout 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:id="#+id/battleRhythmMenu"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".Fragments.BattleRhythmFrag">
<Button
android:id="#+id/newBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="88dp"
android:text="New Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<Button
android:id="#+id/editBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="50dp"
android:text="Edit Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/newBattle" />
<Button
android:id="#+id/deleteBattle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="76dp"
android:layout_marginLeft="76dp"
android:layout_marginTop="50dp"
android:text="Delete Battle Rhythm"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/editBattle" />
</android.support.constraint.ConstraintLayout>
</layout>
Fragment
public class BattleRhythmFrag extends Fragment {
private BattleRhythmViewModel mViewModel;
private View view;
private Button test;
public static BattleRhythmFrag newInstance() {
return new BattleRhythmFrag();
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.battle_rhythm_fragment, container, false);
mViewModel = new BattleRhythmViewModel();
return view;
}
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mViewModel = ViewModelProviders.of(this).get(BattleRhythmViewModel.class);
// TODO: Use the ViewModel
}
}
View model
public class BattleRhythmViewModel extends ViewModel {
public void launchNewFragment(FragmentManager fragM)
{
Log.d("viewmodel","hitting launchNewFrag");
HomeFrag test = new HomeFrag();
fragM.beginTransaction().replace(R.id.homeContent,test,"launched"+test);
}
public void test()
{Log.d("viewmodel","hitting test");
}
}
Your error is in viewModel constructor.
you must add a default constructor beacuse you don't added any factory ViewModelProvider.Factory but your BattleRhythmViewModel dosen't have any default constructor.
ANSWER 1:
public class BattleRhythmViewModel extends ViewModel {
public void launchNewFragment(){
}
public void test()
{Log.d("viewmodel","hitting test");
}
}
}
ANSWER 2: better than answer 1 beacuse you don't need add default and can use your fragment in model
public class Factory implements ViewModelProvider.Factory {
private FragmentManager fragM;
public Factory(FragmentManager fragM) {
this.fragM= fragM;
}
#NonNull
#Override
public <T extends ViewModel> T create(#NonNull Class<T> modelClass) {
if (modelClass.isAssignableFrom(BattleRhythmViewModel.class)) {
return (T) new BattleRhythmViewModel(fragM);
}
throw new IllegalArgumentException("Unknown ViewModel class");
}
}
change your viewmodel creator line to
Factory factory = new Factory(this)
mViewModel = ViewModelProviders.of(this,factory).get(BattleRhythmViewModel.class);
I use data binding.
Here parent adapter:
public abstract class PreviewSortAdapter extends RealmRecyclerViewAdapter {
protected Context context;
#BindingAdapter("imageUrl")
public static void loadImage(ImageView view, String imageUrl) {
Glide.with(view.getContext()).load(imageUrl)
.apply(RequestOptions.bitmapTransform(
new GlideRoundedCornersTransformation(view.getContext(), (int) AndroidUtil.dpToPx(view.getContext(),
view.getContext().getResources().getInteger(R.integer.image_rounded_corner_radius_dp)),
0, GlideRoundedCornersTransformation.CornerType.TOP)))
.into(view);
}
}
Here my child adapter:
public class MapListSortAdapter extends PreviewSortAdapter {
public MapListSortAdapter(Context context, OrderedRealmCollection<Merchant> data) {
super(context, data, true);
}
#BindingAdapter("imageUrl")
public static void loadImage(ImageView view, String imageUrl) {
Debug.d(TAG, "loadImage: ");
Glide.with(view.getContext()).load(imageUrl)
.into(view);
}
#Override
protected int getLayoutForPosition(int position) {
return R.layout.map_list_item;
}
}
As you can see in my child adapter I override method loadImage(). I want to call method loadImage() from child adapter.
Herer map_list_item.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">
<data>
<variable
name="item"
type="com.myproject.android.customer.api.model.Merchant" />
</data>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/white"
android:minHeight="90dp">
<ImageView
android:id="#+id/imageViewPhoto"
android:layout_width="90dp"
android:layout_height="90dp"
android:scaleType="centerCrop"
app:imageUrl="#{item.preview.formats.reference.url}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
</layout>
As you can see I use custom tag app:imageUrl to call method loadImage().
The problem is that method is call but it call of parent adapter - PreviewSortAdapter.loadImage().
But I need to call this method in child adapter: MapListSortAdapter.loadImage().
Methods anotated with the static modifier doesn't have hieritance. Just remove the static modifier and it should work
I'm trying to handle clickable TextView on data binding method, but i get this error:
Cannot find the setter for attribute 'android:clickable' with parameter type lambda on android.widget.TextView
my TextView widgets must be clickable and i show simple Toast, how can i set text to that such as android:text="#string/my_text and can be clickable?
ActivityRegister:
public class ActivityRegister extends BaseActivities
implements ActivityRegisterContract.View{
private ActivityRegisterBinding binding;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_register);
ActivityRegisterPresenter mainActivityPresenter = new ActivityRegisterPresenter(this);
ActivityRegisterData viewModel = new ActivityRegisterData();
viewModel.setReadContactPermission(Utils.getString(R.string.get_read_contact_permission, context));
binding.setPresenter(mainActivityPresenter);
}
#Override
public void getReadContactsPermission() {
Utils.toast("CLICKED", context);
}
}
presenter:
public class ActivityRegisterPresenter {
private ActivityRegisterContract.View view;
public ActivityRegisterPresenter(ActivityRegisterContract.View mView) {
view = mView;
}
public void getReadContactsPermission(){
view.getReadContactsPermission();
}
}
ActivityRegisterContract
public interface ActivityRegisterContract {
public interface View {
void getReadContactsPermission();
}
}
and then ActivityRegisterData
public class ActivityRegisterData extends BaseObservable {
private String readContactPermission;
public ActivityRegisterData() {
}
#Bindable
public String getReadContactPermission() {
return readContactPermission;
}
public void setReadContactPermission(String readContactPermission) {
this.readContactPermission = readContactPermission;
notifyPropertyChanged(BR.readContactPermission);
}
}
my layout:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:slidingLayer="http://schemas.android.com/apk/res-auto">
<data>
<variable
name="viewModel"
type="com.example.Ui.Register.Model.ActivityRegisterData"/>
<variable
name="presenter"
type="com.example.Ui.Register.Presenter.ActivityRegisterPresenter"/>
</data>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#d1d1d1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<TextView
android:id="#+id/permission_for_read_contacts"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="#string/permission_for_read_contacts"
android:textColor="#color/white"/>
<TextView
android:layout_width="match_parent"
android:layout_height="#dimen/default_textview_height"
android:background="#drawable/selector_blue_buttons"
android:clickable="#{()->presenter.getReadContactsPermission()}"
android:text="#{viewModel.readContactPermission}"
android:textColor="#color/white"/>
</LinearLayout>
</LinearLayout>
</FrameLayout>
</layout>
problem is for this line on layout:
<TextView
android:layout_width="match_parent"
android:layout_height="#dimen/default_textview_height"
android:background="#drawable/selector_blue_buttons"
android:clickable="#{()->presenter.getReadContactsPermission()}"
android:text="#{viewModel.readContactPermission}"
android:textColor="#color/white"/>
I dont know about your code.but to make a clickable text, you just have to add listener to it or you can define onClick attribute in Xml and define that method in Activity to handle click event.
Use this:
android:onclick="doSomething"
And in activity
public void doSomething(View v){
//Write your code here
}