From 89b8c3adb34dba765e0eb88e34cb38d35a86dec9 Mon Sep 17 00:00:00 2001 From: Mike Penz Date: Mon, 17 Nov 2014 20:19:40 +0100 Subject: [PATCH] * change to Android-Iconics * update AboutLibraries * add rebound library from Android to make a smooth animation * use IconicsDrawable instead of real drawable. * add SwipeRefreshLayout * some other changes --- app/build.gradle | 10 +- .../lollipopshowcase/DetailActivity.java | 7 +- .../lollipopshowcase/MainActivity.java | 68 ++++++------ .../adapter/ApplicationAdapter.java | 8 ++ .../itemanimator/CustomItemAnimator.java | 100 ++++++++++++++++++ .../itemanimator/RebountItemAnimator.java | 95 +++++++++++++++++ app/src/main/res/layout/activity_detail.xml | 3 +- app/src/main/res/layout/activity_main.xml | 29 ++--- 8 files changed, 267 insertions(+), 53 deletions(-) create mode 100644 app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/CustomItemAnimator.java create mode 100644 app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/RebountItemAnimator.java diff --git a/app/build.gradle b/app/build.gradle index a818660..1dbbbd4 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -25,8 +25,8 @@ android { applicationId 'com.mikepenz.lollipopshowcase' minSdkVersion 16 targetSdkVersion 21 - versionCode 205 - versionName "2.0.5" + versionCode 210 + versionName "2.1.0" } buildTypes { @@ -64,7 +64,9 @@ dependencies { compile 'com.android.support:cardview-v7:21.0.0' compile 'com.nispok:snackbar:2.0.1' - compile 'com.joanzapata.android:android-iconify:1.0.6' + + compile 'com.mikepenz.iconics:library:0.5.1@aar' - compile 'com.tundem.aboutlibraries:library:4.0.1@aar' + compile 'com.mikepenz.aboutlibraries:library:4.3.0@aar' + compile 'com.facebook.rebound:rebound:0.3.6' } diff --git a/app/src/main/java/com/mikepenz/lollipopshowcase/DetailActivity.java b/app/src/main/java/com/mikepenz/lollipopshowcase/DetailActivity.java index 9987850..eda1eee 100755 --- a/app/src/main/java/com/mikepenz/lollipopshowcase/DetailActivity.java +++ b/app/src/main/java/com/mikepenz/lollipopshowcase/DetailActivity.java @@ -6,18 +6,22 @@ import android.content.ComponentName; import android.content.Intent; import android.content.pm.ResolveInfo; +import android.graphics.Color; import android.os.Build; import android.os.Bundle; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.ViewPropertyAnimator; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.mikepenz.lollipopshowcase.entity.AppInfo; import com.mikepenz.lollipopshowcase.util.UploadHelper; +import com.mikpenz.iconics.IconicsDrawable; +import com.mikpenz.iconics.typeface.FontAwesome; import com.nispok.snackbar.Snackbar; import java.util.Date; @@ -55,7 +59,8 @@ public void onClick(View v) { rowContainer = (LinearLayout) findViewById(R.id.row_container); // Fab Button - View fabButton = findViewById(R.id.fab_button); + ImageButton fabButton = (ImageButton) findViewById(R.id.fab_button); + fabButton.setImageDrawable(new IconicsDrawable(this, FontAwesome.Icon.faw_upload).color(Color.WHITE).actionBarSize()); fabButton.setOnClickListener(fabClickListener); Utils.configureFab(fabButton); diff --git a/app/src/main/java/com/mikepenz/lollipopshowcase/MainActivity.java b/app/src/main/java/com/mikepenz/lollipopshowcase/MainActivity.java index 5085ff9..b3e1416 100644 --- a/app/src/main/java/com/mikepenz/lollipopshowcase/MainActivity.java +++ b/app/src/main/java/com/mikepenz/lollipopshowcase/MainActivity.java @@ -3,33 +3,33 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ResolveInfo; +import android.graphics.Color; import android.os.AsyncTask; import android.os.Bundle; import android.support.v4.app.ActivityOptionsCompat; import android.support.v4.util.Pair; import android.support.v4.widget.DrawerLayout; +import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.ActionBarActivity; import android.support.v7.app.ActionBarDrawerToggle; -import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.View; -import android.view.animation.Animation; -import android.view.animation.AnimationUtils; -import android.view.animation.LayoutAnimationController; import android.widget.CompoundButton; +import android.widget.ImageButton; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Switch; -import com.joanzapata.android.iconify.IconDrawable; -import com.joanzapata.android.iconify.Iconify; +import com.mikepenz.aboutlibraries.Libs; +import com.mikepenz.aboutlibraries.ui.LibsActivity; import com.mikepenz.lollipopshowcase.adapter.ApplicationAdapter; import com.mikepenz.lollipopshowcase.entity.AppInfo; +import com.mikepenz.lollipopshowcase.itemanimator.RebountItemAnimator; import com.mikepenz.lollipopshowcase.util.UploadHelper; -import com.tundem.aboutlibraries.Libs; -import com.tundem.aboutlibraries.ui.LibsActivity; +import com.mikpenz.iconics.IconicsDrawable; +import com.mikpenz.iconics.typeface.FontAwesome; import java.util.ArrayList; import java.util.Collections; @@ -38,15 +38,9 @@ public class MainActivity extends ActionBarActivity { private List applicationList = new ArrayList(); - private Toolbar toolbar; - private ActionBarDrawerToggle actionBarDrawerToggle; - - private DrawerLayout mDrawerLayout; - private LinearLayout mDrawerList; - - private RecyclerView mRecyclerView; private ApplicationAdapter mAdapter; - private View fabButton; + private ImageButton fabButton; + private SwipeRefreshLayout mSwipeRefreshLayout; @Override @@ -60,22 +54,22 @@ protected void onCreate(Bundle savedInstanceState) { //Utils.configureWindowEnterExitTransition(getWindow()); // Handle Toolbar - toolbar = (Toolbar) findViewById(R.id.toolbar); + Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); getSupportActionBar().setDisplayHomeAsUpEnabled(true); // Handle DrawerLayout - mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer); + DrawerLayout mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer); // Handle ActionBarDrawerToggle - actionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close); + ActionBarDrawerToggle actionBarDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close); actionBarDrawerToggle.syncState(); // Handle different Drawer States :D mDrawerLayout.setDrawerListener(actionBarDrawerToggle); // Handle DrawerList - mDrawerList = (LinearLayout) findViewById(R.id.drawerList); + LinearLayout mDrawerList = (LinearLayout) findViewById(R.id.drawerList); // Init DrawerElems NOTE Just don't do this in a live app :D final SharedPreferences pref = getSharedPreferences("com.mikepenz.applicationreader", 0); @@ -112,19 +106,27 @@ public void onClick(View v) { startActivity(i); } }); - ((ImageView) mDrawerList.findViewById(R.id.drawer_opensource_icon)).setImageDrawable(new IconDrawable(this, Iconify.IconValue.fa_github).colorRes(R.color.secondary).actionBarSize()); + ((ImageView) mDrawerList.findViewById(R.id.drawer_opensource_icon)).setImageDrawable(new IconicsDrawable(this, FontAwesome.Icon.faw_github).colorRes(R.color.secondary).actionBarSize()); // Fab Button - fabButton = findViewById(R.id.fab_button); + fabButton = (ImageButton) findViewById(R.id.fab_button); + fabButton.setImageDrawable(new IconicsDrawable(this, FontAwesome.Icon.faw_upload).color(Color.WHITE).actionBarSize()); fabButton.setOnClickListener(fabClickListener); Utils.configureFab(fabButton); - mRecyclerView = (RecyclerView) findViewById(R.id.list); + RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.list); mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); - mRecyclerView.setItemAnimator(new DefaultItemAnimator()); + mRecyclerView.setItemAnimator(new RebountItemAnimator()); mAdapter = new ApplicationAdapter(new ArrayList(), R.layout.row_application, MainActivity.this); mRecyclerView.setAdapter(mAdapter); + mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container); + mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + @Override + public void onRefresh() { + new InitializeApplicationsTask().execute(); + } + }); new InitializeApplicationsTask().execute(); } @@ -142,7 +144,7 @@ public void animateActivity(AppInfo appInfo, View appIcon) { Intent i = new Intent(this, DetailActivity.class); i.putExtra("appInfo", appInfo.getComponentName()); - ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, Pair.create(fabButton, "fab"), Pair.create(appIcon, "appIcon")); + ActivityOptionsCompat transitionActivityOptions = ActivityOptionsCompat.makeSceneTransitionAnimation(this, Pair.create((View) fabButton, "fab"), Pair.create(appIcon, "appIcon")); startActivity(i, transitionActivityOptions.toBundle()); } @@ -151,7 +153,8 @@ private class InitializeApplicationsTask extends AsyncTask { @Override protected void onPreExecute() { - //MainActivity.this.setProgressBarIndeterminate(true); + mSwipeRefreshLayout.setRefreshing(true); + super.onPreExecute(); } @@ -161,7 +164,6 @@ protected Void doInBackground(Void... params) { final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null); mainIntent.addCategory(Intent.CATEGORY_LAUNCHER); - //Clean up ail applicationList.clear(); List ril = getPackageManager().queryIntentActivities(mainIntent, 0); @@ -170,19 +172,19 @@ protected Void doInBackground(Void... params) { } Collections.sort(applicationList); + for (AppInfo appInfo : applicationList) { + //load icons before shown. so the list is smoother + appInfo.getIcon(); + } + return null; } @Override protected void onPostExecute(Void result) { - //MainActivity.this.setProgressBarIndeterminate(false); mAdapter.setApplications(applicationList); - Animation fadeIn = AnimationUtils.loadAnimation(MainActivity.this, android.R.anim.slide_in_left); - fadeIn.setDuration(250); - LayoutAnimationController layoutAnimationController = new LayoutAnimationController(fadeIn); - mRecyclerView.setLayoutAnimation(layoutAnimationController); - mRecyclerView.startLayoutAnimation(); + mSwipeRefreshLayout.setRefreshing(false); super.onPostExecute(result); } diff --git a/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java b/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java index 788ab4b..c3dd121 100755 --- a/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java +++ b/app/src/main/java/com/mikepenz/lollipopshowcase/adapter/ApplicationAdapter.java @@ -25,6 +25,14 @@ public ApplicationAdapter(List applications, int rowLayout, MainActivit this.mAct = act; } + public void clearApplications() { + int size = this.applications.size(); + if (size > 0) { + this.applications.clear(); + this.notifyItemRangeRemoved(0, size - 1); + } + } + public void setApplications(List applications) { this.applications = applications; this.notifyItemRangeInserted(0, applications.size() - 1); diff --git a/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/CustomItemAnimator.java b/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/CustomItemAnimator.java new file mode 100644 index 0000000..2fc532f --- /dev/null +++ b/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/CustomItemAnimator.java @@ -0,0 +1,100 @@ +package com.mikepenz.lollipopshowcase.itemanimator; + +import android.animation.Animator; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.support.v7.widget.RecyclerView; +import android.view.View; +import android.view.animation.AccelerateDecelerateInterpolator; + +import java.util.ArrayList; +import java.util.List; + + +public class CustomItemAnimator extends RecyclerView.ItemAnimator { + + List mViewHolders = new ArrayList(); + + @Override + public void runPendingAnimations() { + if (!mViewHolders.isEmpty()) { + int animationDuration = 300; + AnimatorSet animator; + View target; + for (final RecyclerView.ViewHolder viewHolder : mViewHolders) { + target = viewHolder.itemView; + target.setPivotX(target.getMeasuredWidth() / 2); + target.setPivotY(target.getMeasuredHeight() / 2); + + animator = new AnimatorSet(); + + animator.playTogether( + ObjectAnimator.ofFloat(target, "translationX", -target.getMeasuredWidth(), 0.0f), + ObjectAnimator.ofFloat(target, "alpha", target.getAlpha(), 1.0f) + ); + + animator.setTarget(target); + animator.setDuration(animationDuration); + animator.setInterpolator(new AccelerateDecelerateInterpolator()); + animator.setStartDelay((animationDuration * viewHolder.getPosition()) / 10); + animator.addListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + + } + + @Override + public void onAnimationEnd(Animator animation) { + mViewHolders.remove(viewHolder); + } + + @Override + public void onAnimationCancel(Animator animation) { + + } + + @Override + public void onAnimationRepeat(Animator animation) { + + } + }); + animator.start(); + } + } + } + + @Override + public boolean animateRemove(RecyclerView.ViewHolder viewHolder) { + return false; + } + + @Override + public boolean animateAdd(RecyclerView.ViewHolder viewHolder) { + viewHolder.itemView.setAlpha(0.0f); + return mViewHolders.add(viewHolder); + } + + @Override + public boolean animateMove(RecyclerView.ViewHolder viewHolder, int i, int i2, int i3, int i4) { + return false; + } + + @Override + public boolean animateChange(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder viewHolder2, int i, int i2, int i3, int i4) { + return false; + } + + @Override + public void endAnimation(RecyclerView.ViewHolder viewHolder) { + } + + @Override + public void endAnimations() { + } + + @Override + public boolean isRunning() { + return !mViewHolders.isEmpty(); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/RebountItemAnimator.java b/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/RebountItemAnimator.java new file mode 100644 index 0000000..e51531b --- /dev/null +++ b/app/src/main/java/com/mikepenz/lollipopshowcase/itemanimator/RebountItemAnimator.java @@ -0,0 +1,95 @@ +package com.mikepenz.lollipopshowcase.itemanimator; + +import android.animation.AnimatorSet; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import com.facebook.rebound.SimpleSpringListener; +import com.facebook.rebound.Spring; +import com.facebook.rebound.SpringConfig; +import com.facebook.rebound.SpringSystem; + +import java.util.ArrayList; +import java.util.List; + + +public class RebountItemAnimator extends RecyclerView.ItemAnimator { + + // Create a system to run the physics loop for a set of springs. + private SpringSystem springSystem = SpringSystem.create(); + private SpringConfig springConfig = new SpringConfig(70, 10); + + //hold the views to animate in runPendingAnimations + private List mViewHolders = new ArrayList(); + + @Override + public void runPendingAnimations() { + if (!mViewHolders.isEmpty()) { + int animationDuration = 300; + AnimatorSet animator; + + for (final RecyclerView.ViewHolder viewHolder : mViewHolders) { + final View target = viewHolder.itemView; + + // Add a spring to the system. + Spring spring = springSystem.createSpring(); + spring.setSpringConfig(springConfig); + spring.setCurrentValue(0.0f); + + // Add a listener to observe the motion of the spring. + spring.addListener(new SimpleSpringListener() { + + @Override + public void onSpringUpdate(Spring spring) { + // You can observe the updates in the spring + // state by asking its current value in onSpringUpdate. + float value = (float) spring.getCurrentValue(); + + target.setScaleX(value); + target.setScaleY(value); + } + }); + + // Set the spring in motion; moving from 0 to 1 + spring.setEndValue(1.0f); + } + } + } + + @Override + public boolean animateRemove(RecyclerView.ViewHolder viewHolder) { + return false; + } + + @Override + public boolean animateAdd(RecyclerView.ViewHolder viewHolder) { + //viewHolder.itemView.setAlpha(0.0f); + viewHolder.itemView.setScaleX(0); + viewHolder.itemView.setScaleY(0); + return mViewHolders.add(viewHolder); + } + + @Override + public boolean animateMove(RecyclerView.ViewHolder viewHolder, int i, int i2, int i3, int i4) { + return false; + } + + @Override + public boolean animateChange(RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder viewHolder2, int i, int i2, int i3, int i4) { + return false; + } + + @Override + public void endAnimation(RecyclerView.ViewHolder viewHolder) { + } + + @Override + public void endAnimations() { + } + + @Override + public boolean isRunning() { + return !mViewHolders.isEmpty(); + } + +} \ No newline at end of file diff --git a/app/src/main/res/layout/activity_detail.xml b/app/src/main/res/layout/activity_detail.xml index 7e2826b..bb9ff79 100755 --- a/app/src/main/res/layout/activity_detail.xml +++ b/app/src/main/res/layout/activity_detail.xml @@ -86,9 +86,8 @@ android:background="@drawable/button_round" android:stateListAnimator="@anim/fab_anim" android:elevation="8dp" - android:padding="8dp" + android:padding="14dp" android:scaleType="fitCenter" - android:src="@drawable/ic_upload" android:layout_centerHorizontal="true" android:layout_alignParentBottom="true"/> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 10a100f..95d2b8e 100755 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -17,18 +17,22 @@ android:background="?attr/colorPrimary" android:elevation="4dp" android:transitionName="actionBar"/> - - + android:layout_height="match_parent"> + + + android:padding="14dp" + android:scaleType="fitCenter"/>