数据绑定Android回收器视图
我使用android数据绑定,下面是我用来设置变量的类数据绑定Android回收器视图,android,android-databinding,Android,Android Databinding,我使用android数据绑定,下面是我用来设置变量的类 public class DayTemp extends BaseObservable implements Serializable { @SerializedName("dt") long date; @SerializedName("pressure") double pressure; @SerializedName("humidity") long humidity; @S
public class DayTemp extends BaseObservable implements Serializable {
@SerializedName("dt")
long date;
@SerializedName("pressure")
double pressure;
@SerializedName("humidity")
long humidity;
@SerializedName("temp")
Temp temp;
@SerializedName("weather")
ArrayList<Weather> weathers;
@SerializedName("speed")
double speed;
@SerializedName("deg")
double deg;
@SerializedName("clouds")
double clouds;
@Bindable
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
notifyPropertyChanged(BR.date);
}
@Bindable
public double getPressure() {
return pressure;
}
public void setPressure(double pressure) {
this.pressure = pressure;
notifyPropertyChanged(BR.pressure);
}
@Bindable
public long getHumidity() {
return humidity;
}
public void setHumidity(long humidity) {
this.humidity = humidity;
notifyPropertyChanged(BR.humidity);
}
@Bindable
public Temp getTemp() {
return temp;
}
public void setTemp(Temp temp) {
this.temp = temp;
notifyPropertyChanged(BR.temp);
}
@Bindable
public ArrayList<Weather> getWeathers() {
return weathers;
}
public void setWeathers(ArrayList<Weather> weathers) {
this.weathers = weathers;
notifyPropertyChanged(BR.weathers);
}
@Bindable
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
notifyPropertyChanged(BR.speed);
}
@Bindable
public double getDeg() {
return deg;
}
public void setDeg(double deg) {
this.deg = deg;
notifyPropertyChanged(BR.deg);
}
@Bindable
public double getClouds() {
return clouds;
}
public void setClouds(double clouds) {
this.clouds = clouds;
notifyPropertyChanged(BR.clouds);
}
}
布局文件:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
>
<data>
<import type="com.weatherappforleftshift.currentlocation.DateUtils"/>
<variable
name="daytemp" type="com.weatherappforleftshift.currentlocation.model.DayTemp"/>
</data>
<TextView
android:id="@+id/weather_status"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
android:text="@{HOW TO SET TEXT HERE FROM weathers list}"
android:layout_height="wrap_content" />
</layout>
我想将天气类的图标和描述设置到我的recyclerview
如何在项目布局中实现这一点???您可以查看这个github项目 我已经为recyclerview处理了数据绑定 更具体地说,以下2个文件将是感兴趣的 在虚拟机中添加:
@Bindable
public String getWeathersText() {
StringBuilder builder = new StringBuilder();
for (int i = 0; i < weathers.size(); i++) {
builder.append(weathers.get(i).getText);
}
return builder.toString();
}
@Bindable
公共字符串getWeathersText(){
StringBuilder=新的StringBuilder();
对于(int i=0;i
在布局xml中:
<TextView
android:id="@+id/weather_status"
android:layout_width="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginStart="10dp"
app:weathersText="@{daytemp.weathersText}"
android:layout_height="wrap_content" />
我没有检查它,但我认为它应该有帮助…首先,您需要在布局xml中创建“Weather”类的变量/实例
<variable
name="weatherData" type="<packageName>.Weather"/>
有很多方法可以剥这只猫的皮。但是您特别提到绑定,那么让我们用正确的方法来做:) 您将需要一些东西,但不要担心,其中大部分是一次性锅炉板,您可以在每个recyclerview上反复使用。这就是它的美妙之处 1) 布局中的RecyclerView 2) RecyclerView的通用绑定适配器 3) 用于转换类型和设置的JMVStatic适配器 4) 用于与RecyclerView适配器通信的接口 差不多就这么多了,让我们进入代码。 顺便说一句,如果你不想理解它,你几乎可以复制和粘贴,虽然它可以做更多的事情,然后你需要。还有其他处理单击事件的方法。您可以将它们嵌套到行布局文件中,而不会产生任何问题 步骤1: 接口类
interface IBindingRecyclerView<T> {
/////////////////////////////////////////////////////////////////
// EXTERNAL METHODS
/////////////////////////////////////////////////////////////////
fun getRowLayoutResourceId(): Int
fun getBindingModelId(): Int
fun getActionButtonResourceId(): Int
fun onItemClick(model: T, position: Int)
fun onItemLongClick(model: T, position: Int)
fun onActionItemClick(model: T, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder)
}
}
可重复使用的物品包括:
- 接口
- jvm静态适配器
- 回收器视图适配器
- 垂直装饰器
快乐编码。希望这有帮助。@pskink我会处理好的。。。thnx@tynn仅要求数据绑定,无法从类访问arraylist如何在此处从weathers列表设置文本是无效的信息。至少提供代码,说明如何将
天气
列表转换为字符序列
。一个实用程序方法或其他东西…天气列表是带有文本和图标的自定义arraylist,它位于DayTemp类中,这是我的recyclerview项的根类。我尝试像这样访问该列表@{DayTemp.weathers.get(),但不能访问天气中的精确元素。考虑使用它。首先输入THNX,但我想访问它。现在我正在做这个@ { TayTim.WeeSt.GET()},但是我想得到与Weikes相关的数据,WeeStices是一个ARARYLIST。我通过使用两个数据变量THNX来解决它。
bindind.setWeatherData(whetherList.get(position));
interface IBindingRecyclerView<T> {
/////////////////////////////////////////////////////////////////
// EXTERNAL METHODS
/////////////////////////////////////////////////////////////////
fun getRowLayoutResourceId(): Int
fun getBindingModelId(): Int
fun getActionButtonResourceId(): Int
fun onItemClick(model: T, position: Int)
fun onItemLongClick(model: T, position: Int)
fun onActionItemClick(model: T, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder)
}
object BindingAdapterMethods {
/////////////////////////////////////////////////////////////////
// MEMBERS
/////////////////////////////////////////////////////////////////
private var TAG: String = SSGlobals.SEARCH_STRING + "BindingAdapterMethods"
/////////////////////////////////////////////////////////////////
// METHODS
/////////////////////////////////////////////////////////////////
/**
* This makes sure that the interface and observable list is set in the recyclerView's adapter. If the adapter is null,
* then a new one is created.
* @param view
* @param iBindingRecyclerView
* @param list
*/
@JvmStatic
@BindingAdapter(value = ["bindRcvInterface", "bindRcvList", "bindRcvPlusInterface"], requireAll = false)
fun setBindingRecyclerViewProperties(view: RecyclerView, iBindingRecyclerView: IBindingRecyclerView<*>, list: ObservableArrayList<*>?, iBindingRecyclerViewPlus: IBindingRecyclerViewPlus<*>? = null) {
if (view.adapter == null) {
val layoutManager = LinearLayoutManager(view.context)
view.layoutManager = layoutManager
view.invalidateItemDecorations()
view.addItemDecoration(VerticalItemDecoration(0))
view.adapter = BindingRecyclerViewAdapter<Any?>()
}
val adapter = view.adapter as BindingRecyclerViewAdapter<*>
adapter.setIBindingRecyclerView(iBindingRecyclerView, iBindingRecyclerViewPlus)
if(list != null) {
adapter.setList(list)
}
}
}
class MyListFragment : BaseFragment(), IBindingRecyclerView<YourListModelType> {
/////////////////////////////////////////////////////////////////
// MEMBERS
/////////////////////////////////////////////////////////////////
private lateinit var mBinding: FragmentYourItemListBinding
private var mYourItemModelList : ObservableArrayList<YourListModelType> = ObservableArrayList()
/////////////////////////////////////////////////////////////////
// LIFE CYCLE OVERRIDES
/////////////////////////////////////////////////////////////////
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_your_item_list, container, false)
mBinding.fragment = this
mBinding.iBindingRecyclerView = this
return mBinding.root
}
override fun onResume() {
super.onResume()
fillYourListOfItems()
}
/////////////////////////////////////////////////////////////////
// PROPERTIES
/////////////////////////////////////////////////////////////////
fun getYourListItemModelList() : ObservableArrayList<YourListItemModelType> {
return mYourItemModelList
}
/////////////////////////////////////////////////////////////////
// IBINDINGRECYCLERVIEW OVERRIDES
/////////////////////////////////////////////////////////////////
override fun getRowLayoutResourceId(): Int {
return R.layout.row_your_layout_file
}
override fun getBindingModelId(): Int {
return BR.YourListModelType //defined in the xml coming up next
}
override fun getActionButtonResourceId(): Int {
return -1 //if you aren't using, just return -1 or remove from interface
}
override fun onItemClick(model: YourListModelType, position: Int) {
//handle the click of your item, launch a detail activity, whatever you need
}
override fun onItemLongClick(model: YourListModelType, position: Int) {
//same as above, but if not using, you can remove from interface
}
override fun onActionItemClick(model: YourListModelType, position: Int, holder: BindingRecyclerViewAdapter.BindingHolder) {
//if not using, you can remove from interface
}
}
<data>
<variable name="fragment" type="com.yourpath.fragments.MyListFragment" />
<variable name="iBindingRecyclerView" type="com.yourpath.interfaces.IBindingRecyclerView"/>
</data>
class BindingRecyclerViewAdapter<T> : RecyclerView.Adapter<BindingRecyclerViewAdapter.BindingHolder>(), View.OnClickListener, View.OnLongClickListener {
/////////////////////////////////////////////////////////////////
// MEMBERS
/////////////////////////////////////////////////////////////////
private val MODEL_TAG = -124
private val MODEL_POSITION_TAG = -125
private var mRowLayoutResourceId: Int = 0
private var mBindingModelId: Int = 0
private var mActionButtonId: Int = 0
private var mHasActionButton: Boolean = false
private var mList: ObservableArrayList<*>? = null
private lateinit var mIBindingRecyclerView: IBindingRecyclerView<T>
private var mIBindingRecyclerViewPlus: IBindingRecyclerViewPlus<T>? = null
/////////////////////////////////////////////////////////////////
// PROPERTIES
/////////////////////////////////////////////////////////////////
/**
* This is now how the interface needs to be set. This is taken care of in the @BindingAdapter
* method "bind:rcvInterface" (BindingAdapterMethods). I also decided to take care of setting the
* rowLayoutResourceId here, more as a "might as well" sort of thing, but also preventing the chance
* of a null ref exception if we were to use mIBindingRecyclerView.getRowLayoutResourceId() and
* mIBindingRecyclerView was null. Same goes for bindingModelId.
* @param iBindingRecyclerView
*/
fun setIBindingRecyclerView(iBindingRecyclerView: IBindingRecyclerView<*>, iBindingRecyclerViewPlus: IBindingRecyclerViewPlus<*>? = null) {
mIBindingRecyclerView = iBindingRecyclerView as IBindingRecyclerView<T>
mRowLayoutResourceId = iBindingRecyclerView.getRowLayoutResourceId()
mBindingModelId = iBindingRecyclerView.getBindingModelId()
mActionButtonId = iBindingRecyclerView.getActionButtonResourceId()
mHasActionButton = mActionButtonId > 0
mIBindingRecyclerViewPlus = iBindingRecyclerViewPlus as IBindingRecyclerViewPlus<T>?
}
/**
* This is how the list is set and any changes made will be notified here. If notifyDataSetChanged()
* is not called here, then the view will not be updated with the list changes. Setting the list gets
* taken care of in the @BindingAdapter method "bind:rcvList" (BindingAdapterMethods). Anytime the list
* changes in the activity/fragment, it will trigger the "bind:rcvList" method, and that will call
* setList(), thus updating the list and notifying data set changed which updates the view properly.
* @param list
*/
fun setList(list: ObservableArrayList<*>) {
mList = list
notifyDataSetChanged()
}
/////////////////////////////////////////////////////////////////
// BASE CLASS OVERRIDES
/////////////////////////////////////////////////////////////////
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BindingHolder {
val inflater = LayoutInflater.from(parent.context)
val viewDataBinding = DataBindingUtil.inflate<ViewDataBinding>(inflater, mRowLayoutResourceId, parent, false)
return BindingHolder(viewDataBinding)
}
override fun onBindViewHolder(holder: BindingHolder, position: Int) {
val model = mList!![position]
holder.binding.setVariable(mBindingModelId, model)
holder.binding.root.setTag(MODEL_TAG, model)
holder.binding.root.setTag(MODEL_POSITION_TAG, position)
holder.binding.root.setOnClickListener(this)
holder.binding.root.setOnLongClickListener(this)
if(mIBindingRecyclerViewPlus != null){
mIBindingRecyclerViewPlus?.onRowBinding(model as T, position, holder)
}
if (mHasActionButton) {
val btnAction = holder.binding.root.findViewById<View>(mActionButtonId)
btnAction.setTag(MODEL_TAG, model)
btnAction.setTag(MODEL_POSITION_TAG, position)
onActionClick(btnAction, holder)
}
holder.binding.executePendingBindings()
}
override fun getItemCount(): Int {
return if (mList == null) 0 else mList!!.size
}
////////////////////////////////////////////////////////////////
// CLICK LISTENERS
////////////////////////////////////////////////////////////////
override fun onClick(v: View) {
val model = v.getTag(MODEL_TAG) as T
val position = v.getTag(MODEL_POSITION_TAG) as Int
mIBindingRecyclerView.onItemClick(model, position)
}
override fun onLongClick(v: View): Boolean {
val model = v.getTag(MODEL_TAG) as T
val position = v.getTag(MODEL_POSITION_TAG) as Int
mIBindingRecyclerView.onItemLongClick(model, position)
return true
}
fun onActionClick(btnAction: View, holder: BindingHolder) {
btnAction.setOnClickListener {
val model = btnAction.getTag(MODEL_TAG) as T
val position = btnAction.getTag(MODEL_POSITION_TAG) as Int
mIBindingRecyclerView.onActionItemClick(model, position, holder)
}
}
////////////////////////////////////////////////////////////////
// SCOPED CLASSES
////////////////////////////////////////////////////////////////
class BindingHolder(var binding: ViewDataBinding) : RecyclerView.ViewHolder(binding.root)
}
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:paddingStart="@dimen/dp_20"
android:paddingEnd="@dimen/dp_20"
app:bindRcvInterface="@{iBindingRecyclerView}"
app:bindRcvList="@{fragment.getYourListItemModelList}"/>
class VerticalItemDecoration (private var spacingInPx: Int) : RecyclerView.ItemDecoration() {
/*///////////////////////////////////////////////////////////////
// ITEM DECORATION OVERRIDES
*////////////////////////////////////////////////////////////////
override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
outRect.bottom = spacingInPx
}