Merged PR 216546: PeoplePicker: Dropdown polish
- Using Outlook's adjustDropDownPositionAndSize and getMaxAvailableHeight methods in ContactPickerView to resize the drop down to the available space in the view. This makes the list less jumpy, which is most noticeable when it appears above the anchor. - Switching between portrait and landscape mode no longer dismisses the dropdown nor removes the constraint text. The dropdown also resizes smoothly to adapt. Going from landscape to portrait, the dropdown takes up the full screen, but it does this in Outlook, also. - Removed the default drop shadow for the dropdown and replaced it with a layer-list drawable that gives it a border along the anchor. - Refactored some dimens / color naming Related work items: #670910
This commit is contained in:
Родитель
9e9db96d81
Коммит
80dd8257b3
|
@ -23,7 +23,10 @@
|
|||
<activity android:name="com.microsoft.officeuifabricdemo.demos.AvatarViewActivity" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.CalendarViewActivity" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.DateTimePickerDialogActivity" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.PeoplePickerViewActivity" />
|
||||
<activity
|
||||
android:name="com.microsoft.officeuifabricdemo.demos.PeoplePickerViewActivity"
|
||||
android:configChanges="orientation|keyboardHidden|screenSize"
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.PersonaChipViewActivity" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.PersonaListViewActivity" />
|
||||
<activity android:name="com.microsoft.officeuifabricdemo.demos.PersonaViewActivity" />
|
||||
|
|
|
@ -2,24 +2,24 @@
|
|||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/people_picker_layout"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:showDividers="middle"
|
||||
android:divider="@drawable/ms_row_divider">
|
||||
android:divider="@drawable/ms_row_divider"
|
||||
android:orientation="vertical"
|
||||
android:showDividers="middle">
|
||||
|
||||
<com.microsoft.officeuifabric.peoplepicker.PeoplePickerView
|
||||
android:id="@+id/people_picker_select"
|
||||
app:label="@string/people_picker_select_example"
|
||||
app:personaChipClickStyle="select"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
app:label="@string/people_picker_select_example"
|
||||
app:personaChipClickStyle="select" />
|
||||
|
||||
<com.microsoft.officeuifabric.peoplepicker.PeoplePickerView
|
||||
android:id="@+id/people_picker_select_deselect"
|
||||
app:label="@string/people_picker_select_deselect_example"
|
||||
app:personaChipClickStyle="select_deselect"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
android:layout_height="wrap_content"
|
||||
app:label="@string/people_picker_select_deselect_example"
|
||||
app:personaChipClickStyle="select_deselect" />
|
||||
|
||||
</LinearLayout>
|
|
@ -58,7 +58,7 @@ internal class PeoplePickerTextView : TokenCompleteTextView<IPersona> {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defines what happens when a user clicks on a [personaChip] token.
|
||||
* Defines what happens when a user clicks on a [personaChip].
|
||||
*/
|
||||
var personaChipClickStyle: PeoplePickerPersonaChipClickStyle = PeoplePickerPersonaChipClickStyle.Select
|
||||
set(value) {
|
||||
|
|
|
@ -63,13 +63,12 @@ internal class PeoplePickerTextViewAdapter : ArrayAdapter<IPersona>, Filterable
|
|||
|
||||
private fun createDivider(): InsetDrawable {
|
||||
val spacing = PersonaView.getSpacing(context, AvatarSize.LARGE)
|
||||
val insetDrawable = InsetDrawable(
|
||||
return InsetDrawable(
|
||||
ContextCompat.getDrawable(context, R.drawable.ms_row_divider),
|
||||
spacing.insetLeft,
|
||||
0,
|
||||
spacing.cellPadding,
|
||||
0
|
||||
)
|
||||
return insetDrawable
|
||||
}
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
package com.microsoft.officeuifabric.peoplepicker
|
||||
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.util.AttributeSet
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Filter
|
||||
|
@ -19,13 +21,10 @@ import kotlinx.android.synthetic.main.view_people_picker.view.*
|
|||
typealias PeoplePickerPersonaChipClickStyle = TokenCompleteTextView.TokenClickStyle
|
||||
|
||||
/**
|
||||
* [PeoplePickerView] is a customizable [TemplateView] comprised of a label and [PeoplePickerTextView].
|
||||
* [PeoplePickerView] is a customizable view comprised of a label and [PeoplePickerTextView].
|
||||
*
|
||||
* TODO Future work:
|
||||
* - Handle cases where [pickedPersonas] is modified programmatically.
|
||||
* - Use Outlook's adjustDropDownPositionAndSize and getMaxAvailableHeight methods in ContactPickerView
|
||||
* to resize the drop down to the available space in the view. This will make the list less jumpy,
|
||||
* which is most noticeable when it appears above the [PeoplePickerTextView].
|
||||
*/
|
||||
class PeoplePickerView : TemplateView {
|
||||
/**
|
||||
|
@ -177,6 +176,54 @@ class PeoplePickerView : TemplateView {
|
|||
peoplePickerTextView?.addObject(persona)
|
||||
}
|
||||
|
||||
// Dropdown
|
||||
|
||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
||||
super.onConfigurationChanged(newConfig)
|
||||
adjustDropDownHeight()
|
||||
}
|
||||
|
||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
||||
super.onLayout(changed, left, top, right, bottom)
|
||||
adjustDropDownHeight()
|
||||
}
|
||||
|
||||
private fun adjustDropDownHeight() {
|
||||
val dropDownHeight = getMaxAvailableHeight()
|
||||
if (peoplePickerTextView?.dropDownHeight == dropDownHeight)
|
||||
return
|
||||
peoplePickerTextView?.dropDownHeight = dropDownHeight
|
||||
if (peoplePickerTextView?.isPopupShowing == true)
|
||||
// Force popup layout to refresh
|
||||
peoplePickerTextView?.showDropDown()
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapted from Android's PopupWindow.
|
||||
*/
|
||||
private fun getMaxAvailableHeight(): Int {
|
||||
val displayFrame = Rect()
|
||||
getWindowVisibleDisplayFrame(displayFrame)
|
||||
|
||||
val anchorLocationOnScreen = IntArray(2)
|
||||
getLocationOnScreen(anchorLocationOnScreen)
|
||||
|
||||
val anchorTop = anchorLocationOnScreen[1]
|
||||
val yOffset = resources.getDimension(R.dimen.uifabric_people_picker_dropdown_vertical_offset).toInt()
|
||||
val distanceToBottom = displayFrame.bottom - (anchorTop + height) - yOffset
|
||||
val distanceToTop = anchorTop - displayFrame.top + yOffset
|
||||
var returnedHeight = Math.max(distanceToBottom, distanceToTop)
|
||||
|
||||
val background = peoplePickerTextView?.dropDownBackground
|
||||
if (background != null) {
|
||||
val backgroundPadding = Rect()
|
||||
background.getPadding(backgroundPadding)
|
||||
returnedHeight -= backgroundPadding.top + backgroundPadding.bottom
|
||||
}
|
||||
|
||||
return returnedHeight
|
||||
}
|
||||
|
||||
// Filter
|
||||
|
||||
private class PersonaFilter(val view: PeoplePickerView) : Filter() {
|
||||
|
@ -193,17 +240,17 @@ class PeoplePickerView : TemplateView {
|
|||
|
||||
val availablePersonas = view.availablePersonas
|
||||
val suggestedPersonas: ArrayList<IPersona>
|
||||
if (availablePersonas == null)
|
||||
suggestedPersonas = ArrayList()
|
||||
else
|
||||
if (constraint != null) {
|
||||
suggestedPersonas = when {
|
||||
availablePersonas == null -> ArrayList()
|
||||
constraint != null -> {
|
||||
val searchTerm = constraint.toString().toLowerCase()
|
||||
val filteredResults = availablePersonas.filter {
|
||||
it.name.toLowerCase().contains(searchTerm) && !view.pickedPersonas.contains(it)
|
||||
}
|
||||
suggestedPersonas = ArrayList(filteredResults)
|
||||
} else
|
||||
suggestedPersonas = availablePersonas
|
||||
ArrayList(filteredResults)
|
||||
}
|
||||
else -> availablePersonas
|
||||
}
|
||||
return FilterResults().apply {
|
||||
values = suggestedPersonas
|
||||
count = suggestedPersonas.size
|
||||
|
@ -218,8 +265,7 @@ class PeoplePickerView : TemplateView {
|
|||
view.peoplePickerTextViewAdapter?.personas = it
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
view.peoplePickerTextViewAdapter?.personas = results.values as ArrayList<IPersona>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -164,7 +164,7 @@ class PersonaChipView : TemplateView {
|
|||
|
||||
private fun setDisabledState() {
|
||||
avatarView?.alpha = DISABLED_BACKGROUND_OPACITY
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal, R.color.uifabric_chip_disabled_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal, R.color.uifabric_persona_chip_disabled_text)
|
||||
}
|
||||
|
||||
private fun setNormalState() {
|
||||
|
@ -173,15 +173,15 @@ class PersonaChipView : TemplateView {
|
|||
updateCloseIconVisibility(false)
|
||||
}
|
||||
if (hasError) {
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal_error, R.color.uifabric_chip_error_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal_error, R.color.uifabric_persona_chip_error_text)
|
||||
|
||||
} else {
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal, R.color.uifabric_chip_normal_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_normal, R.color.uifabric_persona_chip_normal_text)
|
||||
}
|
||||
}
|
||||
|
||||
private fun setPressedState() {
|
||||
updateStateStyles(R.drawable.persona_chip_background_pressed, R.color.uifabric_chip_normal_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_pressed, R.color.uifabric_persona_chip_normal_text)
|
||||
}
|
||||
|
||||
private fun setSelectedState() {
|
||||
|
@ -189,9 +189,9 @@ class PersonaChipView : TemplateView {
|
|||
updateCloseIconVisibility(true)
|
||||
}
|
||||
if (hasError) {
|
||||
updateStateStyles(R.drawable.persona_chip_background_active_error, R.color.uifabric_chip_active_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_active_error, R.color.uifabric_persona_chip_active_text)
|
||||
} else {
|
||||
updateStateStyles(R.drawable.persona_chip_background_active, R.color.uifabric_chip_active_text)
|
||||
updateStateStyles(R.drawable.persona_chip_background_active, R.color.uifabric_persona_chip_active_text)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/people_picker_popup_background_above" android:state_above_anchor="true" />
|
||||
<item android:drawable="@drawable/people_picker_popup_background_below" />
|
||||
</selector>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:drawable="@drawable/ms_row_divider"
|
||||
android:gravity="bottom" />
|
||||
<item android:bottom="@dimen/uifabric_divider_height">
|
||||
<color android:color="@color/uifabric_people_picker_popup_background" />
|
||||
</item>
|
||||
</layer-list>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:drawable="@drawable/ms_row_divider"
|
||||
android:gravity="top" />
|
||||
<item android:top="@dimen/uifabric_divider_height">
|
||||
<color android:color="@color/uifabric_people_picker_popup_background" />
|
||||
</item>
|
||||
</layer-list>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/uifabric_chip_active" />
|
||||
<solid android:color="@color/uifabric_persona_chip_active" />
|
||||
<corners android:radius="@dimen/uifabric_corner_radius_2dp" />
|
||||
</shape>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/uifabric_chip_error_active" />
|
||||
<solid android:color="@color/uifabric_persona_chip_error_active" />
|
||||
<corners android:radius="@dimen/uifabric_corner_radius_2dp" />
|
||||
</shape>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/uifabric_chip_normal" />
|
||||
<solid android:color="@color/uifabric_persona_chip_normal" />
|
||||
<corners android:radius="@dimen/uifabric_corner_radius_2dp" />
|
||||
</shape>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/uifabric_chip_error" />
|
||||
<solid android:color="@color/uifabric_persona_chip_error" />
|
||||
<corners android:radius="@dimen/uifabric_corner_radius_2dp" />
|
||||
</shape>
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--Copyright (c) 2018. Microsoft Corporation. All rights reserved.-->
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="@color/uifabric_chip_pressed"/>
|
||||
<solid android:color="@color/uifabric_persona_chip_pressed"/>
|
||||
<corners android:radius="@dimen/uifabric_corner_radius_2dp" />
|
||||
</shape>
|
|
@ -29,14 +29,16 @@
|
|||
android:id="@+id/people_picker_text_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/uifabric_white"
|
||||
android:background="@color/uifabric_people_picker_text_view_background"
|
||||
android:gravity="center_vertical"
|
||||
android:dropDownWidth="match_parent"
|
||||
android:dropDownVerticalOffset="@dimen/uifabric_people_picker_dropdown_vertical_offset"
|
||||
android:imeOptions="flagNoExtractUi|actionDone"
|
||||
android:minHeight="@dimen/uifabric_min_touch_size"
|
||||
android:paddingTop="@dimen/uifabric_people_picker_token_padding"
|
||||
android:paddingBottom="@dimen/uifabric_people_picker_token_padding"
|
||||
android:paddingTop="@dimen/uifabric_people_picker_text_view_padding"
|
||||
android:paddingBottom="@dimen/uifabric_people_picker_text_view_padding"
|
||||
android:popupBackground="@drawable/people_picker_popup_background"
|
||||
android:popupElevation="@dimen/uifabric_people_picker_popup_elevation"
|
||||
android:textAppearance="@style/TextAppearance.UIFabric.PeoplePickerText"
|
||||
android:textColorHint="@android:color/transparent" />
|
||||
|
||||
|
|
|
@ -5,23 +5,23 @@
|
|||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="@dimen/uifabric_chip_height"
|
||||
android:layout_height="@dimen/uifabric_persona_chip_height"
|
||||
android:baselineAligned="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="@dimen/uifabric_chip_padding">
|
||||
android:padding="@dimen/uifabric_persona_chip_padding">
|
||||
|
||||
<com.microsoft.officeuifabric.persona.AvatarView
|
||||
android:id="@+id/persona_chip_avatar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/uifabric_chip_spacing"
|
||||
android:layout_marginEnd="@dimen/uifabric_persona_chip_spacing"
|
||||
app:avatarSize="xsmall" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/persona_chip_close"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginEnd="@dimen/uifabric_chip_spacing"
|
||||
android:layout_marginEnd="@dimen/uifabric_persona_chip_spacing"
|
||||
android:src="@drawable/ms_ic_close"/>
|
||||
|
||||
<TextView
|
||||
|
|
|
@ -47,21 +47,6 @@
|
|||
<item>#393939</item>
|
||||
</array>
|
||||
|
||||
<!--Chips-->
|
||||
<color name="uifabric_chip_normal">@color/uifabric_background_gray</color>
|
||||
<color name="uifabric_chip_normal_text">@color/uifabric_black</color>
|
||||
<!-- TODO update after design adds #0D000000 to toolkit -->
|
||||
<color name="uifabric_chip_pressed">#0D000000</color>
|
||||
<color name="uifabric_chip_active">@color/uifabric_primary</color>
|
||||
<color name="uifabric_chip_active_text">@color/uifabric_white</color>
|
||||
<!-- TODO update after design adds #FFF3F4 to toolkit -->
|
||||
<color name="uifabric_chip_error">#FFF3F4</color>
|
||||
<!-- TODO update after design adds #E8484C to toolkit -->
|
||||
<color name="uifabric_chip_error_active">#E8484C</color>
|
||||
<!-- TODO update after design adds #A80000 to toolkit -->
|
||||
<color name="uifabric_chip_error_text">#A80000</color>
|
||||
<color name="uifabric_chip_disabled_text">@color/uifabric_gray</color>
|
||||
|
||||
<!--CalendarView-->
|
||||
<color name="uifabric_calendar_week_header_background">@color/uifabric_primary</color>
|
||||
<color name="uifabric_calendar_week_heading_week_day_text">@color/uifabric_gray</color>
|
||||
|
@ -86,6 +71,25 @@
|
|||
<color name="uifabric_number_picker_default_accent">@color/uifabric_primary</color>
|
||||
<color name="uifabric_number_picker_default_text">@color/uifabric_gray</color>
|
||||
|
||||
<!--PeoplePicker-->
|
||||
<color name="uifabric_people_picker_popup_background">@color/uifabric_white</color>
|
||||
<color name="uifabric_people_picker_text_view_background">@color/uifabric_white</color>
|
||||
|
||||
<!--Persona Chip-->
|
||||
<color name="uifabric_persona_chip_normal">@color/uifabric_background_gray</color>
|
||||
<color name="uifabric_persona_chip_normal_text">@color/uifabric_black</color>
|
||||
<!-- TODO update after design adds #0D000000 to toolkit -->
|
||||
<color name="uifabric_persona_chip_pressed">#0D000000</color>
|
||||
<color name="uifabric_persona_chip_active">@color/uifabric_primary</color>
|
||||
<color name="uifabric_persona_chip_active_text">@color/uifabric_white</color>
|
||||
<!-- TODO update after design adds #FFF3F4 to toolkit -->
|
||||
<color name="uifabric_persona_chip_error">#FFF3F4</color>
|
||||
<!-- TODO update after design adds #E8484C to toolkit -->
|
||||
<color name="uifabric_persona_chip_error_active">#E8484C</color>
|
||||
<!-- TODO update after design adds #A80000 to toolkit -->
|
||||
<color name="uifabric_persona_chip_error_text">#A80000</color>
|
||||
<color name="uifabric_persona_chip_disabled_text">@color/uifabric_gray</color>
|
||||
|
||||
<!--Shared-->
|
||||
<color name="uifabric_divider">@color/uifabric_border_gray</color>
|
||||
|
||||
|
|
|
@ -40,8 +40,9 @@
|
|||
<dimen name="uifabric_number_picker_padding_right">8dp</dimen>
|
||||
|
||||
<!--PeoplePicker-->
|
||||
<dimen name="uifabric_people_picker_token_padding">6dp</dimen>
|
||||
<dimen name="uifabric_people_picker_popup_elevation">0dp</dimen>
|
||||
<dimen name="uifabric_people_picker_dropdown_vertical_offset">0dp</dimen>
|
||||
<dimen name="uifabric_people_picker_text_view_padding">6dp</dimen>
|
||||
|
||||
<!--Persona-->
|
||||
<dimen name="uifabric_persona_horizontal_spacing">16dp</dimen>
|
||||
|
@ -51,9 +52,9 @@
|
|||
<dimen name="uifabric_persona_label_spacing">8dp</dimen>
|
||||
|
||||
<!--PersonaChip-->
|
||||
<dimen name="uifabric_chip_height">32dp</dimen>
|
||||
<dimen name="uifabric_chip_padding">6dp</dimen>
|
||||
<dimen name="uifabric_chip_spacing">6dp</dimen>
|
||||
<dimen name="uifabric_persona_chip_height">32dp</dimen>
|
||||
<dimen name="uifabric_persona_chip_padding">6dp</dimen>
|
||||
<dimen name="uifabric_persona_chip_spacing">6dp</dimen>
|
||||
|
||||
<!--Shared-->
|
||||
<dimen name="uifabric_divider_height">.5dp</dimen>
|
||||
|
|
Загрузка…
Ссылка в новой задаче