diff options
Diffstat (limited to 'android/src')
9 files changed, 136 insertions, 85 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt index 0deaff3ed8..85f2da5e61 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/LoginFragment.kt @@ -55,6 +55,10 @@ class LoginFragment : ServiceDependentFragment(OnNoService.GoToLaunchScreen) { scrollArea = view.findViewById(R.id.scroll_area) + view.findViewById<View>(R.id.contents).setOnClickListener { + accountLogin.clearFocus() + } + fetchHistory() scrollToShow(accountLogin) diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt index c2acd6a924..131d9c0c65 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLogin.kt @@ -1,9 +1,14 @@ package net.mullvad.mullvadvpn.ui.widget +import android.animation.ValueAnimator +import android.app.Activity import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater import android.view.View +import android.view.View.OnLayoutChangeListener +import android.view.ViewGroup.MarginLayoutParams +import android.view.inputmethod.InputMethodManager import android.widget.ArrayAdapter import android.widget.ListView import android.widget.RelativeLayout @@ -24,40 +29,68 @@ class AccountLogin : RelativeLayout { private val accountHistoryList: ListView = container.findViewById(R.id.history) private val input: AccountInput = container.findViewById(R.id.input) - private var shouldShowAccountHistory = false - set(value) { - synchronized(this) { - field = value - updateAccountHistory() - } + private val dividerHeight = resources.getDimensionPixelSize(R.dimen.account_history_divider) + private val historyEntryHeight = + resources.getDimensionPixelSize(R.dimen.account_history_entry_height) + + private val historyAnimation = ValueAnimator.ofInt(0, 0).apply { + addUpdateListener { animation -> + updateHeight(animation.animatedValue as Int) + } + + duration = 350 + } + + private val expandedHeight: Int + get() = collapsedHeight + historyHeight + + private var historyHeight by observable(0) { _, oldHistoryHeight, newHistoryHeight -> + if (newHistoryHeight != oldHistoryHeight) { + historyAnimation.setIntValues(collapsedHeight, expandedHeight) + reposition() + } + } + + private var collapsedHeight by observable(0) { _, oldCollapsedHeight, newCollapsedHeight -> + if (newCollapsedHeight != oldCollapsedHeight) { + historyAnimation.setIntValues(newCollapsedHeight, expandedHeight) + reposition() } + } private var inputHasFocus by observable(false) { _, _, hasFocus -> updateBorder() + shouldShowAccountHistory = hasFocus - if (hasFocus) { - shouldShowAccountHistory = true + if (!hasFocus) { + hideKeyboard() } } - var accountHistory: ArrayList<String>? = null - set(value) { - synchronized(this) { - field = value - updateAccountHistory() + private var shouldShowAccountHistory by observable(false) { _, isShown, show -> + if (isShown != show) { + if (show) { + historyAnimation.start() + } else { + historyAnimation.reverse() } } + } + + var accountHistory by observable<ArrayList<String>?>(null) { _, _, history -> + val entryCount = history?.size ?: 0 + + historyHeight = entryCount * (historyEntryHeight + dividerHeight) + updateAccountHistory() + } var state: LoginState by observable(LoginState.Initial) { _, _, newState -> input.loginState = newState updateBorder() - when (newState) { - LoginState.Initial -> {} - LoginState.InProgress -> loggingInState() - LoginState.Success -> successState() - LoginState.Failure -> {} + if (newState == LoginState.Success) { + visibility = View.INVISIBLE } } @@ -81,6 +114,8 @@ class AccountLogin : RelativeLayout { } init { + border.elevation = elevation + 0.1f + input.apply { onFocusChanged.subscribe(this) { hasFocus -> inputHasFocus = hasFocus @@ -91,6 +126,12 @@ class AccountLogin : RelativeLayout { state = LoginState.Initial } } + + addOnLayoutChangeListener( + OnLayoutChangeListener { _, _, top, _, bottom, _, _, _, _ -> + collapsedHeight = bottom - top + } + ) } } @@ -99,14 +140,6 @@ class AccountLogin : RelativeLayout { input.onTextChanged.unsubscribe(this) } - private fun loggingInState() { - accountHistoryList.visibility = View.INVISIBLE - } - - private fun successState() { - visibility = View.INVISIBLE - } - private fun updateAccountHistory() { accountHistory?.let { history -> accountHistoryList.apply { @@ -123,12 +156,6 @@ class AccountLogin : RelativeLayout { input.loginWith(history[idx]) } } - - if (shouldShowAccountHistory && accountHistoryList.visibility != View.VISIBLE) { - accountHistoryList.visibility = View.VISIBLE - accountHistoryList.translationY = -accountHistoryList.height.toFloat() - accountHistoryList.animate().translationY(0.0F).setDuration(350).start() - } } } @@ -141,4 +168,30 @@ class AccountLogin : RelativeLayout { border.borderState = BorderState.UNFOCUSED } } + + private fun updateHeight(height: Int) { + val layoutParams = container.layoutParams as MarginLayoutParams + + layoutParams.height = height + layoutParams.bottomMargin = expandedHeight - height + + container.layoutParams = layoutParams + } + + private fun reposition() { + historyAnimation.end() + + if (shouldShowAccountHistory) { + updateHeight(expandedHeight) + } else { + updateHeight(collapsedHeight) + } + } + + private fun hideKeyboard() { + val inputManagerId = Activity.INPUT_METHOD_SERVICE + val inputManager = context.getSystemService(inputManagerId) as InputMethodManager + + inputManager.hideSoftInputFromWindow(windowToken, 0) + } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLoginBorder.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLoginBorder.kt index ee29ef9be0..e5ee732e08 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLoginBorder.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/widget/AccountLoginBorder.kt @@ -72,20 +72,6 @@ class AccountLoginBorder : RelativeLayout { } } - init { - val borderElevation = elevation + 0.1f - - topLeftCorner.elevation = borderElevation - topRightCorner.elevation = borderElevation - bottomLeftCorner.elevation = borderElevation - bottomRightCorner.elevation = borderElevation - - topBorder.elevation = borderElevation - leftBorder.elevation = borderElevation - rightBorder.elevation = borderElevation - bottomBorder.elevation = borderElevation - } - constructor(context: Context) : super(context) {} constructor(context: Context, attributes: AttributeSet) : super(context, attributes) {} diff --git a/android/src/main/res/drawable/account_history_background.xml b/android/src/main/res/drawable/account_history_background.xml deleted file mode 100644 index 596eb2d43d..0000000000 --- a/android/src/main/res/drawable/account_history_background.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> - <item> - <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <corners android:radius="@dimen/account_login_corner_radius" /> - <solid android:color="@color/darkBlue" /> - </shape> - </item> - <item android:top="0dp" - android:right="1dp" - android:bottom="1dp" - android:left="1dp"> - <shape xmlns:android="http://schemas.android.com/apk/res/android"> - <corners android:radius="@dimen/account_login_corner_radius" /> - <solid android:color="@color/white" /> - </shape> - </item> -</layer-list> diff --git a/android/src/main/res/drawable/account_history_entry_background.xml b/android/src/main/res/drawable/account_history_entry_background.xml new file mode 100644 index 0000000000..ea25d2b72a --- /dev/null +++ b/android/src/main/res/drawable/account_history_entry_background.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<selector xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <item android:state_pressed="false" + android:state_focused="false"> + <shape android:shape="rectangle"> + <solid android:color="@color/white60" /> + </shape> + </item> + <item android:state_pressed="true"> + <shape android:shape="rectangle"> + <solid android:color="@color/white40" /> + </shape> + </item> + <item android:state_focused="true"> + <shape android:shape="rectangle"> + <solid android:color="@color/white40" /> + </shape> + </item> +</selector> diff --git a/android/src/main/res/layout/account_history_entry.xml b/android/src/main/res/layout/account_history_entry.xml index 1860a96262..440cce957d 100644 --- a/android/src/main/res/layout/account_history_entry.xml +++ b/android/src/main/res/layout/account_history_entry.xml @@ -1,12 +1,14 @@ <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" - android:layout_height="wrap_content" + android:layout_height="@dimen/account_history_entry_height" android:orientation="vertical"> <TextView android:id="@+id/account_history_entry_text_view" - android:layout_width="fill_parent" - android:layout_height="wrap_content" - android:textColor="@color/blue" - android:padding="10dip" - android:textSize="@dimen/text_medium" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="@drawable/account_history_entry_background" + android:paddingHorizontal="12dp" + android:gravity="center_vertical" + android:textColor="@color/blue80" + android:textSize="@dimen/text_medium_plus" android:textStyle="bold" /> </LinearLayout> diff --git a/android/src/main/res/layout/account_login.xml b/android/src/main/res/layout/account_login.xml index b64a52d6e6..43d76c89e6 100644 --- a/android/src/main/res/layout/account_login.xml +++ b/android/src/main/res/layout/account_login.xml @@ -1,20 +1,18 @@ <merge xmlns:android="http://schemas.android.com/apk/res/android"> <net.mullvad.mullvadvpn.ui.widget.AccountLoginBorder android:id="@+id/border" android:layout_width="match_parent" - android:layout_height="48dp" - android:layout_alignParentTop="true"> - <net.mullvad.mullvadvpn.ui.widget.AccountInput android:id="@+id/input" - android:layout_width="match_parent" - android:layout_height="48dp" - android:layout_alignParentTop="true" - android:orientation="horizontal" /> - </net.mullvad.mullvadvpn.ui.widget.AccountLoginBorder> + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentBottom="true" /> + <net.mullvad.mullvadvpn.ui.widget.AccountInput android:id="@+id/input" + android:layout_width="match_parent" + android:layout_height="48dp" + android:layout_alignParentTop="true" + android:orientation="horizontal" /> <ListView android:id="@+id/history" android:layout_width="fill_parent" android:layout_height="wrap_content" - android:layout_below="@id/border" + android:layout_below="@id/input" android:divider="@drawable/account_history_list_divider" - android:dividerHeight="1dp" - android:visibility="invisible" - android:background="@drawable/account_history_background" /> + android:dividerHeight="@dimen/account_history_divider" /> </merge> diff --git a/android/src/main/res/layout/login.xml b/android/src/main/res/layout/login.xml index 4510d0c627..0f34a409c6 100644 --- a/android/src/main/res/layout/login.xml +++ b/android/src/main/res/layout/login.xml @@ -4,9 +4,13 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:fillViewport="true"> - <LinearLayout android:layout_width="match_parent" + <LinearLayout android:id="@+id/contents" + android:layout_width="match_parent" android:layout_height="match_parent" - android:orientation="vertical"> + android:orientation="vertical" + android:focusable="true" + android:focusableInTouchMode="true" + android:descendantFocusability="beforeDescendants"> <net.mullvad.mullvadvpn.ui.widget.HeaderBar android:id="@+id/header_bar" android:layout_width="match_parent" android:layout_height="wrap_content" /> @@ -66,7 +70,7 @@ android:text="@string/login_description" /> <net.mullvad.mullvadvpn.ui.widget.AccountLogin android:id="@+id/account_login" android:layout_width="match_parent" - android:layout_height="wrap_content" /> + android:layout_height="@dimen/account_history_entry_height" /> <Space android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="3" /> diff --git a/android/src/main/res/values/dimensions.xml b/android/src/main/res/values/dimensions.xml index 692fba86e4..235c3d94b3 100644 --- a/android/src/main/res/values/dimensions.xml +++ b/android/src/main/res/values/dimensions.xml @@ -6,6 +6,8 @@ <dimen name="dialog_margin">14dp</dimen> <dimen name="account_login_corner_radius">4dp</dimen> <dimen name="account_login_border_width">2dp</dimen> + <dimen name="account_history_divider">1dp</dimen> + <dimen name="account_history_entry_height">48dp</dimen> <dimen name="edit_text_corner_radius">4dp</dimen> <dimen name="button_height">44dp</dimen> <dimen name="cell_switch_border_radius">16dp</dimen> |
