今更遅れてDataBinding事始め(5)[コピペ用]
いままでのまとめ
- 今更遅れてDataBinding事始め(1)[環境構築] - exception think
- 今更遅れてDataBinding事始め(2) - exception think
- 今更遅れてDataBinding事始め(3)[include] - exception think
- 今更遅れてDataBinding事始め(3.5) - exception think
- 今更遅れてDataBinding事始め(3.7) - exception think
- 今更遅れてDataBinding事始め(4)[双方向] - exception think
現在通常の開発で data-bindingを使っていますが、今回は作業をする上でのチートシート的なものをまとめておこうかと
なんでここらへんのコピペシートが必要なの?
- data-bindingは、
アプリの構造的設計な話
自分の場合は
no | 役割 | 対応クラス/ファイル | 具体的な操作 |
---|---|---|---|
1 | Controler | Activity/Fragment/ListAdapter | RestAPIで一覧等を取得 |
2 | View | layout.xml | 値のマッピング、表示 |
3 | ViewModel | Utilクラス★ | 単純マッピングできない表示、挙動の加工 |
★に関しては、
- BindingAdapter を記述しているクラス
- 通信やDB保存を隠蔽するManger
普通のQittaとかの例のように、それ専用の ViewModelクラスを作ってそれぞれに書く必要はない
自分の場合だと
- CommonAdapterみたいな一個のクラスに BindingAdapter の関数を箇条書きにしています。
- 理由としてはdata-bindingのクラスにおいてバラバラに書いても全ソースファイルスキャンされるから
- 逆にバラして書くと若干コンパイルが遅くなる
build.grade 編
- app/build/gralde
android{ dataBinding{ enabled = true } } dependencies{ debugCompile 'com.android.support:multidex:1.0.1' }
layout.xml 編
- 基本的に値代入しかできない
- 式判定は、Boolean判定がベター
- 複雑な判定式、処理はBindingAdapterで対応する
import文の定番
<layout> <data> <import type="android.view.View"/> <import type="android.text.TextUtils"/> </data>
namespaceの定番
- layoutの行で下記のワードタイピングで挿入
- appNs
- toolsNs
<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"> //★
bind対象の変数宣言
<layout> <data> <variable name="model" type="com.twitter.sdk.android.core.models.Tweet" /> </data>
判定式の書き方
- 複雑な判定式を書こうとするとlayout解釈で失敗しやすい
- どうしても書きたい場合はBindingAdapterの方で定義して作業する
<ImageView android:visibility="@{TextUtils.isEmpty(model.imageUrl) ? View.GONE:View.VISIBLE}" android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageUrl="@{model.imageUrl}" />
includeレイアウト
- include先も勿論data-bindingのレイアウトであること
- idをふらないとinclude先のレイアウトにアクセスできない
単純に表示だけであれば、NGパターンでも問題ないが、その用途だとそもそも受け渡すのがいらない気がする
NGパターン
<include layout="@layout/include_item_article" app:article="@{article}"/>
- OKパターン
<include android:id="@+id/item_article" android:layout_width="match_parent" android:layout_height="wrap_content" layout="@layout/include_item_article" app:article="@{article}"/>
idを指定した時点で、layout_width/layout_height の指定が強制される
BindingAdapter編
- 一時期 “bind:imageUrl” みたいな書き方が書けたが、現在はLintエラーにされる
引数一つ
関数自体は
- TargetView
- 引数1
CommonAdapter.java
@BindingAdapter("imageUrl") public static void loadImage(ImageView view, String url) { Picasso.with(view.getContext()).load(url).into(view); }
- layout.xml
<ImageView android:visibility="@{TextUtils.isEmpty(model.imageUrl) ? View.GONE:View.VISIBLE}" android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageUrl="@{model.imageUrl}" />
引数2つ
関数自体は
- TargetView
- 引数1
- 引数2
CommonAdapter.java
@BindingAdapter({"imageUrl", "error"}) public static void loadImage(ImageView view, String url, Drawable error) { Picasso.with(view.getContext()).load(url).error(error).into(view); }
- layout.xml
<ImageView android:visibility="@{TextUtils.isEmpty(model.imageUrl) ? View.GONE:View.VISIBLE}" android:layout_width="wrap_content" android:layout_height="wrap_content" app:imageUrl="@{model.imageUrl}" app:error="@{ @drawable/ic_error_24dp }" //use material icon />
自分がよく追加しているやつ
CommonAdapter.java
画像読込処理
@BindingAdapter("imageUrl") public static void loadImage(final ImageView view, final String url) { Log.d(TAG,"loadImage=" + url); Glide.with(view.getContext()).load(url).placeholder(R.drawable.c_3d_rotation_black_24dp).into(view); } @BindingAdapter("drawableLeft") public static void drawableLeft(final TextView view ,final String url){ if(TextUtils.isEmpty(url)){ return; } Log.d(TAG,"drawableLeft=" + url); final Context context = view.getContext(); Glide.with(context) .load(url) .asBitmap() .into(new SimpleTarget<Bitmap>(150, 150) { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation anim) { view.setCompoundDrawablesWithIntrinsicBounds(new BitmapDrawable(context.getResources(),bitmap),null,null,null); } @Override public void onLoadFailed(Exception e, Drawable errorDrawable) { super.onLoadFailed(e, errorDrawable); } }); }
- 汎用的な処理
@BindingAdapter("background") public static void setBackground(View view, Drawable Drawable) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { view.setBackground(drawable); } else { view.setBackgroundDrawable(drawable); } } @BindingAdapter("tint") public static void setTint(View view, int color) { Drawable Drawable = view,getBackground(); DrawableCompat.wrap(drawable); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { DrawableCompat.setTint(drawable, color); DrawableCompat.setTintMode(drawable, PorterDuff.Mode.SRC_IN); } else { drawable.setColorFilter(color, PorterDuff.Mode.SRC_IN); } setBackground(view,drawable); }
- layout.xml
<ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" app:tint="@{@color/colorRed}" />
ちなみに
の話は後で知りました(汗
TextViewのtintだと大変なんだな・・ 自分はImageViewとかでしか使ったことないです
使って便利だったやつ
twitter kit の com.twitter.sdk.android.core.models.Tweet って
なぜかメンバーがすべてfinalでして、表示の加工をするためには @BindingAdapter が必須でした
- ハッシュタグ
- @ユーザ
を抽出後リンクを貼る
- CommonAdapter.java
@BindingAdapter("message") public static void setMessage(TextView textView, Tweet tweet) { final Context context = textView.getContext(); String text = tweet.text; final SparseArray<String> links = new SparseArray<String>(); //=== ハッシュタグの抽出処理 ==== int cnt = 0; if(text.indexOf("#") != -1) { int len = text.length(); int st = 0; while (st < len) { st = text.indexOf("#", st); if (st == -1) { break; } int ed = text.indexOf(" ", st); String tag = ed == -1 ? text.substring(st) : text.substring(st, ed); ; links.append(cnt, tag); cnt++; st = ed; if (ed == -1) { break; } } } OnLinkClickListener listener = new OnLinkClickListener() { @Override public void onLinkClick(int textId) { String tag = links.get(textId); if(tag.startWith("#")){ tag = tag.substring(1); String tweetUrl = "twitter://search?query=%23" + tag; Intent i = new Intent(Intent.ACTION_VIEW, Uri.parse(tweetUrl)); context.startActivity(i); } } }; textView.setText(TextLinker.getLinkableText(text, links, listener)); textView.setMovementMethod(LinkMovementMethod.getInstance()); }
まあ投稿するなら下記なんでしょうけど、twitter連携 で検索するとこちらばかり引っかかるんだよな。。
http://twitter.com/share?text=[共有したいテキスト]
https://twitter.com/intent/tweet?hashtags=[#なしのハッシュタグ]
Parameter | Description | Example |
---|---|---|
text | Pre-populated text highlighted in the Tweet composer. | custom share text |
url | URL included with the Tweet. | https://dev.twitter.com/web/tweet-button |
hashtags | A comma-separated list of hashtags to be appended to default Tweet text. | example,demo |
via | Attribute the source of a Tweet to a Twitter username. | twitterdev |
related | A comma-separated list of accounts related to the content of the shared URI. | twitterapi,twitter |
通信やDB保存を隠蔽するManger
これは次回に回します