Skip to content

Instantly share code, notes, and snippets.

@MohammadSamandari
Last active April 2, 2020 11:22
Show Gist options
  • Save MohammadSamandari/935421962efd43b3044800e7577ac58f to your computer and use it in GitHub Desktop.
Save MohammadSamandari/935421962efd43b3044800e7577ac58f to your computer and use it in GitHub Desktop.
RecyclerView

RecyclerView

to show data inside the recyclerview we need the following :

  1. Data to display: Use the mWordList.
  2. A RecyclerView for the scrolling list that contains the list items.
  3. Layout for one item of data. All list items look the same.
  4. A layout manager. RecyclerView.LayoutManager handles the hierarchy and layout of View elements. RecyclerView requires an explicit layout manager to manage the arrangement of list items contained within it. This layout could be vertical, horizontal, or a grid. You will use a vertical LinearLayoutManager.
  5. An adapter. RecyclerView.Adapter connects your data to the RecyclerView. It prepares the data in a RecyclerView.ViewHolder. You will create an adapter that inserts into and updates your generated words in your views.
  6. A ViewHolder. Inside your adapter, you will create a ViewHolder that contains the View information for displaying one item from the item's layout.

To implement these pieces, you will need to:

Add a RecyclerView element to the MainActivity XML content layout (content_main.xml) for the RecyclerView app.

Create an XML layout file (wordlist_item.xml) for one list item, which is WordListItem.

  • Note that the height of the elements inside this layout is wrap-content.

Create an adapter (WordListAdapter) with a ViewHolder (WordViewHolder). Implement the method that takes the data, places it in the ViewHolder, and lets the layout manager know to display it.

  • Android uses adapters (from the Adapter class) to connect data with View items in a list.
  • To connect data with View items, the adapter needs to know about the View items. The adapter uses a ViewHolder that describes a View item and its position within the RecyclerView.
  • First, you will build an adapter that bridges the gap between the data in your word list and the RecyclerView that displays it
  1. Right-click java/com.android.example.recyclerview and select New > Java Class.
  2. Name the class WordListAdapter.
  3. Give WordListAdapter the following signature:
public class WordListAdapter extends
    RecyclerView.Adapter<WordListAdapter.WordViewHolder>  {}
  1. Click the class declaration (WordListAdapter), then click the red light bulb on the left side of the pane. Choose Implement methods.

Create the ViewHolder for the adapter

To create the ViewHolder, follow these steps:

  1. Inside the WordListAdapter class, add a new WordViewHolder inner class with this signature:
class WordViewHolder extends RecyclerView.ViewHolder {}
  1. Add variables to the WordViewHolder inner class for the TextView and the adapter:
public final TextView wordItemView;
final WordListAdapter mAdapter;
  1. In the inner class WordViewHolder, add a constructor that initializes the ViewHolder TextView from the word XML resource, and sets its adapter:

Storing your data in the adapter

You need to hold your data in the adapter, and WordListAdapter needs a constructor that initializes the word list from the data. Follow these steps:

  1. To hold your data in the adapter, create a private linked list of strings in WordListAdapter and call it mWordList.
  2. You can now fill in the getItemCount() method to return the size of mWordList:
  3. WordListAdapter needs a constructor that initializes the word list from the data. To create a View for a list item, the WordListAdapter needs to inflate the XML for a list item. You use a layout inflator for that job. LayoutInflator reads a layout XML description and converts it into the corresponding View items. Start by creating a member variable for the inflater in WordListAdapter:
  4. Implement the constructor for WordListAdapter. The constructor needs to have a context parameter, and a linked list of words with the app's data. The method needs to instantiate a LayoutInflator for mInflater and set mWordList to the passed in data:
  5. Fill out the onCreateViewHolder() method with this code:
@Override
public WordViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
   View mItemView = mInflater.inflate(R.layout.wordlist_item, parent, false);
   return new WordViewHolder(mItemView, this);
}
  • The onCreateViewHolder() method is similar to the onCreate() method. It inflates the item layout, and returns a ViewHolder with the layout and the adapter.
  1. Fill out the onBindViewHolder() method with the code below:
@Override
public void onBindViewHolder(WordViewHolder holder, int position) {
   String mCurrent = mWordList.get(position);
   holder.wordItemView.setText(mCurrent);
}

In the onCreate() method of MainActivity, create a RecyclerView and initialize it with the adapter and a standard layout manager.

Now that you have an adapter with a ViewHolder, you can finally create a RecyclerView and connect all the pieces to display your data.

  1. Add member variables for the RecyclerView and the adapter.
  2. In the onCreate() method of MainActivity, add the following code that creates the RecyclerView and connects it with an adapter and the data. The comments explain each line. You must insert this code after the mWordList initialization.
// Get a handle to the RecyclerView.
mRecyclerView = findViewById(R.id.recyclerview);
// Create an adapter and supply the data to be displayed.
mAdapter = new WordListAdapter(this, mWordList);
// Connect the adapter with the RecyclerView.
mRecyclerView.setAdapter(mAdapter);
// Give the RecyclerView a default layout manager.
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));

Make the list interactive

  1. Open WordListAdapter.
  2. Change the WordViewHolder class signature to implement View.onClickListener:
  3. Add the following code to the body of the onClick() method.
// Get the position of the item that was clicked.
int mPosition = getLayoutPosition();
// Use that to access the affected item in mWordList.
String element = mWordList.get(mPosition);
// Change the word in the mWordList.
mWordList.set(mPosition, "Clicked! " + element);
// Notify the adapter, that the data has changed so it can 
// update the RecyclerView to display the data.
mAdapter.notifyDataSetChanged();
  1. Connect the onClickListener with the View. Add this code to the WordViewHolder constructor (below the this.mAdapter = adapter line):
itemView.setOnClickListener(this);

Summery

  • RecyclerView is a resource-efficient way to display a scrollable list of items.
  • To create a View for each list item, the adapter inflates an XML layout resource for a list item using LayoutInflator.
  • LinearLayoutManager is a RecyclerView layout manager that shows items in a vertical or horizontal scrolling list.
  • GridLayoutManager is a RecyclerView layout manager that shows items in a grid
  • StaggeredGridLayoutManager is a RecyclerView layout manager that shows items in a staggered grid.
  • Use RecyclerView.Adapter to connect your data to the RecyclerView. It prepares the data in a RecyclerView.ViewHolder that describes a View item and its position within the RecyclerView.
  • Implement View.onClickListener to detect mouse clicks in a RecyclerView.

Note: Create a style from the TextView attributes:

You can use styles to allow elements to share groups of display attributes. An easy way to create a style is to extract the style of a UI element that you already created. to do so: Right-click (or Control-click) the Element you just created in ....xml, and choose Refactor > Extract > Style. The Extract Android Style dialog appears.

Scroll to an item in the recyclerview

mRecyclerView.smoothScrollToPosition(mWordList.size()-1);

To add a ripple effect to the recycleview

add this code to the xml of the main container of the one item of the recyclerview

android:focusable="true"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
package mohammad.samandari.recycleviewdemo;
import android.os.Bundle;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.util.Log;
import android.view.View;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// TAG variable for the system Logs.
private static final String TAG = "Lord";
//Creating a list of word to populate the recyclerview
private final LinkedList<String> mWordList = new LinkedList<>();
private RecyclerView mRecyclerView;
private WordListAdapter mAdapter;
@Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//A loop to populate the Linkedlist with some words.
for (int i = 0; i < 20; i++) {
mWordList.add("Word" + i);
}
// Get a handle to the RecyclerView.
mRecyclerView = findViewById(R.id.recyclerview);
// Create an adapter and supply the data to be displayed.
mAdapter = new WordListAdapter(this, mWordList);
// Connect the adapter with the RecyclerView.
mRecyclerView.setAdapter(mAdapter);
// Give the RecyclerView a default layout manager.
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
FloatingActionButton fab = findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick (View view) {
int mWordListSize = mWordList.size();
mWordList.add("Word" + mWordListSize);
mAdapter.notifyDataSetChanged();
mRecyclerView.smoothScrollToPosition(mWordListSize);
}
});
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dp">
<TextView
android:id="@+id/word"
style="@style/word_title" />
</LinearLayout>
package mohammad.samandari.recycleviewdemo;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.LinkedList;
public class WordListAdapter extends RecyclerView.Adapter<WordListAdapter.WordViewHolder> {
private LinkedList<String> mWordList;
public WordListAdapter (LinkedList<String> wordList) {
this.mWordList = wordList;
}
class WordViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView wordItemView;
public WordViewHolder (@NonNull View itemView) {
super(itemView);
wordItemView = itemView.findViewById(R.id.word);
itemView.setOnClickListener(this);
}
@Override
public void onClick (View v) {
// Get the position of the item that was clicked.
int mPosition = getLayoutPosition();
// Use that to access the affected item in mWordList.
String element = mWordList.get(mPosition);
// Change the word in the mWordList.
mWordList.set(mPosition, element + " Was Clicked");
// Notify the adapter, that the data has changed so it can
// update the RecyclerView to display the data.
mAdapter.notifyDataSetChanged();
}
}
@NonNull
@Override
public WordListAdapter.WordViewHolder onCreateViewHolder (@NonNull ViewGroup parent, int viewType) {
View mItemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.wordlist_item, parent, false);
return new WordViewHolder(mItemView);
}
@Override
public void onBindViewHolder (@NonNull WordListAdapter.WordViewHolder holder, int position) {
String mCurrent = mWordList.get(position);
holder.wordItemView.setText(mCurrent);
}
@Override
public int getItemCount () {
return mWordList.size();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment