Skip to content

Commit

Permalink
Merge pull request #6 from manneohlund/rc-2.2.0
Browse files Browse the repository at this point in the history
Rc 2.2.0
  • Loading branch information
manneohlund authored Jul 31, 2019
2 parents cdfee5a + 3319cc7 commit 8b78ac4
Show file tree
Hide file tree
Showing 24 changed files with 464 additions and 53 deletions.
35 changes: 33 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ allprojects {
#### Step 2. Add the dependency
```groovy
dependencies {
implementation 'com.github.manneohlund:smart-recycler-adapter:2.1.0'
implementation 'com.github.manneohlund:smart-recycler-adapter:2.2.0'
}
```

Expand Down Expand Up @@ -172,7 +172,38 @@ SmartRecyclerAdapter
(view, actionId, position) -> openMovieInfo())
.into(recyclerView);
```


### SmartEndlessScrollRecyclerAdapter

A popular feature in apps is to have endless scrolling with pagination, in other words load more items when user has scrolled to bottom.
With SmartEndlessScrollRecyclerAdapter you can achieve this.

#### 1. Create adapter
```java
SmartEndlessScrollRecyclerAdapter endlessScrollAdapter = SmartEndlessScrollRecyclerAdapter
.items(items)
.map(MovieModel.class, MovieViewHolder.class)
.into(recyclerView);
```

#### 2. Set OnLoadMoreListener to your SmartEndlessScrollRecyclerAdapter

Called when scrolled to the last item and loading view is visible.

```java
endlessScrollAdapter.setOnLoadMoreListener(() -> {
endlessScrollAdapter.addItems(moreItems);
});
```

#### More SmartEndlessScrollRecyclerAdapter features

Enable/Disable endless scrolling and thus removing the loading view.
`endlessScrollAdapter.setEndlessScrollEnabled(false);`

You can also set your custom loading/loadmore view.
`endlessScrollAdapter.setCustomLoadMoreLayoutResource(R.layout.your_custom_loadmore_view);`

### Adapter creation with ViewTypeResolver

If you want to bind one data type with different view holders depending on some attribute you can set a ViewTypeResolver.
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ buildscript {
allprojects {
// Smart Adapter global version code and name
ext {
VERSION_CODE = 7
VERSION_NAME = '2.1.0'
VERSION_CODE = 8
VERSION_NAME = '2.2.0'
TARGET_SDK_VERSION = 28
MIN_SDK_VERSION = 14
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
Expand Down Expand Up @@ -43,13 +44,14 @@
import java.util.List;
import java.util.Locale;

import smartadapter.SmartEndlessScrollRecyclerAdapter;
import smartadapter.SmartRecyclerAdapter;

public class DemoActivity extends AppCompatActivity {

RecyclerView recyclerView;
SmartRecyclerAdapter mainSmartMovieAdapter;
SmartRecyclerAdapter comingSoonSmartMovieAdapter;
SmartEndlessScrollRecyclerAdapter mainSmartMovieAdapter;
SmartEndlessScrollRecyclerAdapter comingSoonSmartMovieAdapter;
SmartRecyclerAdapter myWatchListSmartMovieAdapter;
SmartRecyclerAdapter actionMoviesSmartMovieAdapter;
SmartRecyclerAdapter adventuresMoviesSmartMovieAdapter;
Expand Down Expand Up @@ -84,7 +86,7 @@ private void initSmartRecyclerAdapter() {
items.add(new RecentlyPlayedMoviesModel("Recently played"));
items.add(new CopyrightModel(String.format("SmartRecyclerAdapter v%s\n\nDeveloped by Manne Öhlund", BuildConfig.VERSION_NAME)));

mainSmartMovieAdapter = SmartRecyclerAdapter
mainSmartMovieAdapter = SmartEndlessScrollRecyclerAdapter
.items(items)
.map(MoviePosterModel.class, PosterViewHolder.class)
.map(MovieBannerModel.class, BannerViewHolder.class)
Expand Down Expand Up @@ -184,10 +186,25 @@ private void initSmartRecyclerAdapter() {
.map(RecentlyPlayedMoviesViewHolder.class, recentlyPlayedMoviesSmartMovieAdapter)

.into(recyclerView);

// Endless pagination
mainSmartMovieAdapter.setOnLoadMoreListener(() -> {
Toast.makeText(getApplicationContext(), "LoadMore", Toast.LENGTH_SHORT).show();

int indexBeforeCopyright = 2;
new Handler().postDelayed(() -> {
mainSmartMovieAdapter.addItem(
mainSmartMovieAdapter.getItemCount() - indexBeforeCopyright,
new MovieBannerModel("More items loaded", MovieDataItems.INSTANCE.getRandomBanner())
);
},
800);
});
}

int moreItemsLoadedCount = 0;
private void initNestedSmartRecyclerAdapters() {
comingSoonSmartMovieAdapter = SmartRecyclerAdapter.items(MovieDataItems.INSTANCE.getComingSoonItems())
comingSoonSmartMovieAdapter = SmartEndlessScrollRecyclerAdapter.items(MovieDataItems.INSTANCE.getComingSoonItems())
.map(MovieModel.class, LargeThumbViewHolder.class)
.addViewEventListener(
LargeThumbViewHolder.class,
Expand All @@ -203,6 +220,24 @@ private void initNestedSmartRecyclerAdapters() {
})
.create();

// Set custom load more view
comingSoonSmartMovieAdapter.setCustomLoadMoreLayoutResource(R.layout.custom_loadmore_view);

// Pagination ends after 3 loads
comingSoonSmartMovieAdapter.setOnLoadMoreListener(() -> {
Toast.makeText(getApplicationContext(), "LoadMore", Toast.LENGTH_SHORT).show();

new Handler().postDelayed(() -> {
comingSoonSmartMovieAdapter.addItems(
comingSoonSmartMovieAdapter.getItemCount()-1,
MovieDataItems.INSTANCE.getLoadMoreItems()
);
if (moreItemsLoadedCount++ == 2)
comingSoonSmartMovieAdapter.setEndlessScrollEnabled(false);
},
1000);
});

myWatchListSmartMovieAdapter = SmartRecyclerAdapter.items(MovieDataItems.INSTANCE.getMyWatchListItems())
.map(MovieModel.class, ThumbViewHolder.class)
.addViewEventListener(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.smartrecycleradapter

import android.os.Bundle
import android.os.Handler
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.GridLayoutManager
import android.widget.Toast
Expand All @@ -10,8 +11,8 @@ import com.example.smartrecycleradapter.models.MovieModel
import com.example.smartrecycleradapter.viewholder.HeaderViewHolder
import com.example.smartrecycleradapter.viewholder.ThumbViewHolder
import kotlinx.android.synthetic.main.activity_movie_category_details.*
import smartadapter.SmartEndlessScrollRecyclerAdapter
import smartadapter.SmartRecyclerAdapter
import java.util.Arrays.asList

enum class MovieType(val title: String) {
COMING_SOON("Coming soon"),
Expand All @@ -24,14 +25,15 @@ enum class MovieType(val title: String) {

class MovieCategoryDetailsActivity : AppCompatActivity() {

private lateinit var movieType: MovieType;
private lateinit var movieType: MovieType
private var endlessScrollCount = 0

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_movie_category_details)

intent?.getIntExtra("MovieType", MovieType.ANIMATED.ordinal)?.let {
movieType = MovieType.values()[it];
movieType = MovieType.values()[it]
}

initSmartRecyclerAdapter()
Expand All @@ -45,11 +47,10 @@ class MovieCategoryDetailsActivity : AppCompatActivity() {
MovieType.ADVENTURE -> MovieDataItems.nestedAdventureItems
MovieType.ANIMATED -> MovieDataItems.nestedAnimatedItems
MovieType.SCI_FI -> MovieDataItems.nestedSciFiItems
else -> asList()
}

val adapterItems: ArrayList<Any> = ArrayList<Any>()
adapterItems.add(movieType.title);
adapterItems.add(movieType.title)
adapterItems.addAll(movieItems)

val gridAutoLayoutManager = GridAutoLayoutManager(this, 100)
Expand All @@ -59,13 +60,43 @@ class MovieCategoryDetailsActivity : AppCompatActivity() {
}
}

SmartRecyclerAdapter.items(adapterItems)
.map(String::class.java, HeaderViewHolder::class.java)
.map(MovieModel::class.java, ThumbViewHolder::class.java)
.setLayoutManager(gridAutoLayoutManager)
.addViewEventListener(ThumbViewHolder::class.java, R.id.action_on_click) { view, actionId, position ->
Toast.makeText(this, "Movie $position", Toast.LENGTH_SHORT).show()
when (movieType) {
MovieType.COMING_SOON, MovieType.MY_WATCH_LIST -> {
SmartRecyclerAdapter.items(adapterItems)
.map(String::class.java, HeaderViewHolder::class.java)
.map(MovieModel::class.java, ThumbViewHolder::class.java)
.setLayoutManager(gridAutoLayoutManager)
.addViewEventListener(ThumbViewHolder::class.java, R.id.action_on_click) { view, actionId, position ->
Toast.makeText(this, "Movie $position", Toast.LENGTH_SHORT).show()
}
.into(recyclerView)
}
MovieType.ACTION, MovieType.ADVENTURE,MovieType.ANIMATED, MovieType.SCI_FI -> {
val endlessScrollAdapter: SmartEndlessScrollRecyclerAdapter = SmartEndlessScrollRecyclerAdapter.items(adapterItems)
.map(String::class.java, HeaderViewHolder::class.java)
.map(MovieModel::class.java, ThumbViewHolder::class.java)
.setLayoutManager(gridAutoLayoutManager)
.addViewEventListener(ThumbViewHolder::class.java, R.id.action_on_click) { view, actionId, position ->
Toast.makeText(this, "Movie $position", Toast.LENGTH_SHORT).show()
}
.into(recyclerView)

endlessScrollAdapter.setOnLoadMoreListener {
if (!endlessScrollAdapter.isLoading) {
endlessScrollAdapter.setIsLoading(true)
Toast.makeText(applicationContext, "LoadMore", Toast.LENGTH_SHORT).show()

Handler().postDelayed({
endlessScrollAdapter.addItems(movieItems)
if (endlessScrollCount++ == 3) {
endlessScrollAdapter.setEndlessScrollEnabled(false);
}
endlessScrollAdapter.setIsLoading(false)
},
3000)
}
}
.into(recyclerView)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object MovieDataItems {
const val THUMBS_BASE_URL = "https://raw.githubusercontent.com/manneohlund/smart-recycler-adapter-resources/master/thumbs/"

// Coming soon
val comingSoonItems: List<Any> = asList(
val comingSoonItems: List<Any> = mutableListOf(
MovieModel("Fist man", "first_man"),
MovieModel("Terminator dark fate", "terminator_dark_fate"),
MovieModel("Murder Mystery", "murder_mystery"),
Expand All @@ -40,6 +40,23 @@ object MovieDataItems {
MovieModel("Abominable", "abominable")
)

// Load more items
val loadMoreItems: List<Any> = asList(
MovieModel("Terminator dark fate", "terminator_dark_fate"),
MovieModel("Joker", "joker"),
MovieModel("Fist man", "first_man"),
MovieModel("The Lion king", "lion_king"),
MovieModel("John Wick 3", "john_wick_3"),
MovieModel("Grinch", "grinch"),
MovieModel("Wonder Woman", "woderwoman"),
MovieModel("Hellboy", "hellboy"),
MovieModel("Predator", "predator"),
MovieModel("It 2", "it_2"),
MovieModel("Once upon a time in Hollywood", "once_hollywood"),
MovieModel("Age of uprising", "age_of_uprising"),
MovieModel("Murder Mystery", "murder_mystery")
)

// My watchlist
val myWatchListItems: List<Any> = mutableListOf(
MovieModel("Joker", "joker"),
Expand Down
8 changes: 8 additions & 0 deletions sample/src/main/res/layout/custom_loadmore_view.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<ProgressBar xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/progressBar"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="160dp"
android:layout_height="240dp"
android:layout_gravity="center"
android:padding="60dp" />
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package smartadapter;

/*
* Created by Manne Öhlund on 2019-07-29.
* Copyright (c) All rights reserved.
*/

import android.support.annotation.LayoutRes;
import android.support.annotation.NonNull;

import smartadapter.listener.OnLoadMoreListener;

/**
* Defines the extension methods for {@link SmartEndlessScrollRecyclerAdapter}.
*/
public interface ISmartEndlessScrollRecyclerAdapter {

/**
* Used to determine if loading view should show or not.
* If {@link #isEndlessScrollEnabled()} returns true this returns 1.
* @return offset loading view count
*/
int getEndlessScrollOffset();

/**
* Checks if endless scrolling is enabled.
* @return endless scrolling enabled
*/
boolean isEndlessScrollEnabled();

/**
* Setter for enabling endless scrolling by letting the {@link SmartEndlessScrollRecyclerAdapter} render a loading view.
* @param enabled if true enables endless scrolling.
*/
void setEndlessScrollEnabled(boolean enabled);

/**
* Checks if the {@link SmartEndlessScrollRecyclerAdapter} is in loading state.
* Good to use when async loading takes time and user scrolls back and forth.
* @return loading state
*/
boolean isLoading();

/**
* Setting the loading state to {@link SmartEndlessScrollRecyclerAdapter}.
* @param loading state for loading more items
*/
void setIsLoading(boolean loading);

/**
* Setter for {@link OnLoadMoreListener} callback for listening on when the {@link SmartEndlessScrollRecyclerAdapter}
* is showing the {@link smartadapter.viewholder.LoadMoreViewHolder}.
* @param onLoadMoreListener load more callback
*/
void setOnLoadMoreListener(@NonNull OnLoadMoreListener onLoadMoreListener);

/**
* Enables customization of the layout for the {@link smartadapter.viewholder.LoadMoreViewHolder}.
* @param loadMoreLayoutResource layout resource
*/
void setCustomLoadMoreLayoutResource(@LayoutRes int loadMoreLayoutResource);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import java.util.HashMap;
import java.util.List;

import smartadapter.internal.Mapper;
import smartadapter.internal.mapper.ViewHolderMapper;
import smartadapter.listener.ViewEventListener;
import smartadapter.viewholder.SmartViewHolder;
import smartadapter.widget.ViewTypeResolver;
Expand Down Expand Up @@ -230,9 +230,9 @@ public interface ISmartRecyclerAdapter {

/**
* Returns the data item view holder mapper.
* @return Mapper
* @return ViewHolderMapper
*/
Mapper getMapper();
ViewHolderMapper getMapper();

/**
* Returns {@link ViewTypeResolver}.
Expand Down
Loading

0 comments on commit 8b78ac4

Please sign in to comment.