web-dev-qa-db-ja.com

RecyclerViewアダプターでカスタムビューを使用しますか?

次のような基本的なカスタムビューがあります。

_public class CustomView extends RelativeLayout {

    private User user;

    private ImageView profilePicture;

    public CustomView(Context context) {
        super(context);
        init();
    }

    public CustomView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        inflate(getContext(), R.layout.custom_layout, this);

        profilePicture = (ImageView) findViewById(R.id.profilePicture);

        // ACCESS USER MODEL HERE
        // e.g. user.getUsername()
    }

}
_

ご覧のとおり、ビューのユーザーデータにアクセスしたい(つまり、user.getUsername())。

また、RecyclerViewアダプターでカスタムビューを使用できる必要があります。

現在、私のアダプターは次のようになっています。

_public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {

    private Context context;

    private List<User> userData;

    public MyAdapter(Context context, List<User> userData) {
        this.context = context;
        this.userData = userData;
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        public ViewHolder(View v) {
            super(v);
        }
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = LayoutInflater.from(context);

        // HOW TO INFLATE THE CUSTOM VIEW?

        // ViewHolder viewHolder = new ViewHolder(customView);

        return viewHolder;
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        // ANYTHING HERE?
    }

    @Override
    public int getItemCount() {
        return userData.size();
    }

}
_

アダプタでカスタムビューを膨らませるにはどうすればよいですか?
また、onBindViewHolder()に何かを入れるべきですか?

注:I mustカスタムビューを使用します。これは、このビューをさまざまなアダプター(つまり、このRecyclerViewアダプターだけでなく)で使用するためです。

13
user7638732

次のようなCustomViewクラスを想定します。

public class CustomView extends RelativeLayout {
    private User user;
    private ImageView profilePicture;

    // override all constructors to ensure custom logic runs in all cases
    public CustomView(Context context) {
        this(context, null);
    }
    public CustomView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }
    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }
    public CustomView(
            Context context,
            AttributeSet attrs,
            int defStyleAttr,
            int defStyleRes
    ) {
        super(context, attrs, defStyleAttr, defStyleRes);

        // put all custom logic in this constructor, which always runs
        inflate(getContext(), R.layout.custom_layout, this);
        profilePicture = (ImageView) findViewById(R.id.profilePicture);
    }

    public void setUser(User newUser) {
        user = newUser;
        // ACCESS USER MODEL HERE
        // e.g. user.getUsername()
    }
}

RecyclerView.AdapterRecyclerView.ViewHolderは次のようになります。

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
    // no Context reference needed—can get it from a ViewGroup parameter
    private List<User> userData;

    public MyAdapter(List<User> userData) {
        // make own copy of the list so it can't be edited externally
        this.userData = new ArrayList<User>(userData);
    }

    @Override
    public int getItemCount() {
        return userData.size();
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        // no need for a LayoutInflater instance—
        // the custom view inflates itself
        CustomView itemView = new CustomView(parent.getContext());
        // manually set the CustomView's size
        itemView.setLayoutParams(new ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.WRAP_CONTENT
        ));
        return new ViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(final ViewHolder holder, int position) {
        holder.getCustomView().setUser(userData.get(position));
    }

    public class ViewHolder extends RecyclerView.ViewHolder {
        private CustomView customView;

        public ViewHolder(View v) {
            super(v);
            customView = (CustomView) v;
        }

        public CustomView getCustomView() {
            return customView;
        }
    }
}
  • CustomViewは独自のセットアップを管理します。セットアップは独自のコンストラクターで行われ、この場合はXMLファイルのインフレーションを使用します。 (または、プログラムで子ビューを設定できます。)
  • このため、RecyclerView.Adapterはインフレーションを実行する必要がありません。新しいCustomViewインスタンスを作成し、CustomViewに独自のセットアップを心配させます。
  • CustomViewは、Userメソッドが呼び出されるまでsetUserインスタンスを取得できないため、コンストラクターでユーザーアクセスを行うことはできません。いずれにせよ、1つのCustomViewライフタイムにわたって、RecyclerViewは、異なる時間に多くの異なるユーザーの情報を表示するように要求できます。 CustomViewはこれを行うことができる必要があります。したがって、setUserメソッドが導入されています。
  • CustomViewはXMLではなくコードによってインスタンス化されるため、サイズの属性をXMLで定義することはできません。したがって、サイズ設定は、インスタンス化後にプログラムで行われます。
  • onBindViewHolderは、setUserCustomViewを呼び出して、CustomViewを正しいUserインスタンスにリンクするだけです。
  • ViewHolderクラスは、RecyclerViewアイテムとCustomViewの間の単なるリンクになりました。

RecyclerViews内の別のクラスから事前に構築されたカスタムビューを使用する(つまり、RecyclerView.Adapter内でXMLを拡張しない)ことは、決して議論されていないようです。カスタムビューがRecyclerView内で排他的に使用されている場合でも、素晴らしいアイデアだと思います。なぜなら、それは 懸念の分離を促進する および 単一責任原則の順守

23
Alex Peters
_CustomView extends RelativeLayout {
_

すでにビューがあります(まあ、ViewGroup

カスタムビューを拡張する方法

必要はありません...カスタムビューオブジェクトのポイントは、XMLを必要としないため、インフレが発生しないことです。

new CustomView()を作成できますが、すべてのレイアウトパラメーターを設定する必要があり、XMLで見た目がきれいになります。


ほとんどのRecyclerViewチュートリアルでは、 XMLを使用した膨張 を示しています。

_View customView = inflater.inflate(...);
ViewHolder viewHolder = new ViewHolder(customView);
_

クラスチェーンには_CustomView > RelativeLayout > ViewGroup > View_があるため、これは機能するはずです。

_LayoutInflater inflater = LayoutInflater.from(context);
_

前に言ったように、膨らませたいXMLファイルがなければこれは必要ありません。

また、context変数も必要ありません。

parent.getContext()は良い解決策です。

_// ANYTHING HERE?
_

ええ、そうです、ViewHolderViewHolderが保持すべきデータと「バインド」する必要があります。

繰り返しになりますが、すべてではありませんが、ほとんどのチュートリアルでこれを説明しています。

4
cricket_007