From 26e50738166102cae79144ee90ff362b2ab58d95 Mon Sep 17 00:00:00 2001 From: Tiger Oakes Date: Mon, 15 Jul 2019 11:24:59 -0400 Subject: [PATCH] [fenix] No issue: Use putCompoundDrawables helper (https://github.com/mozilla-mobile/fenix/pull/3982) --- .../fenix/browser/FenixSnackbarDelegate.kt | 12 ++--- .../viewholders/NoContentMessageViewHolder.kt | 3 +- .../OnboardingFirefoxAccountViewHolder.kt | 3 +- .../viewholders/onboarding/OnboardingIcon.kt | 3 +- .../quickactionsheet/QuickActionUIView.kt | 22 ++++---- .../mozilla/fenix/utils/ClearableEditText.kt | 53 ++++++++++++++----- .../main/res/layout/no_content_message.xml | 3 +- 7 files changed, 65 insertions(+), 34 deletions(-) diff --git a/app/src/main/java/org/mozilla/fenix/browser/FenixSnackbarDelegate.kt b/app/src/main/java/org/mozilla/fenix/browser/FenixSnackbarDelegate.kt index 2aaaba452..92023b6fd 100644 --- a/app/src/main/java/org/mozilla/fenix/browser/FenixSnackbarDelegate.kt +++ b/app/src/main/java/org/mozilla/fenix/browser/FenixSnackbarDelegate.kt @@ -5,6 +5,7 @@ package org.mozilla.fenix.browser import android.view.View +import androidx.annotation.StringRes import com.google.android.material.snackbar.Snackbar import mozilla.components.feature.contextmenu.ContextMenuCandidate import org.mozilla.fenix.components.FenixSnackbar @@ -13,19 +14,16 @@ class FenixSnackbarDelegate(val view: View, private val anchorView: View?) : ContextMenuCandidate.SnackbarDelegate { override fun show( snackBarParentView: View, - text: Int, + @StringRes text: Int, duration: Int, - action: Int, + @StringRes action: Int, listener: ((v: View) -> Unit)? ) { val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(view.context.getString(text)) - if (listener != null) { - val newListener = { + if (listener != null && action != 0) { + snackbar.setAction(view.context.getString(action)) { listener.invoke(view) } - if (action != 0) { - snackbar.setAction(view.context.getString(action), newListener) - } } snackbar.anchorView = anchorView snackbar.show() diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoContentMessageViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoContentMessageViewHolder.kt index 1943b95a9..d6be11fcf 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoContentMessageViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/NoContentMessageViewHolder.kt @@ -9,6 +9,7 @@ import androidx.annotation.DrawableRes import androidx.annotation.StringRes import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.no_content_message.view.* +import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R class NoContentMessageViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { @@ -19,7 +20,7 @@ class NoContentMessageViewHolder(private val view: View) : RecyclerView.ViewHold @StringRes description: Int ) { with(view.context) { - view.no_content_header.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, icon, 0) + view.no_content_header.putCompoundDrawablesRelativeWithIntrinsicBounds(end = getDrawable(icon)) view.no_content_header.text = getString(header) view.no_content_description.text = getString(description) } diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingFirefoxAccountViewHolder.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingFirefoxAccountViewHolder.kt index c04ac6fb2..3e1915aa6 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingFirefoxAccountViewHolder.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingFirefoxAccountViewHolder.kt @@ -9,6 +9,7 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.navigation.Navigation import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.onboarding_firefox_account.view.* +import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R import org.mozilla.fenix.home.HomeFragmentDirections @@ -40,7 +41,7 @@ class OnboardingFirefoxAccountViewHolder(private val view: View) : RecyclerView. private fun updateHeaderText(autoSignedIn: Boolean) { val icon = if (autoSignedIn) avatarAnonymousDrawable else firefoxAccountsDrawable - view.header_text.setCompoundDrawablesRelativeWithIntrinsicBounds(icon, null, null, null) + view.header_text.putCompoundDrawablesRelativeWithIntrinsicBounds(start = icon) val appName = view.context.getString(R.string.app_name) view.header_text.text = diff --git a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingIcon.kt b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingIcon.kt index 88bf6c6e7..4b02d9f9a 100644 --- a/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingIcon.kt +++ b/app/src/main/java/org/mozilla/fenix/home/sessioncontrol/viewholders/onboarding/OnboardingIcon.kt @@ -7,6 +7,7 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding import android.widget.TextView import androidx.annotation.DrawableRes import androidx.appcompat.content.res.AppCompatResources +import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative import org.mozilla.fenix.R import org.mozilla.fenix.ext.setBounds @@ -18,5 +19,5 @@ fun TextView.setOnboardingIcon(@DrawableRes id: Int) { val size = context.resources.getDimensionPixelSize(R.dimen.onboarding_header_icon_height_width) icon?.setBounds(size) - setCompoundDrawablesRelative(icon, null, null, null) + putCompoundDrawablesRelative(start = icon) } diff --git a/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionUIView.kt b/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionUIView.kt index a09b533a5..b65d0dfa7 100644 --- a/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionUIView.kt +++ b/app/src/main/java/org/mozilla/fenix/quickactionsheet/QuickActionUIView.kt @@ -8,6 +8,8 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.LinearLayout +import androidx.annotation.DrawableRes +import androidx.core.content.edit import androidx.core.widget.NestedScrollView import com.google.android.material.bottomsheet.BottomSheetBehavior import io.reactivex.Observable @@ -16,6 +18,7 @@ import io.reactivex.functions.Consumer import kotlinx.android.synthetic.main.fragment_browser.* import kotlinx.android.synthetic.main.layout_quick_action_sheet.* import kotlinx.android.synthetic.main.layout_quick_action_sheet.view.* +import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.ext.components @@ -133,17 +136,18 @@ class QuickActionUIView( } private fun updateReaderModeButton(withNotification: Boolean) { - if (withNotification) { + @DrawableRes + val readerTwoStateDrawableId = if (withNotification) { quickActionSheet.bounceSheet() - val readerTwoStateDrawable = view.context.getDrawable(R.drawable.reader_two_state_with_notification) - view.quick_action_read - .setCompoundDrawablesWithIntrinsicBounds(null, readerTwoStateDrawable, null, null) - Settings.getInstance(view.context).preferences.edit() - .putBoolean(view.context.getString(R.string.pref_key_reader_mode_notification), false).apply() + Settings.getInstance(view.context).preferences.edit { + putBoolean(view.context.getString(R.string.pref_key_reader_mode_notification), false) + } + R.drawable.reader_two_state_with_notification } else { - val readerTwoStateDrawable = view.context.getDrawable(R.drawable.reader_two_state) - view.quick_action_read - .setCompoundDrawablesWithIntrinsicBounds(null, readerTwoStateDrawable, null, null) + R.drawable.reader_two_state } + view.quick_action_read.putCompoundDrawablesRelativeWithIntrinsicBounds( + top = view.context.getDrawable(readerTwoStateDrawableId) + ) } } diff --git a/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt b/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt index 275fde11a..60ce1757c 100644 --- a/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt +++ b/app/src/main/java/org/mozilla/fenix/utils/ClearableEditText.kt @@ -8,14 +8,17 @@ import android.annotation.SuppressLint import android.content.Context import android.graphics.PorterDuff.Mode.SRC_IN import android.graphics.PorterDuffColorFilter -import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.MotionEvent +import android.view.MotionEvent.ACTION_UP import androidx.appcompat.widget.AppCompatEditText -import androidx.core.content.ContextCompat.getColor +import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds import org.mozilla.fenix.R -import org.mozilla.fenix.ThemeManager +import org.mozilla.fenix.ext.getColorFromAttr +/** + * An [AppCompatEditText] that shows a clear button to the user. + */ class ClearableEditText @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, @@ -23,27 +26,49 @@ class ClearableEditText @JvmOverloads constructor( ) : AppCompatEditText(context, attrs, defStyleAttr) { + /** + * Clears the text when the clear icon is touched. + * + * Since the icon is just a compound drawable, we check the tap location + * to see if the X position of the tap is where the drawable is located. + */ @SuppressLint("ClickableViewAccessibility") - override fun onTouchEvent(event: MotionEvent?): Boolean { - if (length() != 0 && event?.action == MotionEvent.ACTION_UP && - event.rawX >= (this@ClearableEditText.right - this@ClearableEditText.compoundPaddingRight) - ) { - this@ClearableEditText.setText("") + override fun onTouchEvent(event: MotionEvent): Boolean { + if (shouldShowClearButton(length()) && event.action == ACTION_UP && event.endDrawableTouched()) { + setText("") return true } return super.onTouchEvent(event) } + /** + * Displays a clear icon if text has been entered. + */ override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) { super.onTextChanged(text, start, lengthBefore, lengthAfter) - if (lengthAfter != 0 && error == null) { - setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_clear, 0) - for (drawable: Drawable in compoundDrawables.filterNotNull()) { - val color = ThemeManager.resolveAttribute(R.attr.primaryText, context!!) - drawable.colorFilter = PorterDuffColorFilter(getColor(context, color), SRC_IN) + val drawable = if (shouldShowClearButton(lengthAfter)) { + context.getDrawable(R.drawable.ic_clear)?.apply { + colorFilter = PorterDuffColorFilter(R.attr.primaryText.getColorFromAttr(context), SRC_IN) } } else { - setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0) + null } + putCompoundDrawablesRelativeWithIntrinsicBounds(end = drawable) } + + /** + * Checks if the clear button should be displayed. + * + * The button should be displayed if the user has entered valid text. + * @param length Length of the text the user has entered. + */ + private fun shouldShowClearButton(length: Int) = + length > 0 && error == null + + /** + * Returns true if the location of the [MotionEvent] is on top of the end drawable. + */ + private fun MotionEvent.endDrawableTouched() = + (layoutDirection == LAYOUT_DIRECTION_LTR && rawX >= (right - compoundPaddingRight)) || + (layoutDirection == LAYOUT_DIRECTION_RTL && rawX <= (left + compoundPaddingLeft)) } diff --git a/app/src/main/res/layout/no_content_message.xml b/app/src/main/res/layout/no_content_message.xml index 648b67023..5f2caae95 100644 --- a/app/src/main/res/layout/no_content_message.xml +++ b/app/src/main/res/layout/no_content_message.xml @@ -19,6 +19,7 @@ android:drawableTint="?primaryText" android:drawablePadding="8dp" tools:text="@tools:sample/lorem" + tools:drawableEnd="@drawable/ic_tab_collection" android:textAppearance="@style/HeaderTextStyle" android:textSize="16sp" /> @@ -32,4 +33,4 @@ android:textSize="14sp" android:textStyle="normal" /> - \ No newline at end of file +