From eda7bb8c85e44816b8eea4d66eec7aed90d6c50c Mon Sep 17 00:00:00 2001 From: Tamas Vegh Date: Mon, 14 Aug 2017 22:51:32 +0200 Subject: [PATCH 1/2] Add other shimmer implementation and new features from that implementation --- FACEBOOK_LICENSE.md | 13 - README.md | 36 +- .../cooltechworks/sample/DemoActivity.java | 29 +- .../cooltechworks/sample/MainActivity.java | 28 +- .../cooltechworks/sample/utils/BaseUtils.java | 66 +- .../sample/utils/DemoConfiguration.java | 62 + .../utils/view/CardPaddingItemDecoration.java | 22 + .../sample/viewholders/ItemHolder.java | 28 +- app/src/main/res/layout/activity_grid.xml | 1 + app/src/main/res/layout/activity_list.xml | 1 + app/src/main/res/layout/activity_main.xml | 44 +- .../main/res/layout/activity_second_grid.xml | 16 + .../main/res/layout/activity_second_list.xml | 16 + .../main/res/layout/layout_second_demo.xml | 123 ++ .../res/layout/layout_second_demo_grid.xml | 41 + .../res/layout/layout_second_news_card.xml | 68 ++ app/src/main/res/values/strings.xml | 3 +- screenshots/second_grid_demo.gif | Bin 0 -> 958458 bytes screenshots/second_list_demo.gif | Bin 0 -> 580277 bytes shimmer/build.gradle | 1 + .../views/shimmer/ShimmerAdapter.java | 28 +- .../views/shimmer/ShimmerRecyclerView.java | 25 +- .../views/shimmer/ShimmerViewHolder.java | 40 +- .../facebook/shimmer/ShimmerFrameLayout.java | 1080 ----------------- .../main/res/layout/viewholder_shimmer.xml | 17 +- shimmer/src/main/res/values/attrs.xml | 3 + shimmer/src/main/res/values/colors.xml | 6 + shimmer/src/main/res/values/shimmer_attrs.xml | 51 - shimmer/src/main/res/values/strings.xml | 4 + shimmer/src/main/res/values/values.xml | 23 - 30 files changed, 631 insertions(+), 1244 deletions(-) delete mode 100644 FACEBOOK_LICENSE.md create mode 100644 app/src/main/java/com/cooltechworks/sample/utils/DemoConfiguration.java create mode 100644 app/src/main/java/com/cooltechworks/sample/utils/view/CardPaddingItemDecoration.java create mode 100644 app/src/main/res/layout/activity_second_grid.xml create mode 100644 app/src/main/res/layout/activity_second_list.xml create mode 100644 app/src/main/res/layout/layout_second_demo.xml create mode 100644 app/src/main/res/layout/layout_second_demo_grid.xml create mode 100644 app/src/main/res/layout/layout_second_news_card.xml create mode 100644 screenshots/second_grid_demo.gif create mode 100644 screenshots/second_list_demo.gif delete mode 100644 shimmer/src/main/java/com/facebook/shimmer/ShimmerFrameLayout.java create mode 100644 shimmer/src/main/res/values/colors.xml delete mode 100644 shimmer/src/main/res/values/shimmer_attrs.xml create mode 100644 shimmer/src/main/res/values/strings.xml delete mode 100644 shimmer/src/main/res/values/values.xml diff --git a/FACEBOOK_LICENSE.md b/FACEBOOK_LICENSE.md deleted file mode 100644 index 15d4ea1..0000000 --- a/FACEBOOK_LICENSE.md +++ /dev/null @@ -1,13 +0,0 @@ -BSD License - -For shimmer-android software - -Copyright (c) 2015, Facebook, Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - -Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - -Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/README.md b/README.md index 094ef46..2e6cddf 100644 --- a/README.md +++ b/README.md @@ -11,21 +11,42 @@ A custom recycler view with shimmer views to indicate that views are loading. Th Demo Screen ------- +------ + +There are two kinds of shimmer animation which you can see here: + +1. This type of shimmer effect uses the whole ViewHolder item to animate on. | List Demo | Grid Demo | | ---------------------------- | ----------------------------- | | | | +2. Here the shimmer effect only applied on for those views which background color is nontransparent. + +| List Demo | Grid Demo | +| ---------------------------- | ----------------------------- | +| | | + + +### Shimmer effect types + +1. As you can see the first demo examples show that the whole ViewHolder item is animated. To achieve the desired effect, the children of the ShimmerLayout should have a nontransparent background. +2. You can achieve the second kind of shimmer effect by adding only one ViewGroup child to the ShimmerLayout with a transparent background. This ViewGroup will have the other views with nontransparent backgrounds on which the effect will be seen. + + You may wonder how can you add background to the root view of the ViewHolder, if you do not have direct access to the ShimmerLayout and the only child has a nontransparent background. The solution for this is to use the `shimmer_demo_view_holder_item_background` attribute. + ### Attributes and Methods Following are the attributes and methods to initialise the demo views. | XML Attributes | Java Methods | Explanation | | ------------- | ------------ | ----------- | -|```app:demo_child_count``` | ```setDemoChildCount(int)``` | Integer value that sets the number of demo views should be present in shimmer adapter | -|```app:demo_layout``` | ```setDemoLayoutReference(int)``` | Layout reference to your demo view. Define your my_demo_view.xml and refer the layout reference here. | -|```app:demo_layout_manager_type``` | ```setDemoLayoutManager(LayoutManagerType)``` | Layout manager of demo view. Can be one among linear_veritical or linear_horizontal or grid. | +|```app:shimmer_demo_child_count``` | ```setDemoChildCount(int)``` | Integer value that sets the number of demo views should be present in shimmer adapter. | +|```app:shimmer_demo_layout``` | ```setDemoLayoutReference(int)``` | Layout reference to your demo view. Define your my_demo_view.xml and refer the layout reference here. | +|```app:shimmer_demo_layout_manager_type``` | ```setDemoLayoutManager(LayoutManagerType)``` | Layout manager of demo view. Can be one among linear_vertical or linear_horizontal or grid. | +|```app:shimmer_demo_shimmer_color``` | ``` - ``` | Color reference or value. It can be used to change the color of the shimmer line. | +|```app:shimmer_demo_angle``` | ``` - ``` | Integer value between 0 and 30 which can modify the angle of the shimmer line. The default value is zero. | +|```app:shimmer_demo_view_holder_item_background``` | ``` - ``` | Color or an xml drawable for the ViewHolder background if you want to achieve the second type of shimmer effect. | @@ -44,6 +65,7 @@ Define your xml as: app:demo_grid_child_count="2" app:demo_layout="@layout/layout_demo_grid" app:demo_layout_manager_type="grid" + app:shimmer_demo_angle="20" /> ``` @@ -76,17 +98,17 @@ Developed By * Harish Sridharan - -Acknowledgements +Used libraries ---------------- -* Facebook for Shimmer Android which lies as a base for this repo. +* ShimmerLayout: the library which achieves the shimmer effect in a memory efficient way. License -------- The repo is released under following licenses Apache License for ShimmerRecycler
-BSD License for Facebook's Shimmer-Android +Apache License for ShimmerLayout diff --git a/app/src/main/java/com/cooltechworks/sample/DemoActivity.java b/app/src/main/java/com/cooltechworks/sample/DemoActivity.java index c29b90c..8a4909d 100644 --- a/app/src/main/java/com/cooltechworks/sample/DemoActivity.java +++ b/app/src/main/java/com/cooltechworks/sample/DemoActivity.java @@ -18,12 +18,11 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; -import android.support.v7.widget.GridLayoutManager; -import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import com.cooltechworks.sample.adapters.CardAdapter; import com.cooltechworks.sample.utils.BaseUtils; +import com.cooltechworks.sample.utils.DemoConfiguration; import com.cooltechworks.views.shimmer.ShimmerRecyclerView; public class DemoActivity extends AppCompatActivity { @@ -37,26 +36,21 @@ public class DemoActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - int type = getType(); + final int type = getType(); RecyclerView.LayoutManager layoutManager; - if (type == BaseUtils.TYPE_LIST) { - setTheme(R.style.AppTheme); - setContentView(R.layout.activity_list); - layoutManager = new LinearLayoutManager(this); - setTitle(R.string.ab_list_title); - - } else { - setTheme(R.style.AppThemeGrid); - setContentView(R.layout.activity_grid); - layoutManager = new GridLayoutManager(this, 2); - setTitle(R.string.ab_grid_title); - - } + final DemoConfiguration demoConfiguration = BaseUtils.getDemoConfiguration(type, this); + setTheme(demoConfiguration.getStyleResource()); + setContentView(demoConfiguration.getLayoutResource()); + layoutManager = demoConfiguration.getLayoutManager(); + setTitle(demoConfiguration.getTitleResource()); shimmerRecycler = (ShimmerRecyclerView) findViewById(R.id.shimmer_recycler_view); + if (demoConfiguration.getItemDecoration() != null) { + shimmerRecycler.addItemDecoration(demoConfiguration.getItemDecoration()); + } mAdapter = new CardAdapter(); mAdapter.setType(type); @@ -70,8 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { public void run() { loadCards(); } - }, 2000); - + }, 3000); } private void loadCards() { diff --git a/app/src/main/java/com/cooltechworks/sample/MainActivity.java b/app/src/main/java/com/cooltechworks/sample/MainActivity.java index 0e3a66d..931d549 100644 --- a/app/src/main/java/com/cooltechworks/sample/MainActivity.java +++ b/app/src/main/java/com/cooltechworks/sample/MainActivity.java @@ -20,6 +20,7 @@ import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.View; +import android.widget.Button; import com.cooltechworks.sample.utils.BaseUtils; @@ -29,17 +30,32 @@ public class MainActivity extends AppCompatActivity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); + + final Button firstListDemoButton = (Button) findViewById(R.id.list_demo_button); + final Button firstGridDemoButton = (Button) findViewById(R.id.grid_demo_button); + + createClickListener(firstListDemoButton, BaseUtils.TYPE_LIST); + createClickListener(firstGridDemoButton, BaseUtils.TYPE_GRID); + + final Button secondListDemoButton = (Button) findViewById(R.id.list_second_demo_button); + final Button secondGridDemoButton = (Button) findViewById(R.id.grid_second_demo_button); + + createClickListener(secondListDemoButton, BaseUtils.TYPE_SECOND_LIST); + createClickListener(secondGridDemoButton, BaseUtils.TYPE_SECOND_GRID); } - public void listButtonClick(View v) { - Intent intent = new Intent(this, DemoActivity.class); - intent.putExtra(DemoActivity.EXTRA_TYPE, BaseUtils.TYPE_LIST); - startActivity(intent); + private void createClickListener(Button button, final int demoType) { + button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + startDemo(demoType); + } + }); } - public void gridButtonClick(View v) { + private void startDemo(int demoType) { Intent intent = new Intent(this, DemoActivity.class); - intent.putExtra(DemoActivity.EXTRA_TYPE, BaseUtils.TYPE_GRID); + intent.putExtra(DemoActivity.EXTRA_TYPE, demoType); startActivity(intent); } } diff --git a/app/src/main/java/com/cooltechworks/sample/utils/BaseUtils.java b/app/src/main/java/com/cooltechworks/sample/utils/BaseUtils.java index b9b6f3a..066812d 100644 --- a/app/src/main/java/com/cooltechworks/sample/utils/BaseUtils.java +++ b/app/src/main/java/com/cooltechworks/sample/utils/BaseUtils.java @@ -15,10 +15,14 @@ */ package com.cooltechworks.sample.utils; +import android.content.Context; import android.content.res.Resources; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.LinearLayoutManager; import com.cooltechworks.sample.R; import com.cooltechworks.sample.models.ItemCard; +import com.cooltechworks.sample.utils.view.CardPaddingItemDecoration; /** * Created by sharish on 27/12/16. @@ -26,7 +30,10 @@ public class BaseUtils { - public static final int TYPE_LIST = 0, TYPE_GRID = 1; + public static final int TYPE_LIST = 0; + public static final int TYPE_GRID = 1; + public static final int TYPE_SECOND_LIST = 2; + public static final int TYPE_SECOND_GRID = 3; private static ItemCard[] getListCards(Resources resources) { @@ -115,6 +122,61 @@ private static ItemCard[] getGridCards(Resources resources) { } public static ItemCard[] getCards(Resources resources, int type) { - return type == TYPE_LIST ? getListCards(resources) : getGridCards(resources); + ItemCard[] itemCards; + + switch (type) { + case TYPE_LIST: + case TYPE_SECOND_LIST: + itemCards = getListCards(resources); + break; + case TYPE_GRID: + case TYPE_SECOND_GRID: + itemCards = getGridCards(resources); + break; + default: + itemCards = null; + } + + return itemCards; + } + + public static DemoConfiguration getDemoConfiguration(int configurationType, Context context) { + DemoConfiguration demoConfiguration; + + switch (configurationType) { + case TYPE_LIST: + demoConfiguration = new DemoConfiguration(); + demoConfiguration.setStyleResource(R.style.AppTheme); + demoConfiguration.setLayoutResource(R.layout.activity_list); + demoConfiguration.setLayoutManager(new LinearLayoutManager(context)); + demoConfiguration.setTitleResource(R.string.ab_list_title); + break; + case TYPE_GRID: + demoConfiguration = new DemoConfiguration(); + demoConfiguration.setStyleResource(R.style.AppThemeGrid); + demoConfiguration.setLayoutResource(R.layout.activity_grid); + demoConfiguration.setLayoutManager(new GridLayoutManager(context, 2)); + demoConfiguration.setTitleResource(R.string.ab_grid_title); + break; + case TYPE_SECOND_LIST: + demoConfiguration = new DemoConfiguration(); + demoConfiguration.setStyleResource(R.style.AppTheme); + demoConfiguration.setLayoutResource(R.layout.activity_second_list); + demoConfiguration.setLayoutManager(new LinearLayoutManager(context)); + demoConfiguration.setTitleResource(R.string.ab_list_title); + demoConfiguration.setItemDecoration(new CardPaddingItemDecoration(context)); + break; + case TYPE_SECOND_GRID: + demoConfiguration = new DemoConfiguration(); + demoConfiguration.setStyleResource(R.style.AppThemeGrid); + demoConfiguration.setLayoutResource(R.layout.activity_second_grid); + demoConfiguration.setLayoutManager(new GridLayoutManager(context, 2)); + demoConfiguration.setTitleResource(R.string.ab_grid_title); + break; + default: + demoConfiguration = null; + } + + return demoConfiguration; } } diff --git a/app/src/main/java/com/cooltechworks/sample/utils/DemoConfiguration.java b/app/src/main/java/com/cooltechworks/sample/utils/DemoConfiguration.java new file mode 100644 index 0000000..8e34d37 --- /dev/null +++ b/app/src/main/java/com/cooltechworks/sample/utils/DemoConfiguration.java @@ -0,0 +1,62 @@ +package com.cooltechworks.sample.utils; + + +import android.support.annotation.LayoutRes; +import android.support.annotation.StringRes; +import android.support.annotation.StyleRes; +import android.support.v7.widget.RecyclerView; + +public class DemoConfiguration { + @StyleRes + private int styleResource; + + @LayoutRes + private int layoutResource; + + @StringRes + private int titleResource; + + private RecyclerView.LayoutManager layoutManager; + + private RecyclerView.ItemDecoration itemDecoration; + + public RecyclerView.ItemDecoration getItemDecoration() { + return itemDecoration; + } + + public void setItemDecoration(RecyclerView.ItemDecoration itemDecoration) { + this.itemDecoration = itemDecoration; + } + + public int getStyleResource() { + return styleResource; + } + + public void setStyleResource(int styleResource) { + this.styleResource = styleResource; + } + + public int getLayoutResource() { + return layoutResource; + } + + public void setLayoutResource(int layoutResource) { + this.layoutResource = layoutResource; + } + + public int getTitleResource() { + return titleResource; + } + + public void setTitleResource(int titleResource) { + this.titleResource = titleResource; + } + + public RecyclerView.LayoutManager getLayoutManager() { + return layoutManager; + } + + public void setLayoutManager(RecyclerView.LayoutManager layoutManager) { + this.layoutManager = layoutManager; + } +} diff --git a/app/src/main/java/com/cooltechworks/sample/utils/view/CardPaddingItemDecoration.java b/app/src/main/java/com/cooltechworks/sample/utils/view/CardPaddingItemDecoration.java new file mode 100644 index 0000000..ccf58f7 --- /dev/null +++ b/app/src/main/java/com/cooltechworks/sample/utils/view/CardPaddingItemDecoration.java @@ -0,0 +1,22 @@ +package com.cooltechworks.sample.utils.view; + + +import android.content.Context; +import android.graphics.Rect; +import android.support.v7.widget.RecyclerView; +import android.util.TypedValue; +import android.view.View; + +public class CardPaddingItemDecoration extends RecyclerView.ItemDecoration { + + private int paddingBetweenItems; + + public CardPaddingItemDecoration(Context context) { + this.paddingBetweenItems = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, context.getResources().getDisplayMetrics()); + } + + @Override + public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { + outRect.set(0, 0, 0, paddingBetweenItems); + } +} diff --git a/app/src/main/java/com/cooltechworks/sample/viewholders/ItemHolder.java b/app/src/main/java/com/cooltechworks/sample/viewholders/ItemHolder.java index da644d7..e3cd2de 100644 --- a/app/src/main/java/com/cooltechworks/sample/viewholders/ItemHolder.java +++ b/app/src/main/java/com/cooltechworks/sample/viewholders/ItemHolder.java @@ -25,7 +25,11 @@ import com.bumptech.glide.Glide; import com.cooltechworks.sample.R; import com.cooltechworks.sample.models.ItemCard; -import com.cooltechworks.sample.utils.BaseUtils; + +import static com.cooltechworks.sample.utils.BaseUtils.TYPE_GRID; +import static com.cooltechworks.sample.utils.BaseUtils.TYPE_LIST; +import static com.cooltechworks.sample.utils.BaseUtils.TYPE_SECOND_GRID; +import static com.cooltechworks.sample.utils.BaseUtils.TYPE_SECOND_LIST; /** * Created by sharish on 27/12/16. @@ -40,7 +44,7 @@ public class ItemHolder extends RecyclerView.ViewHolder { public static ItemHolder newInstance(ViewGroup container, int type) { - View root = LayoutInflater.from(container.getContext()).inflate(type == BaseUtils.TYPE_LIST ? R.layout.layout_news_card : R.layout.layout_ecom_item, container, false); + View root = LayoutInflater.from(container.getContext()).inflate(getLayoutResourceId(type), container, false); return new ItemHolder(root); } @@ -61,4 +65,24 @@ public void bind(ItemCard card) { Glide.with(itemView.getContext()).load(card.getThumbnailUrl()).into(mThumbnailView); } + + private static int getLayoutResourceId(int type) { + int selectedLayoutResource; + switch (type) { + case TYPE_LIST: + selectedLayoutResource = R.layout.layout_news_card; + break; + case TYPE_SECOND_LIST: + selectedLayoutResource = R.layout.layout_second_news_card; + break; + case TYPE_GRID: + case TYPE_SECOND_GRID: + selectedLayoutResource = R.layout.layout_ecom_item; + break; + default: + selectedLayoutResource = 0; + } + + return selectedLayoutResource; + } } diff --git a/app/src/main/res/layout/activity_grid.xml b/app/src/main/res/layout/activity_grid.xml index 8518931..b989ca8 100644 --- a/app/src/main/res/layout/activity_grid.xml +++ b/app/src/main/res/layout/activity_grid.xml @@ -35,6 +35,7 @@ limitations under the License. app:shimmer_demo_child_count="10" app:shimmer_demo_grid_child_count="2" app:shimmer_demo_layout="@layout/layout_demo_grid" + app:shimmer_demo_shimmer_color="#21ffffff" app:shimmer_demo_layout_manager_type="grid" /> diff --git a/app/src/main/res/layout/activity_list.xml b/app/src/main/res/layout/activity_list.xml index 1dbc634..9b4ce54 100644 --- a/app/src/main/res/layout/activity_list.xml +++ b/app/src/main/res/layout/activity_list.xml @@ -34,6 +34,7 @@ limitations under the License. android:paddingTop="10dp" app:shimmer_demo_child_count="10" app:shimmer_demo_layout="@layout/layout_demo" + app:shimmer_demo_shimmer_color="#73ffffff" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index f42bea9..9356719 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -17,38 +17,56 @@ limitations under the License. --> - +