No issue: Use putCompoundDrawables helper (#3982)
parent
89a500beaf
commit
5de1678e65
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 =
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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" />
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue