From 1846765cf9b0624727121ecb6a597b71b4e6dabe Mon Sep 17 00:00:00 2001 From: Manuel Martin Date: Wed, 20 Nov 2019 22:39:50 +0100 Subject: [PATCH] Add hover animations to the languages and popup row icons (#2332) --- .../ui/adapters/LanguagesAdapter.java | 62 ++++++++- .../vrbrowser/ui/adapters/PopUpAdapter.java | 57 ++++++++ .../settings/ContentLanguageOptionsView.java | 4 +- .../res/drawable/ic_icon_language_delete.xml | 4 +- app/src/main/res/layout/language_item.xml | 125 +++++++++++------- app/src/main/res/layout/popup_item.xml | 27 ++-- 6 files changed, 214 insertions(+), 65 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/LanguagesAdapter.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/LanguagesAdapter.java index 9a707b738..78527c6b7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/LanguagesAdapter.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/LanguagesAdapter.java @@ -1,11 +1,14 @@ package org.mozilla.vrbrowser.ui.adapters; +import android.animation.ValueAnimator; import android.annotation.SuppressLint; +import android.content.Context; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.animation.AnimationUtils; +import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -23,16 +26,29 @@ public class LanguagesAdapter extends RecyclerView.Adapter { + private static final int ICON_ANIMATION_DURATION = 200; + private List mLanguagesList; private boolean mIsPreferred; + private int mIconColorHover; + private int mIconNormalColor; + private int mIconSize; + private int mMaxIconSize; + @Nullable private final LanguageItemCallback mLanguageItemCallback; - public LanguagesAdapter(@Nullable LanguageItemCallback clickCallback, boolean isPreferred) { + public LanguagesAdapter(@NonNull Context context, @Nullable LanguageItemCallback clickCallback, boolean isPreferred) { mLanguageItemCallback = clickCallback; mIsPreferred = isPreferred; + mIconSize = (int)context.getResources().getDimension(R.dimen.language_row_icon_size); + mMaxIconSize = mIconSize + ((mIconSize*25)/100); + + mIconColorHover = context.getResources().getColor(R.color.smoke, context.getTheme()); + mIconNormalColor = context.getResources().getColor(R.color.concrete, context.getTheme()); + setHasStableIds(true); } @@ -123,6 +139,10 @@ public LanguageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view LanguageItemBinding binding = DataBindingUtil .inflate(LayoutInflater.from(parent.getContext()), R.layout.language_item, parent, false); + binding.add.setOnHoverListener(mIconHoverListener); + binding.delete.setOnHoverListener(mIconHoverListener); + binding.up.setOnHoverListener(mIconHoverListener); + binding.down.setOnHoverListener(mIconHoverListener); binding.setIsPreferred(mIsPreferred); return new LanguageViewHolder(binding); @@ -187,4 +207,44 @@ public long getItemId(int position) { return position; } + private View.OnHoverListener mIconHoverListener = (view, motionEvent) -> { + ImageView icon = (ImageView)view; + int ev = motionEvent.getActionMasked(); + switch (ev) { + case MotionEvent.ACTION_HOVER_ENTER: { + icon.setColorFilter(mIconColorHover); + ValueAnimator anim = ValueAnimator.ofInt(mIconSize, mMaxIconSize); + anim.addUpdateListener(valueAnimator -> { + int val = (Integer) valueAnimator.getAnimatedValue(); + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + layoutParams.width = val; + layoutParams.height = val; + view.setLayoutParams(layoutParams); + }); + anim.setDuration(ICON_ANIMATION_DURATION); + anim.start(); + + return false; + } + + case MotionEvent.ACTION_HOVER_EXIT: { + ValueAnimator anim = ValueAnimator.ofInt(mMaxIconSize, mIconSize); + anim.addUpdateListener(valueAnimator -> { + int val = (Integer) valueAnimator.getAnimatedValue(); + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + layoutParams.width = val; + layoutParams.height = val; + view.setLayoutParams(layoutParams); + }); + anim.setDuration(ICON_ANIMATION_DURATION); + anim.start(); + icon.setColorFilter(mIconNormalColor); + + return false; + } + } + + return false; + }; + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/PopUpAdapter.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/PopUpAdapter.java index 888ab4661..f8d0e4a85 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/PopUpAdapter.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/adapters/PopUpAdapter.java @@ -1,9 +1,12 @@ package org.mozilla.vrbrowser.ui.adapters; +import android.animation.ValueAnimator; import android.content.Context; import android.view.LayoutInflater; import android.view.MotionEvent; +import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import androidx.annotation.NonNull; import androidx.databinding.DataBindingUtil; @@ -24,13 +27,26 @@ public class PopUpAdapter extends RecyclerView.Adapter static final String LOGTAG = SystemUtils.createLogtag(BookmarkAdapter.class); + private static final int ICON_ANIMATION_DURATION = 200; + private List mDisplayList; private PopUpSiteItemCallback mCallback; + private int mIconColorHover; + private int mIconNormalColor; + private int mIconSize; + private int mMaxIconSize; + public PopUpAdapter(Context aContext, PopUpSiteItemCallback callback) { mCallback = callback; + mIconSize = (int)aContext.getResources().getDimension(R.dimen.language_row_icon_size); + mMaxIconSize = mIconSize + ((mIconSize*25)/100); + + mIconColorHover = aContext.getResources().getColor(R.color.smoke, aContext.getTheme()); + mIconNormalColor = aContext.getResources().getColor(R.color.concrete, aContext.getTheme()); + setHasStableIds(true); } @@ -93,6 +109,7 @@ public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int return false; }); + binding.delete.setOnHoverListener(mIconHoverListener); return new PopUpSiteViewHolder(binding); } @@ -119,5 +136,45 @@ static class PopUpSiteViewHolder extends RecyclerView.ViewHolder { } } + private View.OnHoverListener mIconHoverListener = (view, motionEvent) -> { + ImageView icon = (ImageView)view; + int ev = motionEvent.getActionMasked(); + switch (ev) { + case MotionEvent.ACTION_HOVER_ENTER: { + icon.setColorFilter(mIconColorHover); + ValueAnimator anim = ValueAnimator.ofInt(mIconSize, mMaxIconSize); + anim.addUpdateListener(valueAnimator -> { + int val = (Integer) valueAnimator.getAnimatedValue(); + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + layoutParams.width = val; + layoutParams.height = val; + view.setLayoutParams(layoutParams); + }); + anim.setDuration(ICON_ANIMATION_DURATION); + anim.start(); + + return false; + } + + case MotionEvent.ACTION_HOVER_EXIT: { + ValueAnimator anim = ValueAnimator.ofInt(mMaxIconSize, mIconSize); + anim.addUpdateListener(valueAnimator -> { + int val = (Integer) valueAnimator.getAnimatedValue(); + ViewGroup.LayoutParams layoutParams = view.getLayoutParams(); + layoutParams.width = val; + layoutParams.height = val; + view.setLayoutParams(layoutParams); + }); + anim.setDuration(ICON_ANIMATION_DURATION); + anim.start(); + icon.setColorFilter(mIconNormalColor); + + return false; + } + } + + return false; + }; + } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java index ceec75edb..cf47de95f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/ContentLanguageOptionsView.java @@ -41,11 +41,11 @@ private void initialize(Context aContext) { LayoutInflater inflater = LayoutInflater.from(aContext); // Preferred languages adapter - mPreferredAdapter = new LanguagesAdapter(mLanguageItemCallback, true); + mPreferredAdapter = new LanguagesAdapter(getContext(), mLanguageItemCallback, true); mPreferredAdapter.setLanguageList(LocaleUtils.getPreferredLanguages(getContext())); // Available languages adapter - mAvailableAdapter = new LanguagesAdapter(mLanguageItemCallback, false); + mAvailableAdapter = new LanguagesAdapter(getContext(), mLanguageItemCallback, false); mAvailableAdapter.setLanguageList(LocaleUtils.getAvailableLanguages()); // Inflate this data binding layout diff --git a/app/src/main/res/drawable/ic_icon_language_delete.xml b/app/src/main/res/drawable/ic_icon_language_delete.xml index cf446f48d..d2e167e4f 100644 --- a/app/src/main/res/drawable/ic_icon_language_delete.xml +++ b/app/src/main/res/drawable/ic_icon_language_delete.xml @@ -2,7 +2,7 @@ - - + + \ No newline at end of file diff --git a/app/src/main/res/layout/language_item.xml b/app/src/main/res/layout/language_item.xml index 440cd3cd4..1fa775ca6 100644 --- a/app/src/main/res/layout/language_item.xml +++ b/app/src/main/res/layout/language_item.xml @@ -43,34 +43,54 @@ android:duplicateParentState="true" android:orientation="horizontal"> - - - + android:duplicateParentState="true"> + + + + + + + + @@ -109,31 +129,38 @@ android:duplicateParentState="true" android:orientation="horizontal"> - - - + android:duplicateParentState="true"> + + + + + + diff --git a/app/src/main/res/layout/popup_item.xml b/app/src/main/res/layout/popup_item.xml index 48eb497cf..3d67795d6 100644 --- a/app/src/main/res/layout/popup_item.xml +++ b/app/src/main/res/layout/popup_item.xml @@ -20,26 +20,31 @@ android:paddingTop="5dp" android:paddingBottom="5dp"> - + android:layout_centerVertical="true"> + +