diff --git a/src/main/java/org/roboswag/components/listing/adapters/AbstractItemsAdapter.java b/src/main/java/org/roboswag/components/listing/adapters/AbstractItemsAdapter.java index 27ff332..6a0abbb 100644 --- a/src/main/java/org/roboswag/components/listing/adapters/AbstractItemsAdapter.java +++ b/src/main/java/org/roboswag/components/listing/adapters/AbstractItemsAdapter.java @@ -19,6 +19,9 @@ package org.roboswag.components.listing.adapters; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v7.widget.RecyclerView; @@ -47,6 +50,7 @@ public abstract class AbstractItemsAdapter onItemClickListener; @Nullable @@ -98,11 +102,19 @@ public abstract class AbstractItemsAdapter onItemClickListener.onItemClicked(item)); + holder.itemView.setOnClickListener(v -> + postHandler.postDelayed(() -> onItemClickListener.onItemClicked(item), + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? UiUtils.RIPPLE_EFFECT_DELAY : 0)); } } } + @Override + public void onDetachedFromRecyclerView(final RecyclerView recyclerView) { + super.onDetachedFromRecyclerView(recyclerView); + postHandler.removeCallbacksAndMessages(null); + } + protected abstract void onBindItemToViewHolder(@NonNull final TViewHolder holder, final int position, @NonNull TItem item); @Nullable @@ -147,10 +159,10 @@ public abstract class AbstractItemsAdapter parent.notifyDataSetChanged(), - throwable -> { - retryButton.setVisibility(View.VISIBLE); - progressBar.setVisibility(View.INVISIBLE); - }); + throwable -> { + retryButton.setVisibility(View.VISIBLE); + progressBar.setVisibility(View.INVISIBLE); + }); } } diff --git a/src/main/java/org/roboswag/components/navigation/AbstractBaseActivity.java b/src/main/java/org/roboswag/components/navigation/AbstractBaseActivity.java index 936a98c..f98e233 100644 --- a/src/main/java/org/roboswag/components/navigation/AbstractBaseActivity.java +++ b/src/main/java/org/roboswag/components/navigation/AbstractBaseActivity.java @@ -23,7 +23,9 @@ import android.app.ActivityManager; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; +import android.os.Build; import android.os.Bundle; +import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.ActivityCompat; @@ -65,6 +67,8 @@ public abstract class AbstractBaseActivity extends AppCompatActivity private String requestedPermission; private final PublishSubject requestPermissionsEvent = PublishSubject.create(); + private final Handler postHandler = new Handler(); + /* Returns id of main fragments container where navigation-node fragments should be */ protected int getFragmentContainerId() { throw new UnsupportedOperationException("Implement getFragmentContainerId method to use fragment managing"); @@ -205,11 +209,16 @@ public abstract class AbstractBaseActivity extends AppCompatActivity //TODO: log return null; } - getSupportFragmentManager().beginTransaction() - .replace(getFragmentContainerId(), fragment, backStackTag) - .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) - .addToBackStack(backStackTag) - .commit(); + + postHandler.postDelayed(() -> { + getSupportFragmentManager().beginTransaction() + .replace(getFragmentContainerId(), fragment, backStackTag) + .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN) + .addToBackStack(backStackTag) + .commit(); + }, + Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP ? UiUtils.RIPPLE_EFFECT_DELAY : 0); + return fragment; } @@ -277,6 +286,12 @@ public abstract class AbstractBaseActivity extends AppCompatActivity } } + @Override + protected void onDestroy() { + super.onDestroy(); + postHandler.removeCallbacksAndMessages(null); + } + private void findTopFragmentAndPopBackStackToIt(@NonNull final FragmentManager fragmentManager, final int stackSize) { String lastFragmentName = fragmentManager.getBackStackEntryAt(stackSize - 1).getName(); diff --git a/src/main/java/org/roboswag/components/utils/Typefaces.java b/src/main/java/org/roboswag/components/utils/Typefaces.java index fae2632..fdb7cb5 100644 --- a/src/main/java/org/roboswag/components/utils/Typefaces.java +++ b/src/main/java/org/roboswag/components/utils/Typefaces.java @@ -30,7 +30,6 @@ import android.widget.TextView; import org.roboswag.components.R; import org.roboswag.components.views.TypefacedText; import org.roboswag.core.log.Lc; -import org.roboswag.core.utils.ShouldNotHappenException; import java.io.IOException; import java.util.Arrays; @@ -94,7 +93,7 @@ public final class Typefaces { typefacedText.setTypeface(customTypeface, typeface == null ? Typeface.NORMAL : typeface.getStyle()); } } else if (!allowEmptyCustomTypeface) { - Lc.assertion(new ShouldNotHappenException("TypefacedText has no customTypeface attribute: " + typefacedText)); + Lc.assertion("TypefacedText has no customTypeface attribute: " + typefacedText); } } diff --git a/src/main/java/org/roboswag/components/utils/UiUtils.java b/src/main/java/org/roboswag/components/utils/UiUtils.java index fa67949..062731b 100644 --- a/src/main/java/org/roboswag/components/utils/UiUtils.java +++ b/src/main/java/org/roboswag/components/utils/UiUtils.java @@ -1,18 +1,20 @@ package org.roboswag.components.utils; +import android.app.Activity; import android.content.Context; -import android.graphics.drawable.Drawable; import android.os.Build; -import android.support.annotation.ColorRes; -import android.support.annotation.DrawableRes; import android.support.annotation.LayoutRes; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.util.DisplayMetrics; import android.util.TypedValue; +import android.view.Display; +import android.view.KeyCharacterMap; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; +import android.view.ViewConfiguration; import android.view.ViewGroup; import org.roboswag.components.navigation.AbstractBaseFragment; @@ -25,6 +27,8 @@ import rx.functions.Func1; */ public final class UiUtils { + // to enable ripple effect on tap + public static final long RIPPLE_EFFECT_DELAY = 250; private static final int MAX_METRICS_TRIES_COUNT = 5; @NonNull @@ -53,6 +57,11 @@ public final class UiUtils { return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0; } + public static int getNavigationBarHeight(@NonNull final Context context) { + final int resourceId = context.getResources().getIdentifier("navigation_bar_height", "dimen", "android"); + return resourceId > 0 ? context.getResources().getDimensionPixelSize(resourceId) : 0; + } + @NonNull public static View inflate(@LayoutRes final int layoutId, @NonNull final ViewGroup parent) { return LayoutInflater.from(parent.getContext()).inflate(layoutId, parent, false); @@ -80,22 +89,25 @@ public final class UiUtils { return result; } - @SuppressWarnings("deprecation") - public static int getColor(@NonNull final Context context, @ColorRes final int colorResId) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return context.getResources().getColor(colorResId, context.getTheme()); - } else { - return context.getResources().getColor(colorResId); - } - } + //http://stackoverflow.com/questions/14853039/how-to-tell-whether-an-android-device-has-hard-keys/14871974#14871974 + public static boolean hasSoftKeys(@NonNull final Activity activity) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + final Display display = activity.getWindowManager().getDefaultDisplay(); - @SuppressWarnings("deprecation") - public static Drawable getDrawable(@NonNull final Context context, @DrawableRes final int drawableResId) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - return context.getResources().getDrawable(drawableResId, context.getTheme()); - } else { - return context.getResources().getDrawable(drawableResId); + final DisplayMetrics realDisplayMetrics = new DisplayMetrics(); + display.getRealMetrics(realDisplayMetrics); + + final DisplayMetrics displayMetrics = new DisplayMetrics(); + display.getMetrics(displayMetrics); + + return (realDisplayMetrics.widthPixels - displayMetrics.widthPixels) > 0 + || (realDisplayMetrics.heightPixels - displayMetrics.heightPixels) > 0; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { + final boolean hasMenuKey = ViewConfiguration.get(activity).hasPermanentMenuKey(); + final boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK); + return !hasMenuKey && !hasBackKey; } + return false; } private UiUtils() {