diff --git a/README.md b/README.md index 70fe1e0..8793e25 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -## A RecyclerView that is powered by Realm +# A RecyclerView that is powered by Realm -A powerful Recyclerview wrapper when working with Realm as your datastore. It supports the following out of the box: +A powerful ```Recyclerview``` wrapper for working with ```Realm``` as your datastore. It supports the following features out of the box: * Custom adapter that automatically refreshes the list when the realm changes and animates the new items in. * Empty state -* Optional pull-to-refresh (backed by SwipeRefreshLayout) +* Pull-to-refresh (backed by SwipeRefreshLayout) * Infinite scrolling (callback for more data fetching) -* Section headers +* Section headers (backed by SuperSLiM) -###How To Include It: +##How To Include It: ``` repositories { @@ -23,6 +23,73 @@ A powerful Recyclerview wrapper when working with Realm as your datastore. It su } ``` -###Demo +##Demo -![Screenshot](https://raw.githubusercontent.com/thorbenprimke/realm-recyclerview/master/extra/screenshot-demo-app.gif) \ No newline at end of file +![Screenshot](https://raw.githubusercontent.com/thorbenprimke/realm-recyclerview/master/extra/screenshot-demo-app.gif) + +## How To Get Started: + +The ```RealmRecyclerView``` has a few attributes that can be set in XML in order to customize it's look and feel and most importanlty which layoutType is used. In addition, it relies on an extended ```RecyclerView.Adapter``` called ```RealmBasedRecyclerViewAdapter``` to provide support for animation and headers. + +##RealmRecyclerView + +The snippet below shows how to include the ```RealmRecyclerView``` in your layout file. + +``` + +``` + +Important to note here is that the ```app:rrvLayoutType``` attribute has to be set. It determines which ```LayoutManager``` will be used. The options are: + +* ```LinearLayout``` +* ```Grid``` +* ```LinearLayoutWithHeaders``` + +All these will yield vertical linear or grid layouts. + +###Other Attributes: + +```rrvIsRefreshable```: Adds the pull-to-refresh feature to the ```recyclerView```. In order to receive the refresh events, a listner has to be set via ```setOnRefreshListener``` and ```setRefreshing``` is used to control either turn the refersh animation on/off. + +```rrvEmptyLayoutId```: A custom empty state view can be provided via this attribute. Whenever the list has no item, the empty state is shown. + +```rrvGridLayoutSpanCount```: This attribute has to be set with an integer greater than zero when the ```rrvLayoutType``` is set to ```Grid```. + +##RealmBasedRecyclerViewAdapter: + +The heart of the ```RealmRecyclerView```'s functionality comes from this custom ```RecyclerView.Adapter```. It includes support for insertion/deletion animation whenever the ```Realm``` changes. It also inculde the logic to generate the headers for the list's contents if it's of type ```LinearLayoutWithHeaders```. + +* ```automaticUpdate```: If automaticUpdate is set, the ```RealmResults``` are automatially updated and the list is refershed with new results. + +* ```animateResults```: If animateResults is set together with automaticUpdate, the automatic updates are animated. This is limited to a single deletion or insertion. If it's more than one item, it will simply refresh the list. The animation leverages the resuls primary key column in order as a unique identifier for each row. Therefore your ```Realm```'s schema needs to include a primary key column of type ```Integer``` or ```String```. + +* ```addSectionHeaders```: When the ```rrvLayoutType``` is ```LinearLayoutWithHeaders```, addSectionHeaders needs be set in order for the adapter to generate the headers. The ```headerColumnName``` needs to be set as well in order to look up the header column programmatically your ```Realm```'s schema. *Note: There is currently no support for customizing the header and it is always inline|sticky.* + +##Feedback/More Features: +I would love to hear your feedback. Do you find the ```RealmRecyclerView``` useful? What functionality are you missing? Open a ```Github``` issue and let me know. Thanks! + + +## License +``` +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +Included dependencies are: +Copyright (C) SuperSLiM/Tonic Artos (https://github.com/TonicArtos/SuperSLiM) +``` \ No newline at end of file diff --git a/example/app/build.gradle b/example/app/build.gradle index 714457a..460ae91 100644 --- a/example/app/build.gradle +++ b/example/app/build.gradle @@ -27,6 +27,6 @@ dependencies { compile 'com.android.support:recyclerview-v7:22.0.+' -// compile project(':library') - compile 'com.github.thorbenprimke:realm-recyclerview:0.9' + compile project(':library') +// compile 'com.github.thorbenprimke:realm-recyclerview:0.9' } diff --git a/library/src/main/java/co/moonmonkeylabs/realmrecyclerview/RealmRecyclerView.java b/library/src/main/java/co/moonmonkeylabs/realmrecyclerview/RealmRecyclerView.java index ff732ce..b3d892f 100644 --- a/library/src/main/java/co/moonmonkeylabs/realmrecyclerview/RealmRecyclerView.java +++ b/library/src/main/java/co/moonmonkeylabs/realmrecyclerview/RealmRecyclerView.java @@ -109,6 +109,9 @@ private void init(Context context, AttributeSet attrs) { case LinearLayoutWithHeaders: recyclerView.setLayoutManager(new LayoutManager(getContext())); break; + + default: + throw new IllegalStateException("The type attribute has to be set."); } recyclerView.setHasFixedSize(true); @@ -266,13 +269,6 @@ private void updateEmptyContentContainerVisibility(RecyclerView.Adapter adapter) // Pull-to-refresh // - /** - * Only if custom is set for the manager, this method should be used to set the manager. - */ - public void setLayoutManager(RecyclerView.LayoutManager layoutManger) { - recyclerView.setLayoutManager(layoutManger); - } - public void setOnRefreshListener(OnRefreshListener onRefreshListener) { this.onRefreshListener = onRefreshListener; } diff --git a/library/src/main/java/io/realm/RealmBasedRecyclerViewAdapter.java b/library/src/main/java/io/realm/RealmBasedRecyclerViewAdapter.java index d0e56ed..fd23d28 100644 --- a/library/src/main/java/io/realm/RealmBasedRecyclerViewAdapter.java +++ b/library/src/main/java/io/realm/RealmBasedRecyclerViewAdapter.java @@ -19,6 +19,7 @@ import android.content.Context; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Adapter; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -34,26 +35,21 @@ import co.moonmonkeylabs.realmrecyclerview.LoadMoreListItemView; import co.moonmonkeylabs.realmrecyclerview.R; +import co.moonmonkeylabs.realmrecyclerview.RealmRecyclerView; import difflib.Delta; import difflib.DiffUtils; import difflib.Patch; import io.realm.internal.ColumnType; import io.realm.internal.TableOrView; +/** + * The base {@link RecyclerView.Adapter} that includes custom functionality to be used with the + * {@link RealmRecyclerView}. + */ public abstract class RealmBasedRecyclerViewAdapter extends RecyclerView.Adapter { - public void addLoadMore() { - loadMoreItem = new Object(); - notifyDataSetChanged(); - } - - public void removeLoadMore() { - loadMoreItem = null; - notifyDataSetChanged(); - } - public class RowWrapper { public final boolean isRealm; @@ -154,6 +150,10 @@ public RealmBasedRecyclerViewAdapter( public abstract VH convertViewHolder(RealmViewHolder viewHolder); + /** + * DON'T OVERRIDE THIS METHOD. Implement onCreateRealmViewHolder instead. + */ + @Override public RealmViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { if (viewType == HEADER_VIEW_TYPE) { View view = inflater.inflate(R.layout.header_item, viewGroup, false); @@ -164,13 +164,16 @@ public RealmViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { return onCreateRealmViewHolder(viewGroup, viewType); } + /** + * DON'T OVERRIDE THIS METHOD. Implement onBindRealmViewHolder instead. + */ @Override public void onBindViewHolder(RealmViewHolder holder, int position) { if (getItemViewType(position) == LOAD_MORE_VIEW_TYPE) { holder.loadMoreView.showSpinner(); } else { if (addSectionHeaders) { - final String header = (String) rowWrappers.get(position).header; + final String header = rowWrappers.get(position).header; final GridSLM.LayoutParams layoutParams = GridSLM.LayoutParams.from(holder.itemView.getLayoutParams()); // Setup the header @@ -234,8 +237,8 @@ public int getItemRealmViewType(int position) { } /** - * Update the RealmResults associated to the Adapter. Useful when the query has been changed. - * If the query does not change you might consider using the automaticUpdate feature + * Update the RealmResults associated with the Adapter. Useful when the query has been changed. + * If the query does not change you might consider using the automaticUpdate feature. * * @param queryResults the new RealmResults coming from the new query. */ @@ -258,7 +261,7 @@ public void updateRealmResults(RealmResults queryResults) { } /** - * Method that create the header string that should be used. Override this method to have + * Method that creates the header string that should be used. Override this method to have * a custom header. */ public String createHeaderFromColumnValue(String columnValue) { @@ -391,5 +394,27 @@ public void onChange() { } }; } + + /** + * Adds the LoadMore item. + */ + public void addLoadMore() { + if (loadMoreItem != null) { + return; + } + loadMoreItem = new Object(); + notifyDataSetChanged(); + } + + /** + * Removes the LoadMoreItems; + */ + public void removeLoadMore() { + if (loadMoreItem == null) { + return; + } + loadMoreItem = null; + notifyDataSetChanged(); + } } diff --git a/library/src/main/res/layout/header_item.xml b/library/src/main/res/layout/header_item.xml index 525b2d7..bc2ec85 100644 --- a/library/src/main/res/layout/header_item.xml +++ b/library/src/main/res/layout/header_item.xml @@ -3,16 +3,12 @@ android:id="@+id/text" 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="wrap_content" android:layout_height="wrap_content" android:gravity="start" - android:padding="16dip" - android:layoutDirection="locale" - android:textDirection="locale" + android:padding="16dp" android:textSize="24sp" app:slm_headerDisplay="inline|sticky" app:slm_isHeader="true" - app:slm_section_headerMarginStart="56dip" - tools:text="Header Item" + app:slm_section_headerMarginStart="56dp" />