##問題
- アプリ内に同じような表示箇所が複数あり、それぞれを修正するのが辛い
- 下記のような、複数の場所で表示するパーツ
##解決案
- 複数のviewを1つのクラスにまとめて、表示ロジックもそのクラス内で完結させたい。
- Custom Viewを使う。
- 今回はRelativeLayoutを継承したクラスを作る。
##Custom Viewとは
Creating Custom Views
- 既存のviewをカスタマイズして使いやすいようにする。
- 例えば、正方形の画像が欲しい時はImageViewをextendsしたクラスを作成してonMeasure()をオーバライドする。
- レイアウトXMLをコピペして作ってる箇所は置き換えられるかもしれません。
##修正ファイル
- レイアウトXML
- viewをextendsしたクラス
- Activityのクラス
- ActiivtyのレイアウトXML
- attrs.xml (レイアウトXMLから値を取得したい場合。これは今回は説明しません。)
##レイアウトXML
- XMLを作成します。
custom_image_view.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- mergeで不必要なviewGrouの階層を作らないようにする -->
<merge
xmlns:android="http://schemas.android.com/apk/res/android">
<ImageView
android:id="@+id/icon"
android:layout_width="150dp"
android:layout_height="150dp"
android:layout_gravity="center_vertical"
android:layout_marginLeft="12dp"
/>
<TextView
android:id="@android:id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</merge>
##viewをextendsしたクラス
CustomImageView.java
public class CustomImageView extends RelativeLayout {
private Context mContext;
<!-- コンストラクタは3つ用意しました。 API21からは4つのコンストラクタが使えるようです-->
public CustomImageView(Context context) {
this(context, null);
}
public CustomImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.custom_image_view, this, true);
}
public void setInfo(String title, String description, String imageUrl) {
ImageView imageView = findViewById(R.id.icon);
Glide.with(getApplicationContext())
.load(imageUrl)
.placeholder(R.drawable.placeholder)
.into(imageView);
((TextView) findViewById(R.id.title)).setText(title);
((TextView) findViewById(R.id.description)).setText(description);
invalidate();
}
}
##customViewを利用するActivityのクラス
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomImageView custom = (CustomImageView) this.findViewById(R.id.custom);
custom.setInfo("title", "description", "画像URL");
}
}
##ActivityのレイアウトXML
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<sample.com.test_customview.CustomImageView
android:id="@+id/custom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
</LinearLayout>
##終わりに
- 見た目や処理を1つにまとめられるので便利です。