1
0
Fork 0

No issue: Use putCompoundDrawables helper (#3982)

master
Tiger Oakes 2019-07-15 11:24:59 -04:00 committed by Sawyer Blatz
parent 89a500beaf
commit 5de1678e65
7 changed files with 65 additions and 34 deletions

View File

@ -5,6 +5,7 @@
package org.mozilla.fenix.browser package org.mozilla.fenix.browser
import android.view.View import android.view.View
import androidx.annotation.StringRes
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import mozilla.components.feature.contextmenu.ContextMenuCandidate import mozilla.components.feature.contextmenu.ContextMenuCandidate
import org.mozilla.fenix.components.FenixSnackbar import org.mozilla.fenix.components.FenixSnackbar
@ -13,19 +14,16 @@ class FenixSnackbarDelegate(val view: View, private val anchorView: View?) :
ContextMenuCandidate.SnackbarDelegate { ContextMenuCandidate.SnackbarDelegate {
override fun show( override fun show(
snackBarParentView: View, snackBarParentView: View,
text: Int, @StringRes text: Int,
duration: Int, duration: Int,
action: Int, @StringRes action: Int,
listener: ((v: View) -> Unit)? listener: ((v: View) -> Unit)?
) { ) {
val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(view.context.getString(text)) val snackbar = FenixSnackbar.make(view, Snackbar.LENGTH_LONG).setText(view.context.getString(text))
if (listener != null) { if (listener != null && action != 0) {
val newListener = { snackbar.setAction(view.context.getString(action)) {
listener.invoke(view) listener.invoke(view)
} }
if (action != 0) {
snackbar.setAction(view.context.getString(action), newListener)
}
} }
snackbar.anchorView = anchorView snackbar.anchorView = anchorView
snackbar.show() snackbar.show()

View File

@ -9,6 +9,7 @@ import androidx.annotation.DrawableRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.no_content_message.view.* import kotlinx.android.synthetic.main.no_content_message.view.*
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelativeWithIntrinsicBounds
import org.mozilla.fenix.R import org.mozilla.fenix.R
class NoContentMessageViewHolder(private val view: View) : RecyclerView.ViewHolder(view) { class NoContentMessageViewHolder(private val view: View) : RecyclerView.ViewHolder(view) {
@ -19,7 +20,7 @@ class NoContentMessageViewHolder(private val view: View) : RecyclerView.ViewHold
@StringRes description: Int @StringRes description: Int
) { ) {
with(view.context) { 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_header.text = getString(header)
view.no_content_description.text = getString(description) view.no_content_description.text = getString(description)
} }

View File

@ -9,6 +9,7 @@ import androidx.appcompat.content.res.AppCompatResources
import androidx.navigation.Navigation import androidx.navigation.Navigation
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.onboarding_firefox_account.view.* 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.R
import org.mozilla.fenix.home.HomeFragmentDirections import org.mozilla.fenix.home.HomeFragmentDirections
@ -40,7 +41,7 @@ class OnboardingFirefoxAccountViewHolder(private val view: View) : RecyclerView.
private fun updateHeaderText(autoSignedIn: Boolean) { private fun updateHeaderText(autoSignedIn: Boolean) {
val icon = if (autoSignedIn) avatarAnonymousDrawable else firefoxAccountsDrawable 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) val appName = view.context.getString(R.string.app_name)
view.header_text.text = view.header_text.text =

View File

@ -7,6 +7,7 @@ package org.mozilla.fenix.home.sessioncontrol.viewholders.onboarding
import android.widget.TextView import android.widget.TextView
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import mozilla.components.support.ktx.android.view.putCompoundDrawablesRelative
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.setBounds 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) val size = context.resources.getDimensionPixelSize(R.dimen.onboarding_header_icon_height_width)
icon?.setBounds(size) icon?.setBounds(size)
setCompoundDrawablesRelative(icon, null, null, null) putCompoundDrawablesRelative(start = icon)
} }

View File

@ -8,6 +8,8 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.annotation.DrawableRes
import androidx.core.content.edit
import androidx.core.widget.NestedScrollView import androidx.core.widget.NestedScrollView
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import io.reactivex.Observable 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.fragment_browser.*
import kotlinx.android.synthetic.main.layout_quick_action_sheet.* import kotlinx.android.synthetic.main.layout_quick_action_sheet.*
import kotlinx.android.synthetic.main.layout_quick_action_sheet.view.* 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.R
import org.mozilla.fenix.components.metrics.Event import org.mozilla.fenix.components.metrics.Event
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
@ -133,17 +136,18 @@ class QuickActionUIView(
} }
private fun updateReaderModeButton(withNotification: Boolean) { private fun updateReaderModeButton(withNotification: Boolean) {
if (withNotification) { @DrawableRes
val readerTwoStateDrawableId = if (withNotification) {
quickActionSheet.bounceSheet() quickActionSheet.bounceSheet()
val readerTwoStateDrawable = view.context.getDrawable(R.drawable.reader_two_state_with_notification) Settings.getInstance(view.context).preferences.edit {
view.quick_action_read putBoolean(view.context.getString(R.string.pref_key_reader_mode_notification), false)
.setCompoundDrawablesWithIntrinsicBounds(null, readerTwoStateDrawable, null, null)
Settings.getInstance(view.context).preferences.edit()
.putBoolean(view.context.getString(R.string.pref_key_reader_mode_notification), false).apply()
} 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_with_notification
} else {
R.drawable.reader_two_state
}
view.quick_action_read.putCompoundDrawablesRelativeWithIntrinsicBounds(
top = view.context.getDrawable(readerTwoStateDrawableId)
)
} }
} }

View File

@ -8,14 +8,17 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.graphics.PorterDuff.Mode.SRC_IN import android.graphics.PorterDuff.Mode.SRC_IN
import android.graphics.PorterDuffColorFilter import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable
import android.util.AttributeSet import android.util.AttributeSet
import android.view.MotionEvent import android.view.MotionEvent
import android.view.MotionEvent.ACTION_UP
import androidx.appcompat.widget.AppCompatEditText 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.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( class ClearableEditText @JvmOverloads constructor(
context: Context, context: Context,
attrs: AttributeSet? = null, attrs: AttributeSet? = null,
@ -23,27 +26,49 @@ class ClearableEditText @JvmOverloads constructor(
) : ) :
AppCompatEditText(context, attrs, defStyleAttr) { 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") @SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent?): Boolean { override fun onTouchEvent(event: MotionEvent): Boolean {
if (length() != 0 && event?.action == MotionEvent.ACTION_UP && if (shouldShowClearButton(length()) && event.action == ACTION_UP && event.endDrawableTouched()) {
event.rawX >= (this@ClearableEditText.right - this@ClearableEditText.compoundPaddingRight) setText("")
) {
this@ClearableEditText.setText("")
return true return true
} }
return super.onTouchEvent(event) return super.onTouchEvent(event)
} }
/**
* Displays a clear icon if text has been entered.
*/
override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) { override fun onTextChanged(text: CharSequence?, start: Int, lengthBefore: Int, lengthAfter: Int) {
super.onTextChanged(text, start, lengthBefore, lengthAfter) super.onTextChanged(text, start, lengthBefore, lengthAfter)
if (lengthAfter != 0 && error == null) { val drawable = if (shouldShowClearButton(lengthAfter)) {
setCompoundDrawablesWithIntrinsicBounds(0, 0, R.drawable.ic_clear, 0) context.getDrawable(R.drawable.ic_clear)?.apply {
for (drawable: Drawable in compoundDrawables.filterNotNull()) { colorFilter = PorterDuffColorFilter(R.attr.primaryText.getColorFromAttr(context), SRC_IN)
val color = ThemeManager.resolveAttribute(R.attr.primaryText, context!!)
drawable.colorFilter = PorterDuffColorFilter(getColor(context, color), SRC_IN)
} }
} else { } 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))
} }

View File

@ -19,6 +19,7 @@
android:drawableTint="?primaryText" android:drawableTint="?primaryText"
android:drawablePadding="8dp" android:drawablePadding="8dp"
tools:text="@tools:sample/lorem" tools:text="@tools:sample/lorem"
tools:drawableEnd="@drawable/ic_tab_collection"
android:textAppearance="@style/HeaderTextStyle" android:textAppearance="@style/HeaderTextStyle"
android:textSize="16sp" /> android:textSize="16sp" />