Merged PR 251892: Snackbar: Bug fixes and polish for icon variant
- Fix a bug so that we can use `Snackbar`s in `RecyclerView`s with `findSuitableParent` method borrowed from android (discovered this while working on `ListItemView`) - Add single line Snackbar with icon variant to the demo and fix bugs so that the icon and text are centered properly - Give a default duration (per design and pm request) - Note which duration is used in the demo button text. | Single-line with icon | Single-line with icon and action | | ------------- |:-------------:| |![Screenshot_1554738893.png](https://onedrive.visualstudio.com/4dcbf0bc-c3cd-49c8-a7c3-ec1924691d9b/_apis/git/repositories/32fa6338-45ea-42a0-aca0-484938e1962a/pullRequests/251892/attachments/Screenshot_1554738893.png) | ![Screenshot_1554738897.png](https://onedrive.visualstudio.com/4dcbf0bc-c3cd-49c8-a7c3-ec1924691d9b/_apis/git/repositories/32fa6338-45ea-42a0-aca0-484938e1962a/pullRequests/251892/attachments/Screenshot_1554738897.png) | | Multi-line with icon | Multi-line with icon and action | |![Screenshot_1554738900.png](https://onedrive.visualstudio.com/4dcbf0bc-c3cd-49c8-a7c3-ec1924691d9b/_apis/git/repositories/32fa6338-45ea-42a0-aca0-484938e1962a/pullRequests/251892/attachments/Screenshot_1554738900.png) | ![Screenshot_1554738905.png](https://onedrive.visualstudio.com/4dcbf0bc-c3cd-49c8-a7c3-ec1924691d9b/_apis/git/repositories/32fa6338-45ea-42a0-aca0-484938e1962a/pullRequests/251892/attachments/Screenshot_1554738905.png) | Related work items: #706313
This commit is contained in:
Родитель
475e3f07af
Коммит
665dc1ccf4
|
@ -21,56 +21,79 @@ class SnackbarActivity : DemoActivity(), View.OnClickListener {
|
|||
super.onCreate(savedInstanceState)
|
||||
|
||||
btn_snackbar_single_line.setOnClickListener(this)
|
||||
btn_snackbar_multi_line.setOnClickListener(this)
|
||||
btn_snackbar_announcement.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_action.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_long_action.setOnClickListener(this)
|
||||
btn_snackbar_single_line_icon.setOnClickListener(this)
|
||||
btn_snackbar_single_line_action.setOnClickListener(this)
|
||||
btn_snackbar_single_line_action_icon.setOnClickListener(this)
|
||||
btn_snackbar_multi_line.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_icon.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_action.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_action_icon.setOnClickListener(this)
|
||||
btn_snackbar_multi_line_long_action.setOnClickListener(this)
|
||||
btn_snackbar_announcement.setOnClickListener(this)
|
||||
}
|
||||
|
||||
override fun onClick(v: View) {
|
||||
when (v.id) {
|
||||
R.id.btn_snackbar_single_line -> Snackbar.make(root_view, getString(R.string.snackbar_single_line), Snackbar.LENGTH_SHORT).show()
|
||||
R.id.btn_snackbar_single_line ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_single_line)).show()
|
||||
|
||||
R.id.btn_snackbar_multi_line -> Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_LONG).show()
|
||||
R.id.btn_snackbar_single_line_icon ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_single_line))
|
||||
.setIcon(R.drawable.ic_done_white)
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_single_line_action -> {
|
||||
val snackbar = Snackbar.make(root_view, getString(R.string.snackbar_single_line), Snackbar.LENGTH_SHORT)
|
||||
snackbar.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
R.id.btn_snackbar_single_line_action ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_single_line))
|
||||
.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
snackbar.show()
|
||||
}
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_multi_line_action -> {
|
||||
val snackbar = Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_INDEFINITE)
|
||||
snackbar.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
R.id.btn_snackbar_single_line_action_icon ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_single_line))
|
||||
.setIcon(R.drawable.ic_done_white)
|
||||
.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
snackbar.show()
|
||||
}
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_multi_line_long_action -> {
|
||||
val snackbar = Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_INDEFINITE)
|
||||
snackbar.setAction(getString(R.string.snackbar_action_long), View.OnClickListener {
|
||||
R.id.btn_snackbar_multi_line ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_LONG).show()
|
||||
|
||||
R.id.btn_snackbar_multi_line_icon ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_LONG)
|
||||
.setIcon(R.drawable.ic_done_white)
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_multi_line_action ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_multi_line), Snackbar.LENGTH_INDEFINITE)
|
||||
.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
snackbar.show()
|
||||
}
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_announcement -> {
|
||||
val snackbar = Snackbar.make(
|
||||
root_view,
|
||||
getString(R.string.snackbar_announcement),
|
||||
Snackbar.LENGTH_INDEFINITE,
|
||||
Snackbar.Style.ANNOUNCEMENT
|
||||
)
|
||||
snackbar.setIcon(R.drawable.ms_ic_birthday)
|
||||
snackbar.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
R.id.btn_snackbar_multi_line_action_icon ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_multi_line))
|
||||
.setIcon(R.drawable.ic_done_white)
|
||||
.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
snackbar.show()
|
||||
}
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_multi_line_long_action ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_multi_line))
|
||||
.setAction(getString(R.string.snackbar_action_long), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
.show()
|
||||
|
||||
R.id.btn_snackbar_announcement ->
|
||||
Snackbar.make(root_view, getString(R.string.snackbar_announcement), style = Snackbar.Style.ANNOUNCEMENT)
|
||||
.setIcon(R.drawable.ic_birthday)
|
||||
.setAction(getString(R.string.snackbar_action), View.OnClickListener {
|
||||
// handle click here
|
||||
})
|
||||
.show()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,6 +5,6 @@
|
|||
-->
|
||||
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<size android:height="@dimen/default_layout_margin" />
|
||||
<size android:height="@dimen/default_view_margin" />
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
-->
|
||||
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="evenOdd"
|
||||
android:pathData="M9,16.17l-4.17,-4.17l-1.42,1.41l5.59,5.59l12,-12l-1.41,-1.41z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
|
@ -19,10 +19,10 @@
|
|||
android:text="@string/snackbar_button_single_line" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line"
|
||||
android:id="@+id/btn_snackbar_single_line_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_multi_line" />
|
||||
android:text="@string/snackbar_button_single_line_icon" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_single_line_action"
|
||||
|
@ -30,12 +30,36 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_single_line_action" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_single_line_action_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_single_line_action_icon" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_multi_line" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_multi_line_icon" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line_action"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_multi_line_action" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line_action_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/snackbar_button_multi_line_action_icon" />
|
||||
|
||||
<android.support.v7.widget.AppCompatButton
|
||||
android:id="@+id/btn_snackbar_multi_line_long_action"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -133,12 +133,16 @@
|
|||
<string name="snackbar_action">Action</string>
|
||||
<string name="snackbar_action_long">Long Text Action</string>
|
||||
<string name="snackbar_announcement">This is an announcement snackbar. It’s used for communicating new features.</string>
|
||||
<string name="snackbar_button_single_line">Single-line</string>
|
||||
<string name="snackbar_button_multi_line">Multi-line</string>
|
||||
<string name="snackbar_button_single_line_action">Single-line with action</string>
|
||||
<string name="snackbar_button_multi_line_action">Multi-line with action</string>
|
||||
<string name="snackbar_button_multi_line_action_long">Multi-line with long action text</string>
|
||||
<string name="snackbar_button_announcement">Announcement style</string>
|
||||
<string name="snackbar_button_single_line">Single-line, short</string>
|
||||
<string name="snackbar_button_single_line_icon">Single-line with icon, short</string>
|
||||
<string name="snackbar_button_single_line_action">Single-line with action, short</string>
|
||||
<string name="snackbar_button_single_line_action_icon">Single-line with action and icon, short</string>
|
||||
<string name="snackbar_button_multi_line">Multi-line, long</string>
|
||||
<string name="snackbar_button_multi_line_icon">Multi-line with icon, long</string>
|
||||
<string name="snackbar_button_multi_line_action">Multi-line with action, indefinite</string>
|
||||
<string name="snackbar_button_multi_line_action_icon">Multi-line with action and icon, short</string>
|
||||
<string name="snackbar_button_multi_line_action_long">Multi-line with long action text, short</string>
|
||||
<string name="snackbar_button_announcement">Announcement style, short</string>
|
||||
<string name="snackbar_multi_line">This is a multi-line snackbar. Max lines are set to two, the rest of the text will truncate.
|
||||
Lorem ipsum dolor sit amet consectetur adipiscing elit. </string>
|
||||
<string name="snackbar_single_line">Single-line snackbar</string>
|
||||
|
|
|
@ -7,11 +7,13 @@ package com.microsoft.officeuifabric.snackbar
|
|||
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.design.widget.BaseTransientBottomBar
|
||||
import android.support.design.widget.CoordinatorLayout
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.widget.AppCompatButton
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.FrameLayout
|
||||
import android.widget.ImageView
|
||||
import android.widget.RelativeLayout
|
||||
import android.widget.TextView
|
||||
|
@ -31,7 +33,9 @@ class Snackbar : BaseTransientBottomBar<Snackbar> {
|
|||
const val LENGTH_SHORT: Int = BaseTransientBottomBar.LENGTH_SHORT
|
||||
const val LENGTH_LONG: Int = BaseTransientBottomBar.LENGTH_LONG
|
||||
|
||||
fun make(parent: ViewGroup, text: CharSequence, duration: Int, style: Style = Style.REGULAR): Snackbar {
|
||||
fun make(view: View, text: CharSequence, duration: Int = LENGTH_SHORT, style: Style = Style.REGULAR): Snackbar {
|
||||
val parent = findSuitableParent(view) ?:
|
||||
throw IllegalArgumentException("No suitable parent found from the given view. Please provide a valid view.")
|
||||
val content = LayoutInflater.from(parent.context).inflate(R.layout.view_snackbar, parent, false)
|
||||
val snackbar = Snackbar(parent, content, ContentViewCallback(content))
|
||||
snackbar.duration = duration
|
||||
|
@ -39,6 +43,36 @@ class Snackbar : BaseTransientBottomBar<Snackbar> {
|
|||
snackbar.setText(text)
|
||||
return snackbar
|
||||
}
|
||||
|
||||
/**
|
||||
* This is adapted from android.support.design.widget.snackbar
|
||||
* It ensures we can use Snackbars in complex ViewGroups like RecyclerView.
|
||||
*/
|
||||
private fun findSuitableParent(view: View): ViewGroup? {
|
||||
var currentView: View? = view
|
||||
var fallbackParent: ViewGroup? = null
|
||||
|
||||
do {
|
||||
if (currentView is CoordinatorLayout)
|
||||
// We've found a CoordinatorLayout, use it
|
||||
return currentView
|
||||
|
||||
if (currentView is FrameLayout)
|
||||
if (currentView.id == android.R.id.content)
|
||||
// If we've hit the decor content view, then we didn't find a CoL in the
|
||||
// hierarchy, so use it.
|
||||
return currentView
|
||||
else
|
||||
// It's not the content view but we'll use it as our fallback
|
||||
fallbackParent = currentView
|
||||
|
||||
// Else, we will loop and crawl up the view hierarchy and try to find a parent
|
||||
currentView = currentView?.parent as? View
|
||||
} while (currentView != null)
|
||||
|
||||
// If we reach here then we didn't find a CoL or a suitable content view so we'll fallback
|
||||
return fallbackParent
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -101,14 +135,20 @@ class Snackbar : BaseTransientBottomBar<Snackbar> {
|
|||
updateBackground()
|
||||
layoutTextAndActionButton()
|
||||
|
||||
val iconImageViewLayoutParams = iconImageView.layoutParams as RelativeLayout.LayoutParams
|
||||
when (style) {
|
||||
Style.REGULAR -> {
|
||||
actionButtonView.setTextColor(ContextCompat.getColor(context, R.color.uifabric_snackbar_action_text))
|
||||
iconImageViewLayoutParams.topMargin = context.resources.getDimension(R.dimen.uifabric_snackbar_icon_inset_regular).toInt()
|
||||
iconImageViewLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL)
|
||||
}
|
||||
Style.ANNOUNCEMENT -> {
|
||||
actionButtonView.setTextColor(ContextCompat.getColor(context, R.color.uifabric_snackbar_action_text_announcement))
|
||||
iconImageViewLayoutParams.topMargin = context.resources.getDimension(R.dimen.uifabric_snackbar_content_inset).toInt()
|
||||
iconImageViewLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL)
|
||||
}
|
||||
}
|
||||
iconImageView.layoutParams = iconImageViewLayoutParams
|
||||
}
|
||||
|
||||
private fun layoutTextAndActionButton() {
|
||||
|
@ -120,12 +160,14 @@ class Snackbar : BaseTransientBottomBar<Snackbar> {
|
|||
if (textWidth > context.resources.getDimension(R.dimen.uifabric_snackbar_action_text_wrapping_width) || style == Style.ANNOUNCEMENT) {
|
||||
// Action button moves to the bottom of the root view
|
||||
textLayoutParams.removeRule(RelativeLayout.START_OF)
|
||||
textLayoutParams.removeRule(RelativeLayout.CENTER_VERTICAL)
|
||||
textLayoutParams.marginEnd = inset
|
||||
buttonLayoutParams.addRule(RelativeLayout.BELOW, snackbar_text)
|
||||
actionButtonView.setPaddingRelative(inset, inset, inset, inset)
|
||||
} else {
|
||||
// Action button moves to the end of the text view
|
||||
textLayoutParams.addRule(RelativeLayout.START_OF, snackbar_action)
|
||||
textLayoutParams.addRule(RelativeLayout.CENTER_VERTICAL)
|
||||
textLayoutParams.bottomMargin = inset
|
||||
if (actionButtonView.text.isNullOrEmpty())
|
||||
textLayoutParams.marginEnd = inset
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
android:layout_height="@dimen/uifabric_snackbar_announcement_icon_size"
|
||||
android:layout_gravity="center_vertical|start"
|
||||
android:layout_marginStart="@dimen/uifabric_snackbar_content_inset"
|
||||
android:layout_marginTop="@dimen/uifabric_snackbar_content_inset"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -82,6 +82,7 @@
|
|||
<dimen name="uifabric_snackbar_background_inset">8dp</dimen>
|
||||
<dimen name="uifabric_snackbar_background_corner_radius">4dp</dimen>
|
||||
<dimen name="uifabric_snackbar_content_inset">@dimen/uifabric_content_inset</dimen>
|
||||
<dimen name="uifabric_snackbar_icon_inset_regular">12dp</dimen>
|
||||
|
||||
<!--Tooltip-->
|
||||
<dimen name="uifabric_tooltip_max_width">176dp</dimen>
|
||||
|
|
Загрузка…
Ссылка в новой задаче