material-components-android icon indicating copy to clipboard operation
material-components-android copied to clipboard

[Lists] Added initial MaterialListItem implementation

Open etlhsu opened this issue 5 years ago • 3 comments
trafficstars

MaterialListItem is an adaptive view holder for RecyclerView lists that makes list items easy.

After initialization, developers are given a pre-built list item. From here, they can enable any element (visual, text, meta etc.) using setVisibility() and set its contents as usual.

Internally, MaterialListItem splits the list item into three separate parts. Each part is implemented as a custom View and handles certain functionality for the list item:

  • Visual - A dynamically-shaped visual (image) seen at the start of some list items.

  • TextCollection - A View that controls the overline, primary and secondary texts.

  • SecondaryContent - Controls the secondary action of the list, either a piece of metadata (text) or a customizable FrameLayout

In addition, MaterialListItem automatically changes depending on whether it is a single-line, two line or three line item. Here is the process that takes place to do such:

  1. TextCollection dynamically calculates the "total lines" of text it uses (single, two or three line typically).

  2. Using a TotalLinesListener, its parent MaterialListItem then observes the total lines and is able to share the total lines with its three child elements.

  3. All three views adjust their view properties to match the Material spec for single-line, two and three line items.

Based on @dsn5ft's recommendations from #1092, Lists now has a single, adaptive MaterialListItem (yay). I spent a lot of time optimizing the internals and tweaking the list item to fit the Material spec so I hope this approach is best for the component!

Example: https://drive.google.com/file/d/1IXp38AiJsrVEWbKO8ql1tVZj0KlE9O7K/view?usp=sharing

API Usage:


@Override
    public MaterialListItem onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        
        //Initialize new list item
        MaterialListItem item = new MaterialListItem(parent);
        
        //Enable and configure the wanted elements
        item.getVisual().setVisibility(View.VISIBLE);
        item.getVisual().setType(Visual.CIRCLE);
        item.getPrimaryText().setVisibility(View.VISIBLE);
        item.getSecondaryContent().getAction().setVisibility(View.VISIBLE);
        item.getSecondaryContent().getAction().addView(...);
    }

@Override
    public void onBindViewHolder(@NonNull MaterialListItem item, int position) {
        
        //Customize the contents of the list item based on data
        item.getVisual().setImageDrawable(...);
        item.getPrimaryText().setText(...);
}

This PR is the start of an amazing journey, and I do have improvements planned for MaterialListItem. However, I am not in sync with your team's roadmap, so feel free to tell me if I should add anything else to this pull request. I intentionally left some parts out and believe they are better reserved for their own PRs:

  • As seen with the code examples above, the API is a little rough. In the next PR, I hope to have Views automatically control their visibility depending on their contents. For example, a TextView would be VISIBLE if it was displaying text, and automatically be GONE if it has no text. This would remove all of the setVisibility() calls and make adoption a bit easier.
  • After the public API has been established, I would like to write documentation to cover public methods, and document important internals.
  • In order for this component to be production-ready, MaterialListItem will need UI tests.

If you feel that one of these features should be included in this PR, I am happy to add it in 😉

etlhsu avatar May 30 '20 08:05 etlhsu