Customising RecyclerViews according to position +/- orientation

If wanting to set differing layouts for a RecyclerView in a particular ViewHolder position +/- orientation (portrait or landscape), you can do the following:

Use the values, values-port and values-land folders to set booleans (or other) to indicate your preferences for layout according to orientation e.g. in values-port\bools.xml add

<bool name="use_expanded_layout">false</bool>

to state that you do not want to use your expanded layout in portrait mode (if desired).
Overriding getViewType will give you the position of the ViewHolder by which you can conditionally set which viewType to use. In your RecyclerView.Adapter file:

private final int CONDENSED_VIEWTYPE_ID = 83; // Randomly generated unique ID to correspond to condensed layout
private final int EXPANDED_VIEWTYPE_ID = 928; // Randomly generated unique ID to correspond to expanded layout
private boolean mUseExpandedLayout; // Declare a variable to determine layout preference
private final Context mContext; // We'll need this

    public RecyclerViewAdapter(@NonNull Context context, RecyclerViewAdapterOnClickHandler clickHandler) { // In the constructor...
        ...
        mContext = context;
        mUseExpandedLayout= context.getResources().getBoolean(R.bool.use_expanded_layout); // ... get the preference from your boolean. If in portrait orientation it will take this value from the values-port\bools.xml file if it exists, otherwise the values\bools.xml file
    }

    @Override
    public int getItemViewType(int position) { // Override getViewType, which gives you the ViewHolder position
        if (!mExpandedLayout || position != 0) { // Use this position to determine which viewType to apply. Here, if the boolean is false or position is not 0...
            return CONDENSED_VIEWTYPE_ID; // ...use the condensed viewType
        }
        return EXPANDED_VIEWTYPE_ID; // Otherwise use the expanded viewType
    }

    @Override
    public RecyclerViewAdapterViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { // In the onCreateViewHolder override...

        View view;

        if (viewType == CONDENSED_VIEWTYPE_ID) { // ...if the viewType has the condensed ID...
            view = LayoutInflater
                    .from(mContext)
                    .inflate(R.layout.condensed_list_item, viewGroup, false); // ...apply the condensed layout
        } else if (viewType == EXPANDED_VIEWTYPE_ID) { // If the viewType has the expanded ID...
            view = LayoutInflater
                    .from(mContext)
                    .inflate(R.layout.expanded_list_item, viewGroup, false); // ...apply the expanded layout
        } else {
            throw new IllegalArgumentException("Invalid layout type");
        }

        return new RecyclerViewAdapterViewHolder(view); // Creates the ViewHolder with the appropriate layout attached
    }

ClickListener on list Adapter

Add a ClickListener to a ListAdapter, in this case a RecyclerView.Adapter.

Within list Adapter class (called ItemListAdapter in this example):
    private final ListItemClickListener mOnClickListener; // Declare field for OnClickListener
    public interface ListItemClickListener { // Create custom interface for your OnClickListener
        void onListItemClick (int item);
    }
    public ItemListAdapter(int numberOfItems, ListItemClickListener listItemClickListener) { // Add as parameter to Adapter constructor
        mNumberItems = numberOfItems;
        mOnClickListener = listItemClickListener;
    }
    class NumberViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { // In class that generates item View implement View.OnClickListener
        public NumberViewHolder(View itemView) {
            super(itemView);
            itemView.setOnClickListener(this); // Set an
        }
        @Override // Override onClick
        public void onClick(View v) {
            mOnClickListener.onListItemClick(getAdapterPosition()); // Call custom interface instance
        }
    }

Within Activity.

public class MainActivity extends AppCompatActivity implements ItemListAdapter.ListItemClickListener { // Implement the custom interface
        mAdapter = new ItemListAdapter(NUM_LIST_ITEMS, this); // Second parameter produces custom OnClickListener in constructor
    @Override // Override the onListItemClick from the custom interface
    public void onListItemClick(int item) {
        if (mToast != null) {
            mToast.cancel();
        }
        Context context = this;
        CharSequence text = "Item number: " + item;
        int duration = Toast.LENGTH_SHORT;
        mToast = Toast.makeText(context, text, duration);
        mToast.show();
    }
}

ud851-Exercises-student\Lesson03-Green-Recycler-View\T03.07-Exercise-RecyclerViewClickHandling
ud851-Sunshine-student\ud851-Sunshine-student\S03.02-Exercise-RecyclerViewClickHandling

Configure RecyclerView with Adapter, ViewHolder & LayoutManager

***ListView is outdated. Use this instead***
The Adapter acquires data from some source, stores the data in a ViewHolder (which holds a findViewById reference to the root View object for the item), caching the View objects represented in the layout. The number of ViewHolders created will equal the number of Views that can fit on the device screen plus a couple above and a couple below (approx) off-screen to make the recycling smooth. Therefore findViewById is only called when these Views are created and not for every item in the list of data.
A LinearLayoutManager is responsible for measuring and positioning item views within a RecyclerView into a linear list. This means that it can produce either a horizontal or vertical list depending on which parameter you pass in to the LinearLayoutManager constructor. It will take old Views which have scrolled off-screen and repopulate them with the new data from the ViewHolders.

This example demonstrates View recycling by showing a list (0-99) with the number on the LHS of the item View, and on the RHS the index of the ViewHolder. In the case of Nexus 6 there are 11 (0-10) of these, along with a green-shaded background of varying saturation to visually enforce the concept. Create an Adapter class.

// Avoid unnecessary garbage collection by using RecyclerView and ViewHolders.
public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.NumberViewHolder> {

    private static final String TAG = RecyclerAdapter.class.getSimpleName(); // Standard practice for logging

    /*
     * The number of ViewHolders that have been created. Typically, you can figure out how many
     * there should be by determining how many list items fit on your screen at once and add 2 to 4
     * to that number. That isn't the exact formula, but will give you an idea of how many
     * ViewHolders have been created to display any given RecyclerView.
     *
     * Here's some ASCII art to hopefully help you understand:
     *
     *    ViewHolders on screen:
     *
     *        *-----------------------------*
     *        |         ViewHolder index: 0 |
     *        *-----------------------------*
     *        |         ViewHolder index: 1 |
     *        *-----------------------------*
     *        |         ViewHolder index: 2 |
     *        *-----------------------------*
     *        |         ViewHolder index: 3 |
     *        *-----------------------------*
     *        |         ViewHolder index: 4 |
     *        *-----------------------------*
     *        |         ViewHolder index: 5 |
     *        *-----------------------------*
     *        |         ViewHolder index: 6 |
     *        *-----------------------------*
     *        |         ViewHolder index: 7 |
     *        *-----------------------------*
     *
     *    Extra ViewHolders (off screen)
     *
     *        *-----------------------------*
     *        |         ViewHolder index: 8 |
     *        *-----------------------------*
     *        |         ViewHolder index: 9 |
     *        *-----------------------------*
     *        |         ViewHolder index: 10|
     *        *-----------------------------*
     *        |         ViewHolder index: 11|
     *        *-----------------------------*
     *
     *    Total number of ViewHolders = 11
     */
    private static int viewHolderCount;

    private int mNumberItems;

    /**
     * Constructor for RecyclerAdapter that accepts a number of items to display
     *
     * @param numberOfItems Number of items to display in list
     */
    public RecyclerAdapter(int numberOfItems) {
        mNumberItems = numberOfItems;
        viewHolderCount = 0;
    }

    /**
     *
     * This gets called when each new ViewHolder is created. This happens when the RecyclerView
     * is laid out. Enough ViewHolders will be created to fill the screen and allow for scrolling.
     *
     * @param viewGroup The ViewGroup that these ViewHolders are contained within.
     * @param viewType  If your RecyclerView has more than one type of item (which ours doesn't) you
     *                  can use this viewType integer to provide a different layout. See
     *                  {@link android.support.v7.widget.RecyclerView.Adapter#getItemViewType(int)}
     *                  for more details.
     * @return A new NumberViewHolder that holds the View for each list item
     */
    @Override
    public NumberViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
        int layoutIdForListItem = R.layout.number_list_item; // number_list_item = layout xml for each item View
        Context context = viewGroup.getContext();
        LayoutInflater inflater = LayoutInflater.from(context);
        boolean shouldAttachToParentImmediately = false;

        View view = inflater.inflate(layoutIdForListItem, viewGroup, shouldAttachToParentImmediately);
        NumberViewHolder viewHolder = new NumberViewHolder(view); // NumberViewHolder is a ViewHolder class we have defined below

        viewHolder.viewHolderIndex.setText("ViewHolder index: " + viewHolderCount); // Prints out the index number of the ViewHolder that is currently being used

        int backgroundColorForViewHolder = ColorUtils
                .getViewHolderBackgroundColorFromInstance(context, viewHolderCount); // This function exists in a separate class
        viewHolder.itemView.setBackgroundColor(backgroundColorForViewHolder); // Sets varying saturation of green as background for visual impact

        viewHolderCount++;
        Log.d(TAG, "onCreateViewHolder: number of ViewHolders created: "
                + viewHolderCount); // Prints number of ViewHolders to Log.d
        return viewHolder;
    }

    /**
     * OnBindViewHolder is called by the RecyclerView to display the data at the specified
     * position. In this method, we update the contents of the ViewHolder to display the correct
     * indices in the list for this particular position, using the "position" argument that is conveniently
     * passed into us.
     *
     * @param holder   The ViewHolder which should be updated to represent the contents of the
     *                 item at the given position in the data set.
     * @param position The position of the item within the adapter's data set.
     */
    @Override
    public void onBindViewHolder(NumberViewHolder holder, int position) {
        Log.d(TAG, "#" + position); // Prints Viewholder index to Log.d as Views are recycled
        holder.bind(position); // Binds the index number (0-99) to the ViewHolder (see bind function below)
    }

    /**
     * This method simply returns the number of items to display. It is used behind the scenes
     * to help layout our Views and for animations.
     *
     * @return The number of items available
     */
    @Override
    public int getItemCount() {
        return mNumberItems;
    }

    /**
     * Cache of the children views for a list item.
     */
    class NumberViewHolder extends RecyclerView.ViewHolder {

        // Will display the position in the list, ie 0 through getItemCount() - 1
        TextView listItemNumberView;
        // Will display which ViewHolder is displaying this data
        TextView viewHolderIndex;

        /**
         * Constructor for our ViewHolder. Within this constructor, we get a reference to our
         * TextViews.
         * @param itemView The View that you inflated in
         *                 {@link RecyclerAdapter#onCreateViewHolder(ViewGroup, int)}
         */
        public NumberViewHolder(View itemView) {
            super(itemView);

            listItemNumberView = (TextView) itemView.findViewById(R.id.tv_item_number); // Reference to TextView on LHS of View
            viewHolderIndex = (TextView) itemView.findViewById(R.id.tv_view_holder_instance); // Reference to TextView on RHS of View
        }

        /**
         * A method we wrote for convenience. This method will take an integer as input and
         * use that integer to display the appropriate text within a list item.
         * @param listIndex Position of the item in the list
         */
        void bind(int listIndex) {
            listItemNumberView.setText(String.valueOf(listIndex)); // Sets the item number (0-99) to the TextView on LHS of item View
        }
    }
}

Add relevant code to Activity.

public class MainActivity extends AppCompatActivity {

    private static final int NUM_LIST_ITEMS = 100; //Sets number of list items to 100

    /*
     * References to RecyclerView and Adapter
     */
    private RecyclerAdapter mAdapter;
    private RecyclerView mNumbersList;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /*
         * Using findViewById, we get a reference to our RecyclerView from xml. This allows us to
         * do things like set the adapter of the RecyclerView and toggle the visibility.
         */
        mNumbersList = (RecyclerView) findViewById(R.id.rv_numbers);

        /*
         * A LinearLayoutManager is responsible for measuring and positioning item views within a
         * RecyclerView into a linear list. This means that it can produce either a horizontal or
         * vertical list depending on which parameter you pass in to the LinearLayoutManager
         * constructor. By default, if you don't specify an orientation, you get a vertical list.
         * In our case, we want a vertical list, so we don't need to pass in an orientation flag to
         * the LinearLayoutManager constructor.
         *
         * There are other LayoutManagers available to display your data in uniform grids,
         * staggered grids, and more! See the developer documentation for more details.
         */
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mNumbersList.setLayoutManager(layoutManager);

        /*
         * Use this setting to improve performance if you know that changes in content do not
         * change the child layout size in the RecyclerView
         */
        mNumbersList.setHasFixedSize(true);

        /*
         * The RecyclerAdapter is responsible for displaying each item in the list.
         */
        mAdapter = new RecyclerAdapter(NUM_LIST_ITEMS);
        mNumbersList.setAdapter(mAdapter);
    }
}

ud851-Exercises-student\Lesson03-Green-Recycler-View\T03.07-Exercise-RecyclerViewClickHandling