RecyclerViewを使うときに起きた問題を解決する方法
Android LにはListView
の進化型であるRecyclerView
というウィジットが追加されました。
RecyclerView
について調べると、ListView
に比べると
- パフォーマンスの向上
- 使いやすさの向上
といった記事が目につきます。
実際にどうなのか、使うまでの手順や気がついたことを記していきます。
※ 本記事は以下の環境で実施されました。
IDE: Android Studio 0.8.8
Java: 1.6.0_65
※ Android DevelopersにはRecyclerView
のトレーニングとして Creating Lists and Cards というのがあります。
compileSdkVersion android-L の回避方法
Android Studioで新しいProjectで Minimum SDK
を API 20+: Android L
に設定する。
作成したときの build.gradle を確認すると次の通りです。
android {
compileSdkVersion 'android-L'
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "jp.co.samril.myapplication"
minSdkVersion 'L'
targetSdkVersion 'L'
versionCode 1
versionName "1.0"
}
...
}
実は、このまま作成されたProjectをコンパイルすると次のようなエラーが発生する。
Error:compileSdkVersion android-L requires compiling
調べてみると、バグらしいですね。
[How-to] Use the v21 Support Libs on Older Versions & Target L While Remaining Backwards-Compatible
build.gradle を次のように修正すればOKです。
android {
compileSdkVersion 20 // ★ここを整数に
buildToolsVersion "20.0.0"
defaultConfig {
applicationId "jp.co.samril.myapplication"
minSdkVersion 'L'
targetSdkVersion 'L'
versionCode 1
versionName "1.0"
}
...
}
低いSDKでコンパイルする方法
RecyclerView
はAndroid Lから追加されたウィジットのため、SDK Versionが 20 以上でないといけません。
build.gradle の dependencies
に次をセットし、
dependencies {
compile 'com.android.support:support-v4:20.+'
compile 'com.android.support:recyclerview-v7:+'
}
実際に低いSDKを設定すると、次のようなコンパイルエラーが発生します。
Error:Execution failed for task '...'.
> Manifest merger failed : uses-sdk:minSdkVersion 14 cannot be smaller than version L declared in library com.android.support:support-v4:21.0.0-rc1
これを解除するには AndroidManifest.xml に uses-sdk
の設定を追加してやればよい。
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="jp.co.homes.android3" >
<uses-sdk tools:node="replace" />
...
xmlns:tools="http://schemas.android.com/tools"
と <uses-sdk tools:node="replace" />
を追記しました。
これで Gradle のビルドは通るようになります。
レイアウトへの配置したときにプレビューが見れない
レイアウトファイルには、通常のListView
と同じ記述で書くことができます。
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
ただし、Preview を確認しようとするとjava.lang.NullPointerException
が発生します。
Rendering Problems
The new RecyclerView does not yet work in Studio. We are working on a fix. (Open Issue 72117, Show Exception)
リンク先に書いてあるとおり、なんとRecyclerView
は Android Studio ではまだ動作しないようです。(まじっすか...
表示したときに発生するNullPointerExceptionを回避する方法
RecyclerView
を埋め込み、無事ビルドまでパスします。
では実機やGenymotionで動作を確認してみようと、画面を表示するとjava.lang.NullPointerException
でクラッシュしました。
java.lang.NullPointerException
at android.support.v7.widget.RecyclerView.onMeasure(RecyclerView.java:1310)
at android.view.View.measure(View.java:16497)
at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:5125)
at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1404)
...
調べてみると、これもAndroid Studioのバグだとか...
Using CardView and RecyclerView in my layout files throws an exception
原因はRecyclerView
を初期化できていないらしい。
回避方法はこちら
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.my_recycler_view);
recyclerView.setHasFixedSize(true); // RecyclerViewのサイズを維持し続ける
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setItemAnimator(new DefaultItemAnimator());
この実装はonCreate()
or onCreateView()
に追記します。
これで NullPointerException を回避できます。
行間に区切り線を表示させる方法
RecyclerView
で android.R.layout.simple_list_item_1
を描画した場合、行間の区切り線が表示されません。
これを回避するには RecyclerView.ItemDecoration を使います。
RecyclerView.ItemDecoration とは
Adapterでセットする特定ビューへの描画やレイアウトの追加ができるものです
例えば、今回のような区切り線やハイライトなど、様々な表現を可能にできます
https://gist.github.com/alexfu/0f464fc3742f134ccd1e を参考に次のクラスを作成します。
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;
/**
* Created by samukaak on 2014/11/20.
*/
public class MyItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{
android.R.attr.listDivider
};
private Drawable mDivider;
public MyItemDecoration(final Context context) {
final TypedArray array = context.obtainStyledAttributes(ATTRS);
mDivider = array.getDrawable(0);
array.recycle();
}
@Override
public void getItemOffsets(final Rect outRect, final int itemPosition, final RecyclerView parent) {
outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
}
@Override
public void onDraw(final Canvas c, final RecyclerView parent) {
drawVertical(c, parent);
}
public void drawVertical(final Canvas c, final RecyclerView parent) {
final int left = parent.getPaddingLeft();
final int right = parent.getWidth() - parent.getPaddingRight();
final int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
final View child = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
.getLayoutParams();
final int top = child.getBottom() + params.bottomMargin;
final int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
それを RecyclerView#addItemDecoration(android.support.v7.widget.RecyclerView.ItemDecoration decor)
を使って設定します。
recyclerView.addItemDecoration(new MyItemDecoration(getActivity()));
参考
Author And Source
この問題について(RecyclerViewを使うときに起きた問題を解決する方法), 我々は、より多くの情報をここで見つけました https://qiita.com/Sam/items/d5b82f6c2830fa4d14a2著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .