Nested use of Card View layout in Fragment

Posted by Serpent7 on Tue, 14 Apr 2020 18:52:52 +0200

Nested Card View layout in Fragment

Look at the effect first:

The layout file of Fragment is very simple, just a RecyclerView layout

<android.support.v7.widget.RecyclerView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/recycler_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>

Then define a class by yourself

public class Fruit {
    private String name;
    private int imageId;

    public Fruit (String name, int imageId){
        this.name = name;
        this.imageId = imageId;
    }

    public String getName() {
        return name;
    }

    int getImageId() {
        return imageId;
    }
}

Write another layout file

<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="5dp"
    app:cardCornerRadius="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/image_fruit"
            android:layout_width="wrap_content"
            android:layout_height="100dp"
            android:scaleType="centerCrop"/>

        <TextView
            android:id="@+id/name_fruit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:gravity="center_horizontal"
            android:textSize="16sp"/>

    </LinearLayout>

</android.support.v7.widget.CardView>

Then there is the adapter. Because Fragment uses RecyclerView to wrap CardView, an adapter is needed

package com.example.deep.news.pic;

import android.content.Context;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.example.deep.news.R;

import java.util.List;

public class FruitAdapter extends RecyclerView.Adapter<FruitAdapter.ViewHolder> {

    private Context context;
    private List<Fruit> myFruitList;

    static class ViewHolder extends RecyclerView.ViewHolder {
        CardView cardView;
        ImageView fruitImage;
        TextView fruitName;

        ViewHolder(View itemView) {
            super(itemView);
            cardView = (CardView) itemView;
            fruitImage = itemView.findViewById(R.id.image_fruit);
            fruitName = itemView.findViewById(R.id.name_fruit);
        }
    }

    public FruitAdapter(List<Fruit> fruitList) {
        myFruitList = fruitList;
    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (context == null) {
            context = parent.getContext();
        }

        View view = LayoutInflater.from(context).inflate(R.layout.fruit_item, parent, false);
        return new ViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        Fruit fruit = myFruitList.get(position);
        holder.fruitName.setText(fruit.getName());
        Glide.with(context).load(fruit.getImageId()).into(holder.fruitImage);
    }

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

}

ViewHolder usually appears in the adapter to quickly set values when listview scrolls, instead of having to recreate many objects each time, thus improving performance.

Finally, it can be loaded in the Fragment

package com.example.deep.news.fragment;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.example.deep.news.R;
import com.example.deep.news.pic.Fruit;
import com.example.deep.news.pic.FruitAdapter;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * First fragment
 */

public class Fragment1 extends Fragment {

    private Fruit[] fruits = {new Fruit("apple", R.drawable.lighthouse), new Fruit("banana", R.drawable.lighthouse), new Fruit("mango", R.drawable.lighthouse)};
    private List<Fruit> fruitList = new ArrayList<>();
    private RecyclerView recyclerView;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.viewpager_layout1, container, false);
        recyclerView = view.findViewById(R.id.recycler_view);
        initView();
        return view;
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initFruits();
    }

    private void initView() {
        GridLayoutManager layoutManager = new GridLayoutManager(this.getContext(), 2);//Parameter: context, number of columns
        recyclerView.setLayoutManager(layoutManager);
        FruitAdapter fruitAdapter = new FruitAdapter(fruitList);
        recyclerView.setAdapter(fruitAdapter);
    }

    private void initFruits() {
        fruitList.clear();
        for (int i = 0; i < 15; i++) {
            Random random = new Random();
            int index = random.nextInt(fruits.length);
            fruitList.add(fruits[index]);
        }
    }

}

Operations in the initview() method must be performed in onCreateView()
GridLayoutManager needs to pass two parameters, one is context object, the other is parameter constant with several columns displayed in one row

Problems encountered

findViewById() cannot be used in Fragment

Solution

First, the onCreateView() method creates the view

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        return inflater.inflate(R.layout.viewpager_layout1, null);
    }

Using the getView() method, this method will eventually return the root view of the current fragment.

RecyclerView recyclerView = (RecyclerView )getView().findViewById(R.id.recycler_view);

If you use the inflate method to instantiate a view yourself

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.viewpager_layout1, container, false)
        return view;
    }

The getView() method is no longer used

RecyclerView recyclerView = view.findViewById(R.id.recycler_view);

It is also important to understand the life cycle of Fragment.

The above is just one of my own learning records. If you have any shortcomings, please point out. Thank you.

Topics: Android Fragment Java