前人未踏の領域へ アプリ開発編

Android, iOSアプリ開発に関する調査メモ置き場。ほとんどAndroid。はてなダイアリーから移行したため古い記事にはアプリ以外も含まれます。

RecyclerViewを使う

とりあえず一覧を表示するサンプル。

ポイント
  • レイアウトの種類はLaytoutManagerで管理
  • ViewHolderの利用が前提になっている
  • setOnItemClickListenerがRecyclerViewには存在しないので、RecyclerView.Adapter内のViewHolderのコンストラクタか、同AdapterのonCreateViewHolderで実装する必要がある
build.gradle

全部はいらないんだけど放り込んでしまう。

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.2.0'
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:support-annotations:22.2.0'
    compile 'com.android.support:recyclerview-v7:22.2.0'
    compile 'com.android.support:palette-v7:22.2.0'
    compile 'com.android.support:gridlayout-v7:22.2.0'
    compile 'com.android.support:cardview-v7:22.2.0'
    compile 'com.android.support:support-v4:22.2.0'
}
styles.xml
<resources>
    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/blue_500</item>
        <item name="colorPrimaryDark">@color/blue_700</item>
        <item name="colorAccent">@color/green_A200</item>
        <item name="android:textColorPrimary">@color/white</item>
        <item name="android:windowBackground">@color/grey_50</item>
    </style>
</resources>
Layout.xml

fragment_main.xml

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivityFragment">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/my_recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:listitem="@android:layout/text_list_item" />
</RelativeLayout>

text_list_item.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="48dp"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        tools:text="サンプルテキスト" />
</LinearLayout>
Fragment
/**
 * A placeholder fragment containing a simple view.
 */
public class MainActivityFragment extends ListFragment {
    private RecyclerView mRecyclerView;
    private RecyclerView.Adapter mAdapter;
    private RecyclerView.LayoutManager mLayoutManager;

    public MainActivityFragment() {
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        /** Layoutの取得  */
        ViewGroup mainView = (ViewGroup) inflater.inflate(R.layout.fragment_main, container, false);

        /** RecyclerViewの取得 */
        mRecyclerView = (RecyclerView) mainView.findViewById(R.id.my_recycler_view);


        /** RecyclerViewの設定 */
        //コンテンツのレイアウトサイズが変更されない場合に指定する。パフォーマンス向上のための設定
        mRecyclerView.setHasFixedSize(true);

        /** LayoutManagerの設定 */
        // 縦スクロール用にLinearLayoutManagerを使う
        mLayoutManager = new LinearLayoutManager(getActivity());
        mRecyclerView.setLayoutManager(mLayoutManager);


        /** Adapterの設定 */
        // RecyclerView.Adapter
        mAdapter = new MyAdapter(createDummyDataStub());
        mRecyclerView.setAdapter(mAdapter);

        return mainView;

    }

    /**
     * ダミーデータ作成
     * @return
     */
    private String[] createDummyDataStub() {
        String[] dataSet = new String[100];
        for (int i = 0; i < dataSet.length; i++) {
            dataSet[i] = "data_" + i;
        }
        return dataSet;
    }
}

Adapter

package com.toikai.toikaimaterial.controller;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import com.toikai.toikaimaterial.R;

/**
 */
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    private String[] mDataSet;


    // Provide a suitable constructor (depends on the kind of dataset)
    public MyAdapter(String[] myDataset) {
        mDataSet = myDataset;
    }

    // リソースからViewを取得してViewHolderを生成して返す。viewTypeも引数で取得可能なので
    // ポジションに応じたViewの出し分けができる
    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
                                                   int viewType) {
        // create a new view
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.text_list_item, parent, false);
        return new ViewHolder(v);
    }

    /**
     * ViewHolderに値をセットする。これまでArrayAdapterのgetView()で行っていた内容に相当。
     * */
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(mDataSet[position]);

    }

    //positionに応じたアイテムのビュータイプを返す
    @Override
    public int getItemViewType(int position) {
        return super.getItemViewType(position);
    }

    //データサイズを返す
    @Override
    public int getItemCount() {
        return mDataSet.length;
    }


    // リストの1行分を表すViewHolder。ここでイベントの設定などもおこなう。
    public static class ViewHolder extends RecyclerView.ViewHolder {
        // each data item is just a string in this case
        public TextView mTextView;

        public ViewHolder(View v) {
            super(v);
            v.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    //行がクリックされた!
                }
            });
            mTextView = (TextView)v.findViewById(R.id.text);
        }
    }

}