activity_second.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">
<data>
<variable
name="temp"
type="com.vogella.Android.databinding.TemperatureData" />
<variable
name="presenter"
type="com.vogella.Android.databinding.MainActivityPresenter"/>
</data>
<Android.support.v7.widget.RecyclerView
Android:id="@+id/my_recycler_view"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
Android:scrollbars="vertical" />
</layout>
rowlayout.xml
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android">
<data>
<variable
name="obj"
type="com.vogella.Android.databinding.TemperatureData"
/>
</data>
<RelativeLayout
Android:layout_width="fill_parent"
Android:layout_height="?android:attr/listPreferredItemHeight"
Android:padding="6dip"
>
<ImageView
Android:id="@+id/icon"
Android:layout_width="wrap_content"
Android:layout_height="fill_parent"
Android:layout_alignParentBottom="true"
Android:layout_alignParentTop="true"
Android:layout_marginRight="6dip"
Android:contentDescription="TODO"
Android:src="@drawable/ic_listentry"
/>
<TextView
Android:id="@+id/secondLine"
Android:layout_width="fill_parent"
Android:layout_height="26dip"
Android:layout_alignParentBottom="true"
Android:layout_alignParentRight="true"
Android:layout_toRightOf="@id/icon"
Android:ellipsize="Marquee"
Android:text="@{obj.location}"
Android:textSize="12sp"
Android:maxLines="1"
/>
<TextView
Android:id="@+id/firstLine"
Android:layout_width="fill_parent"
Android:layout_height="wrap_content"
Android:layout_above="@id/secondLine"
Android:layout_alignParentRight="true"
Android:layout_alignParentTop="true"
Android:layout_alignWithParentIfMissing="true"
Android:layout_toRightOf="@id/icon"
Android:gravity="center_vertical"
Android:text="@{obj.celsius}"
Android:textSize="16sp"
/>
</RelativeLayout>
</layout>
MyAdapter.Java
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {
private List<TemperatureData> data;
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class MyViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
private final ViewDataBinding binding;
public MyViewHolder(ViewDataBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
public void bind(Object obj) {
binding.setVariable(BR.obj,obj);
binding.executePendingBindings();
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<TemperatureData> myDataset) {
data = myDataset;
}
// Create new views (invoked by the layout manager)
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.rowlayout, parent, false);
// set the view's size, margins, paddings and layout parameters
return new MyViewHolder(binding);
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
final TemperatureData temperatureData = data.get(position);
holder.bind(temperatureData);
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return data.size();
}
}
MyAdapter.Java
public class MyAdapter extends MyBaseAdapter {
List<TemperatureData> data;
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<TemperatureData> myDataset) {
data = myDataset;
}
@Override
public Object getDataAtPosition(int position) {
return data.get(position);
}
@Override
public int getLayoutIdForType(int viewType) {
return R.layout.rowlayout;
}
@Override
public int getItemCount() {
return data.size();
}
}
すでに解決策を見つけているかどうかはわかりませんが、私はそれを簡単に行うことができました。
1)onCreateViewHolder
メソッドを次のように変更します。
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
ViewDataBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.rowlayout, parent, false);
MainActivityPresenter presenter = new MainActivityPresenter(this, parent.getContext());
binding.setVariable(BR.presenter,presenter);
// set the view's size, margins, paddings and layout parameters
return new MyViewHolder(binding);
}
2)MyAdapterがMainActivityContract.View
を実装するようにするので、最終的には次のようになります。
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> implements MainActivityContract.View
3)MyAdapter
内に必要なメソッドを実装します;例えば:
@Override
public void showData(TemperatureData data) {
String clickedItemCelsius = data.getCelsius();
}
4)行レイアウトファイルにPresenter変数を追加します。
<variable
name="presenter"
type="com.mvvm.ViewModels.MainActivityPresenter"/>
5)最後に、RelativeLayoutでonClick
イベントをフックします。
<RelativeLayout
Android:layout_width="fill_parent"
Android:layout_height="?android:attr/listPreferredItemHeight"
Android:padding="6dip"
Android:onClick="@{() -> presenter.onShowData(obj)}"
>
それが役に立てば幸い!
ちょっと私は約一週間前にその記事を読んで、同じ問題を抱えていました!この記事では、アクションの処理方法についてはほとんど言及していませんが、その方法については documentation があります。つまり、handler
が必要になります。
このハンドラーはxmlで定義されています
<data>
...
<variable name="handlers" type="com.example.MyHandlers"/>
...
</data>
使用例
<TextView Android:layout_width="wrap_content"
Android:layout_height="wrap_content"
Android:text="@{user.firstName}"
Android:onClick="@{handlers::onClickFriend}"/>
MyHandlers.Javaは次のようになります
public class MyHandlers {
public void onClickFriend(View view) { ... }
}
MyAdapter.Java
に1行追加して変更します
public class MyViewHolder extends RecyclerView.ViewHolder {
public void bind(Object obj) {
binding.setVariable(BR.obj,obj);
binding.executePendingBindings();
binding.setHandlers(new MyHandlers());
}
私はこのコードをテストしていませんが、これが機能しない場合は、アダプターを共有できます。
このように、データバインディングでアイテムクリックを使用できます。
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomView> {
List<NewsModel> newsList;
private LayoutInflater layoutInflater;
public CustomAdapter(List<NewsModel> newsList)
{
this.newsList = newsList;
}
@Override
public CustomView onCreateViewHolder(final ViewGroup parent, final int viewType) {
if(layoutInflater == null)
{
layoutInflater = LayoutInflater.from(parent.getContext());
}
final NewsBinding newsBinding = NewsBinding.inflate(layoutInflater,parent,false);
newsBinding.setPresenter(new ClickListener() {
@Override
public void onclickListener() {
Log.d("click me ","click me "+newsBinding.getNewsview().Title);
Toast.makeText(parent.getContext(),""+newsBinding.getNewsview().Title,Toast.LENGTH_LONG).show();
}
});
// View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.innerlayout,parent,false);
return new CustomView(newsBinding);
}
@Override
public void onBindViewHolder(CustomView holder, int position) {
// News news = newsList.get(position);
// holder.title.setText(news.getTitle());
// holder.desc.setText(news.getDesc());
NewsModel newsModel = newsList.get(position);
holder.bind(newsModel);
}
@Override
public int getItemCount() {
return newsList.size();
}
public class CustomView extends RecyclerView.ViewHolder {
private NewsBinding newsBinding;
// TextView title, desc;
public CustomView(NewsBinding newsBinding) {
super(newsBinding.getRoot());
this.newsBinding = newsBinding;
//title = (TextView)itemView.findViewById(R.id.titleval);
//desc =(TextView)itemView.findViewById(R.id.descval);
}
public void bind(NewsModel newsModel)
{
this.newsBinding.setNewsview(newsModel);
}
public NewsBinding getNewsBinding()
{
return newsBinding;
}
}
}
完全なプロジェクトは https://github.com/Vishulucky/DataBinding-MVVM.git
おそらく最も一般的な解決策は、行レイアウトのルートビューにクリックリスナーを配置し、ビューモデルのメソッドを呼び出すことです。たとえば、rowlayout.xmlの場合:
...
<RelativeLayout
Android:onClick="@{() -> obj.performClickAction()}"
....
リサイクラビューで使用されるviewModel
class UserViewModel (val name: String?, val onClick: () -> Unit)
user_item.xmlのレイアウト
<layout xmlns:Android="http://schemas.Android.com/apk/res/Android"
xmlns:tools="http://schemas.Android.com/tools">
<data>
<variable
name="model"
type="...model.UserViewModel" />
</data>
<TextView
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:clickable="true"
Android:focusable="true"
Android:onClick="@{()->model.onClick.invoke()}"
Android:text="@{model.name}" />
<merge>
プレゼンターまたはmodelViewまたは他の場所でのモデルの作成
fun loadData() {
// ..
val user = UserViewModel("name") { handleUserEvent() }
.. //
}
fun handleUserEvent() {
// TODO handle on click
}