کاستوم setter و ساخت اتریبیوت جدید برای ویو در دیتا بایندینگ
برای اینکه لاجیک مربوط به کد توی XML بتونه برای ویو ست بشه، اتریبیوت های جدیدی برای ویو تعریف میکنیم و مقدار مورد نظر رو از طریق اونها در XML به ویو میدهیم. برای این کار از annotation
@BindingAdapter()
استفاده میشه.
متدی که کاستوم setter ایجاد میکنه باید استاتیک بوده و ویوی مورد نظر که قراره اتریبیوت جدید برای اون تعریف شه، جز آرگومان هاش باشه. مثلا:
@BindingAdapter("loadImage")
public static void setImage(ImageView view, int id){
view.setImageResource(id);
}
رشته ای که در پرانتز BindingAdapter نوشته میشه، اسم اتریبیوت هست. در متد بالا این اتریبیوت برای ImageViewها تعریف میشه و آرگومان دوم میگه که مقدار این اتریبیوت یک int هست.
نحوه استفاده از این اتریبیوت در ویوی ImageView:
app:loadImage="@{cartoon.image}"
عباراتی در که پرانتز نوشته میشه، میتونه چند تا باشه. هر کدوم بیانگر یک اتریبیوت هستن و در صورت استفاده باید همشون مقداردهی بشن البته میشه یه کاری کرد که لزومی نداشته باشه همه اتریبیوت های معرفی شده مقدار داشته باشن. مثلا:
@BindingAdapter(value = {"inputText", "errorText"})
public static void setInputWithError(@NonNull EditText editText, @NonNull String input, @NonNull String error) {
editText.setError(TextUtils.*isEmpty*(input) ? error : null);
}
نحوه استفاده:
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:errorText="@{@string/emptyText}"
app:inputText="@{text}"/>
توی مثال زیر به علت استفاده از requireAll = false لزومی نداره همه اتریبیوت ها مقدار داشته باشن:
@BindingAdapter(value = {"imageUrl", "errorDrawable"}, requireAll = false)
public static void loadImageWithError(@NonNull ImageView imageView,
@Nullable String url, @Nullable Drawable error) {
if (url != null) {
ImageLoader.load(imageView, url);
} else if (error != null) {
imageView.setImageDrawable(error);
}
}
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:errorDrawable="@{@drawable/errorPlaceholder}"/>
نکته: اگر خواستیم اتریبیوت های اندروید رو ادیت کنیم بصورت زیر اونو معرفی میکنیم:
@BindingAdapter("android:src")
public static void setImageUrl(ImageView view, String url) {
Glide.with(view.getContext()).load(url).into(view);
}
نحوه استفاده:
<ImageView
android:id="@+id/icon"
android:layout_width="40dp"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true"
android:layout_marginRight="6dip"
android:contentDescription="TODO"
android:src="@{obj.url}"
/>
منابع خوب:
کد ساخت اتریبیوت های imageView و recyclerView برای اپ انیمیشن ها:
توی این کد فرآیند ست کردن اداپتر و لیوت منیجر برای ریسایکلر ویو اینجا انجام شده. BindingAdapter ها بهتره توی یه کلاس جداگونه باشن. فقط باید حتما پکیج
import androidx.databinding.BindingAdapter;
import شده باشه.
public class CartoonBindingAdapter {
private static final int NUM_COLUMNS = 2;
@BindingAdapter("loadImage")
public static void setImage(ImageView view, int id) {
view.setImageResource(id);
}
@BindingAdapter("setcartoonslist")
public static void setRecyclerList(RecyclerView recyclerView, List<Cartoon> cartoonsList){
if(cartoonsList==null){
return;
}
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if(layoutManager==null){
recyclerView.setLayoutManager(new GridLayoutManager(recyclerView.getContext(), NUM_COLUMNS));
}
CartoonAdapter cartoonAdapter = (CartoonAdapter) recyclerView.getAdapter();
if(cartoonAdapter==null){
cartoonAdapter = new CartoonAdapter(recyclerView.getContext(), cartoonsList);
recyclerView.setAdapter(cartoonAdapter);
}
}
}