diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-09-01 07:13:47 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-09-01 07:13:47 -0300 |
| commit | da5205bb189c74d2d15200cba0164c9dba484812 (patch) | |
| tree | ad13764f6bb87ebd67c419207eea3174a85f6efb | |
| parent | 8334f1ca8dcf1e5fb4e062fd45c0e96ad3759c70 (diff) | |
| parent | 0686e984c70ae6a6d92f9dcbb90828197e74f4e7 (diff) | |
| download | mullvadvpn-da5205bb189c74d2d15200cba0164c9dba484812.tar.xz mullvadvpn-da5205bb189c74d2d15200cba0164c9dba484812.zip | |
Merge branch 'change-account-input-border-rendering'
14 files changed, 215 insertions, 109 deletions
diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt index f1723b2d34..76ac2a86cf 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInput.kt @@ -90,11 +90,7 @@ class AccountInput(val parentView: View, context: Context) { ) } - container.apply { - clipToOutline = true - outlineProvider = AccountInputOutlineProvider(context) - setOnClickListener { shouldShowAccountHistory = true } - } + container.setOnClickListener { shouldShowAccountHistory = true } } private fun initialState() { diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputContainer.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputContainer.kt index 22aa7d3234..4ef365e876 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputContainer.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputContainer.kt @@ -1,33 +1,91 @@ package net.mullvad.mullvadvpn.ui import android.content.Context +import android.graphics.drawable.Drawable import android.util.AttributeSet -import android.widget.LinearLayout +import android.view.LayoutInflater +import android.widget.ImageView +import android.widget.RelativeLayout import net.mullvad.mullvadvpn.R -class AccountInputContainer : LinearLayout { +class AccountInputContainer : RelativeLayout { enum class BorderState { UNFOCUSED, FOCUSED, ERROR } - private val errorBorder = resources.getDrawable(R.drawable.account_input_border_error, null) - private val focusedBorder = resources.getDrawable(R.drawable.account_input_border_focused, null) + // The horizontal and vertical drawables are identical, but they must be separate objects + // because the view that uses them changes the bounds of the drawable. If they are shared + // between the horizontal and vertical views either the drawable becomes a vertical line or a + // horizontal line, and as a consequence either the horizontal or the vertical borders don't + // show correctly, respectively. + private class StateDrawables( + val corner: Drawable, + val horizontalBorder: Drawable, + val verticalBorder: Drawable + ) + + private val unfocusedDrawables = StateDrawables( + resources.getDrawable(R.drawable.account_input_corner, null), + resources.getDrawable(R.drawable.account_input_border, null), + resources.getDrawable(R.drawable.account_input_border, null) + ) + + private val focusedDrawables = StateDrawables( + resources.getDrawable(R.drawable.account_input_corner_focused, null), + resources.getDrawable(R.drawable.account_input_border_focused, null), + resources.getDrawable(R.drawable.account_input_border_focused, null) + ) + + private val errorDrawables = StateDrawables( + resources.getDrawable(R.drawable.account_input_corner_error, null), + resources.getDrawable(R.drawable.account_input_border_error, null), + resources.getDrawable(R.drawable.account_input_border_error, null) + ) + + private val container = + context.getSystemService(Context.LAYOUT_INFLATER_SERVICE).let { service -> + val inflater = service as LayoutInflater + + inflater.inflate(R.layout.account_input_container, this) + } + + private val topLeftCorner: ImageView = container.findViewById(R.id.top_left_corner) + private val topRightCorner: ImageView = container.findViewById(R.id.top_right_corner) + private val bottomLeftCorner: ImageView = container.findViewById(R.id.bottom_left_corner) + private val bottomRightCorner: ImageView = container.findViewById(R.id.bottom_right_corner) + + private val topBorder: ImageView = container.findViewById(R.id.top_border) + private val leftBorder: ImageView = container.findViewById(R.id.left_border) + private val rightBorder: ImageView = container.findViewById(R.id.right_border) + private val bottomBorder: ImageView = container.findViewById(R.id.bottom_border) var borderState = BorderState.UNFOCUSED set(value) { field = value - overlay.clear() - when (value) { - BorderState.UNFOCUSED -> {} - BorderState.FOCUSED -> overlay.add(focusedBorder) - BorderState.ERROR -> overlay.add(errorBorder) + BorderState.UNFOCUSED -> setBorder(unfocusedDrawables) + BorderState.FOCUSED -> setBorder(focusedDrawables) + BorderState.ERROR -> setBorder(errorDrawables) } } + 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) {} @@ -43,21 +101,16 @@ class AccountInputContainer : LinearLayout { ) : super(context, attributes, defaultStyleAttribute, defaultStyleResource) { } - protected override fun onLayout( - changed: Boolean, - left: Int, - top: Int, - right: Int, - bottom: Int - ) { - super.onLayout(changed, left, top, right, bottom) + private fun setBorder(drawables: StateDrawables) { + topLeftCorner.setImageDrawable(drawables.corner) + topRightCorner.setImageDrawable(drawables.corner) + bottomLeftCorner.setImageDrawable(drawables.corner) + bottomRightCorner.setImageDrawable(drawables.corner) - if (changed) { - val width = right - left - val height = bottom - top + leftBorder.setImageDrawable(drawables.verticalBorder) + rightBorder.setImageDrawable(drawables.verticalBorder) - errorBorder.setBounds(0, 0, width, height) - focusedBorder.setBounds(0, 0, width, height) - } + topBorder.setImageDrawable(drawables.horizontalBorder) + bottomBorder.setImageDrawable(drawables.horizontalBorder) } } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputOutlineProvider.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputOutlineProvider.kt deleted file mode 100644 index df35f447fb..0000000000 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/ui/AccountInputOutlineProvider.kt +++ /dev/null @@ -1,15 +0,0 @@ -package net.mullvad.mullvadvpn.ui - -import android.content.Context -import android.graphics.Outline -import android.view.View -import android.view.ViewOutlineProvider -import net.mullvad.mullvadvpn.R - -class AccountInputOutlineProvider(private val context: Context) : ViewOutlineProvider() { - private val cornerRadius = context.resources.getDimension(R.dimen.account_input_corner_radius) - - override fun getOutline(view: View, outline: Outline) { - outline.setRoundRect(0, 0, view.width, view.height, cornerRadius) - } -} diff --git a/android/src/main/res/drawable/account_input_background.xml b/android/src/main/res/drawable/account_input_background.xml index 63c5c6901f..d31775f404 100644 --- a/android/src/main/res/drawable/account_input_background.xml +++ b/android/src/main/res/drawable/account_input_background.xml @@ -2,25 +2,13 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <item android:state_enabled="false"> - <inset android:insetTop="1dp" - android:insetBottom="1dp" - android:insetLeft="1dp" - android:insetRight="1dp"> - <shape android:shape="rectangle"> - <corners android:radius="@dimen/account_input_corner_radius" /> - <solid android:color="@color/white20" /> - </shape> - </inset> + <shape android:shape="rectangle"> + <solid android:color="@color/white20" /> + </shape> </item> <item android:state_enabled="true"> - <inset android:insetTop="1dp" - android:insetBottom="1dp" - android:insetLeft="1dp"> - <shape android:shape="rectangle"> - <corners android:bottomLeftRadius="@dimen/account_input_corner_radius" - android:topLeftRadius="@dimen/account_input_corner_radius" /> - <solid android:color="@color/white" /> - </shape> - </inset> + <shape android:shape="rectangle"> + <solid android:color="@color/white" /> + </shape> </item> </selector> diff --git a/android/src/main/res/drawable/account_input_border.xml b/android/src/main/res/drawable/account_input_border.xml new file mode 100644 index 0000000000..7aa3362f35 --- /dev/null +++ b/android/src/main/res/drawable/account_input_border.xml @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="utf-8"?> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/blue" /> +</shape> diff --git a/android/src/main/res/drawable/account_input_border_error.xml b/android/src/main/res/drawable/account_input_border_error.xml index d2112104ef..7b0b225c85 100644 --- a/android/src/main/res/drawable/account_input_border_error.xml +++ b/android/src/main/res/drawable/account_input_border_error.xml @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <corners android:radius="@dimen/account_input_corner_radius" /> - <stroke android:width="2dp" - android:color="@color/red" /> + <solid android:color="@color/red" /> </shape> diff --git a/android/src/main/res/drawable/account_input_border_focused.xml b/android/src/main/res/drawable/account_input_border_focused.xml index 551399bb0a..fa32039e1d 100644 --- a/android/src/main/res/drawable/account_input_border_focused.xml +++ b/android/src/main/res/drawable/account_input_border_focused.xml @@ -1,7 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> - <corners android:radius="@dimen/account_input_corner_radius" /> - <stroke android:width="2dp" - android:color="@color/darkBlue" /> + <solid android:color="@color/darkBlue" /> </shape> diff --git a/android/src/main/res/drawable/account_input_corner.xml b/android/src/main/res/drawable/account_input_corner.xml new file mode 100644 index 0000000000..aed002b4ec --- /dev/null +++ b/android/src/main/res/drawable/account_input_corner.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="@dimen/account_input_corner_radius" + android:height="@dimen/account_input_corner_radius" + android:viewportWidth="4.0" + android:viewportHeight="4.0"> + <path android:fillColor="@color/blue" + android:pathData="M 0 4 H 2 A 2 2 0 0 1 4 2 V 0 H 0 Z" /> +</vector> diff --git a/android/src/main/res/drawable/account_input_corner_error.xml b/android/src/main/res/drawable/account_input_corner_error.xml new file mode 100644 index 0000000000..c3acb16404 --- /dev/null +++ b/android/src/main/res/drawable/account_input_corner_error.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="@dimen/account_input_corner_radius" + android:height="@dimen/account_input_corner_radius" + android:viewportWidth="4.0" + android:viewportHeight="4.0"> + <path android:fillColor="@color/blue" + android:pathData="M 0 4 H 1 A 3 3 0 0 1 4 1 V 0 H 0 Z" /> + <path android:fillColor="@color/red" + android:pathData="M 0 4 A 4 4 0 0 1 4 0 V 2 A 2 2 0 0 0 2 4 Z" /> +</vector> diff --git a/android/src/main/res/drawable/account_input_corner_focused.xml b/android/src/main/res/drawable/account_input_corner_focused.xml new file mode 100644 index 0000000000..1370463d49 --- /dev/null +++ b/android/src/main/res/drawable/account_input_corner_focused.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="utf-8"?> +<vector xmlns:android="http://schemas.android.com/apk/res/android" + android:width="@dimen/account_input_corner_radius" + android:height="@dimen/account_input_corner_radius" + android:viewportWidth="4.0" + android:viewportHeight="4.0"> + <path android:fillColor="@color/blue" + android:pathData="M 0 4 H 1 A 3 3 0 0 1 4 1 V 0 H 0 Z" /> + <path android:fillColor="@color/darkBlue" + android:pathData="M 0 4 A 4 4 0 0 1 4 0 V 2 A 2 2 0 0 0 2 4 Z" /> +</vector> diff --git a/android/src/main/res/drawable/login_button_background.xml b/android/src/main/res/drawable/login_button_background.xml index d8243a7075..c1041ef523 100644 --- a/android/src/main/res/drawable/login_button_background.xml +++ b/android/src/main/res/drawable/login_button_background.xml @@ -2,25 +2,13 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <item android:state_enabled="false"> - <inset android:insetTop="1dp" - android:insetBottom="1dp" - android:insetRight="1dp"> - <shape android:shape="rectangle"> - <corners android:bottomRightRadius="@dimen/account_input_corner_radius" - android:topRightRadius="@dimen/account_input_corner_radius" /> - <solid android:color="@color/white" /> - </shape> - </inset> + <shape android:shape="rectangle"> + <solid android:color="@color/white" /> + </shape> </item> <item android:state_enabled="true"> - <inset android:insetTop="1dp" - android:insetBottom="1dp" - android:insetRight="1dp"> - <shape android:shape="rectangle"> - <corners android:bottomRightRadius="@dimen/account_input_corner_radius" - android:topRightRadius="@dimen/account_input_corner_radius" /> - <solid android:color="@color/green" /> - </shape> - </inset> + <shape android:shape="rectangle"> + <solid android:color="@color/green" /> + </shape> </item> </selector> diff --git a/android/src/main/res/layout/account_input_container.xml b/android/src/main/res/layout/account_input_container.xml new file mode 100644 index 0000000000..43e0fbea8b --- /dev/null +++ b/android/src/main/res/layout/account_input_container.xml @@ -0,0 +1,59 @@ +<merge xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- corners --> + <ImageView android:id="@+id/top_left_corner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentLeft="true" + android:src="@drawable/account_input_corner" /> + <ImageView android:id="@+id/top_right_corner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentTop="true" + android:layout_alignParentRight="true" + android:rotation="90" + android:src="@drawable/account_input_corner" /> + <ImageView android:id="@+id/bottom_right_corner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentRight="true" + android:rotation="180" + android:src="@drawable/account_input_corner" /> + <ImageView android:id="@+id/bottom_left_corner" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_alignParentBottom="true" + android:layout_alignParentLeft="true" + android:rotation="270" + android:src="@drawable/account_input_corner" /> + <!-- sides --> + <ImageView android:id="@+id/left_border" + android:layout_width="@dimen/account_input_border_width" + android:layout_height="wrap_content" + android:layout_alignParentLeft="true" + android:layout_below="@id/top_left_corner" + android:layout_above="@id/bottom_left_corner" + android:src="@drawable/account_input_border" /> + <ImageView android:id="@+id/right_border" + android:layout_width="@dimen/account_input_border_width" + android:layout_height="wrap_content" + android:layout_alignParentRight="true" + android:layout_below="@id/top_right_corner" + android:layout_above="@id/bottom_right_corner" + android:src="@drawable/account_input_border" /> + <ImageView android:id="@+id/top_border" + android:layout_width="wrap_content" + android:layout_height="@dimen/account_input_border_width" + android:layout_toLeftOf="@id/top_right_corner" + android:layout_toRightOf="@id/top_left_corner" + android:layout_alignParentTop="true" + android:src="@drawable/account_input_border" /> + <ImageView android:id="@+id/bottom_border" + android:layout_width="wrap_content" + android:layout_height="@dimen/account_input_border_width" + android:layout_toLeftOf="@id/bottom_right_corner" + android:layout_toRightOf="@id/bottom_left_corner" + android:layout_alignParentBottom="true" + android:src="@drawable/account_input_border" /> +</merge> diff --git a/android/src/main/res/layout/login.xml b/android/src/main/res/layout/login.xml index bfa0d88e23..87e240928c 100644 --- a/android/src/main/res/layout/login.xml +++ b/android/src/main/res/layout/login.xml @@ -66,30 +66,34 @@ android:text="@string/login_description" /> <net.mullvad.mullvadvpn.ui.AccountInputContainer android:id="@+id/account_input_container" android:layout_width="match_parent" - android:layout_height="48dp" - android:orientation="horizontal"> - <EditText android:id="@+id/account_input" - android:digits="0123456789" - android:layout_width="match_parent" - android:layout_height="match_parent" - android:layout_weight="1" - android:paddingHorizontal="12dp" - android:background="@drawable/account_input_background" - android:inputType="number" - android:singleLine="true" - android:imeOptions="flagNoPersonalizedLearning" - android:textCursorDrawable="@drawable/text_input_cursor" - android:hint="@string/login_hint" - android:textColorHint="@color/blue40" - android:textColor="@color/blue" - android:textSize="@dimen/text_medium_plus" - android:textStyle="bold" /> - <ImageButton android:id="@+id/login_button" - android:layout_width="48dp" - android:layout_height="match_parent" - android:layout_weight="0" - android:background="@drawable/login_button_background" - android:src="@drawable/login_button_arrow" /> + android:layout_height="48dp"> + <LinearLayout android:layout_width="match_parent" + android:layout_height="48dp" + android:layout_alignParentTop="true" + android:orientation="horizontal"> + <EditText android:id="@+id/account_input" + android:digits="0123456789" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_weight="1" + android:paddingHorizontal="12dp" + android:background="@drawable/account_input_background" + android:inputType="number" + android:singleLine="true" + android:imeOptions="flagNoPersonalizedLearning" + android:textCursorDrawable="@drawable/text_input_cursor" + android:hint="@string/login_hint" + android:textColorHint="@color/blue40" + android:textColor="@color/blue" + android:textSize="@dimen/text_medium_plus" + android:textStyle="bold" /> + <ImageButton android:id="@+id/login_button" + android:layout_width="48dp" + android:layout_height="match_parent" + android:layout_weight="0" + android:background="@drawable/login_button_background" + android:src="@drawable/login_button_arrow" /> + </LinearLayout> </net.mullvad.mullvadvpn.ui.AccountInputContainer> <ListView android:id="@+id/account_history_list" android:layout_width="fill_parent" diff --git a/android/src/main/res/values/dimensions.xml b/android/src/main/res/values/dimensions.xml index d06f80e517..1d87dc8350 100644 --- a/android/src/main/res/values/dimensions.xml +++ b/android/src/main/res/values/dimensions.xml @@ -5,6 +5,7 @@ <dimen name="list_item_divider">1dp</dimen> <dimen name="dialog_margin">14dp</dimen> <dimen name="account_input_corner_radius">4dp</dimen> + <dimen name="account_input_border_width">2dp</dimen> <dimen name="edit_text_corner_radius">4dp</dimen> <dimen name="normal_button_height">44dp</dimen> <dimen name="tall_button_height">64dp</dimen> |
