Improve landscape layouts on tablets and larger displays

This commit is contained in:
William Brawner 2020-04-19 17:50:44 -07:00
parent a5fd369f9a
commit c178bd196b
9 changed files with 532 additions and 77 deletions

View file

@ -2,12 +2,12 @@ package com.wbrawner.pihelper
import android.os.Bundle
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.ProgressBar
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment
import androidx.navigation.fragment.FragmentNavigatorExtras
@ -42,21 +42,7 @@ class AddPiHoleFragment : Fragment(), CoroutineScope {
connectButton.performClick()
}
connectButton.setSuspendingOnClickListener(this) {
val progressDialog = AlertDialog.Builder(it.context)
.setTitle(R.string.connecting_to_pihole)
.setNegativeButton(R.string.action_cancel) { _, _ ->
cancel()
}
.setView(FrameLayout(it.context).apply {
addView(ProgressBar(it.context).apply {
layoutParams = FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT,
Gravity.CENTER
)
})
})
.show()
showProgress(true)
if (viewModel.connectToIpAddress(ipAddress.text.toString())) {
navController.navigate(
R.id.action_addPiHoleFragment_to_retrieveApiKeyFragment,
@ -71,10 +57,35 @@ class AddPiHoleFragment : Fragment(), CoroutineScope {
.setPositiveButton(android.R.string.ok) { _, _ -> }
.show()
}
progressDialog.dismiss()
showProgress(false)
}
}
private fun showProgress(show: Boolean) {
if (show) {
piHelperLogo.startAnimation(
RotateAnimation(
0f,
360f,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f
).apply {
duration =
resources.getInteger(android.R.integer.config_longAnimTime).toLong() * 2
repeatMode = Animation.RESTART
repeatCount = Animation.INFINITE
interpolator = LinearInterpolator()
fillAfter = true
}
)
} else {
piHelperLogo.clearAnimation()
}
connectionForm.visibility = if (show) View.GONE else View.VISIBLE
}
override fun onDestroyView() {
cancel()
super.onDestroyView()

View file

@ -6,6 +6,9 @@ import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.Animation
import android.view.animation.LinearInterpolator
import android.view.animation.RotateAnimation
import androidx.fragment.app.Fragment
import androidx.lifecycle.Observer
import androidx.navigation.fragment.findNavController
@ -66,7 +69,27 @@ class RetrieveApiKeyFragment : Fragment(), CoroutineScope {
}
private fun showProgress(show: Boolean) {
progressBar.visibility = if (show) View.VISIBLE else View.GONE
if (show) {
piHelperLogo.startAnimation(
RotateAnimation(
0f,
360f,
Animation.RELATIVE_TO_SELF,
0.5f,
Animation.RELATIVE_TO_SELF,
0.5f
).apply {
duration =
resources.getInteger(android.R.integer.config_longAnimTime).toLong() * 2
repeatMode = Animation.RESTART
repeatCount = Animation.INFINITE
interpolator = LinearInterpolator()
fillAfter = true
}
)
} else {
piHelperLogo.clearAnimation()
}
authenticationForm.visibility = if (show) View.GONE else View.VISIBLE
}

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:width="1dp"
android:height="500dp"
android:gravity="center">
<color android:color="@color/colorOnSurface" />
<shape android:shape="rectangle" />
</item>
</layer-list>

View file

@ -0,0 +1,118 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:fillViewport="true"
tools:background="@color/colorSurface"
tools:context=".AddPiHoleFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:padding="16dp">
<ImageView
android:id="@+id/piHelperLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_app_logo"
android:tint="@color/colorOnSurface"
android:transitionName="piHelperLogo"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/connectionForm"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/piHelperLogo">
<TextView
android:id="@+id/scanNetwork"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/info_scan_network"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="@+id/scanNetworkButton"
app:layout_constraintEnd_toStartOf="@+id/orDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="@+id/scanNetworkButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/action_scan_network"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/orDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/scanNetwork" />
<include
android:id="@+id/orDivider"
layout="@layout/or_divider"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/connectDirectly"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/info_connect"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="@+id/scanNetworkButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/orDivider"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/ipAddressContainer"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/prompt_ip_address"
app:layout_constraintBottom_toTopOf="@+id/connectButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/orDivider"
app:layout_constraintTop_toBottomOf="@+id/connectDirectly"
app:layout_constraintVertical_chainStyle="packed">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/ipAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionGo"
android:inputType="text"
android:maxLines="1"
android:text="pi.hole"
tools:ignore="HardcodedText" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/connectButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/action_connect_pihole"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/orDivider"
app:layout_constraintTop_toBottomOf="@+id/ipAddressContainer" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -0,0 +1,113 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
tools:background="@color/colorSurface">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" />
<ScrollView
android:id="@+id/statusContent"
android:layout_width="match_parent"
android:layout_height="0dp"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
tools:visibility="visible">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:orientation="horizontal"
android:padding="16dp"
tools:context=".MainFragment">
<TextView
android:id="@+id/status"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:padding="4dp"
android:textAlignment="center"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/actionButtons"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Enabled"
tools:textColor="@color/colorGreenDark" />
<LinearLayout
android:id="@+id/actionButtons"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/status"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.button.MaterialButton
android:id="@+id/enableButton"
style="@style/AppTheme.Button.Green"
android:text="@string/action_enable" />
<LinearLayout
android:id="@+id/disableButtons"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:visibility="gone"
tools:visibility="visible">
<com.google.android.material.button.MaterialButton
android:id="@+id/disable10SecondsButton"
style="@style/AppTheme.Button.Red"
android:text="@string/action_disable_10_seconds" />
<com.google.android.material.button.MaterialButton
android:id="@+id/disable30SecondsButton"
style="@style/AppTheme.Button.Red"
android:text="@string/action_disable_30_seconds" />
<com.google.android.material.button.MaterialButton
android:id="@+id/disable5MinutesButton"
style="@style/AppTheme.Button.Red"
android:text="@string/action_disable_5_minutes" />
<com.google.android.material.button.MaterialButton
android:id="@+id/disableCustomTimeButton"
style="@style/AppTheme.Button.Red"
android:text="@string/action_disable_custom" />
<com.google.android.material.button.MaterialButton
android:id="@+id/disablePermanentlyButton"
style="@style/AppTheme.Button.Red"
android:text="@string/action_disable_permanently" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<ImageView
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/app_name"
android:src="@drawable/ic_app_logo"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/toolbar"
tools:visibility="gone" />
</androidx.constraintlayout.widget.ConstraintLayout>

View file

@ -0,0 +1,141 @@
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:clipChildren="false"
android:clipToPadding="false"
android:fillViewport="true"
android:padding="16dp"
tools:background="@color/colorSurface"
tools:context=".RetrieveApiKeyFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="400dp"
android:layout_gravity="center">
<ImageView
android:id="@+id/piHelperLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@string/accessibility_description_pi_helper_logo"
android:src="@drawable/ic_app_logo"
android:tint="@color/colorOnSurface"
android:transitionName="piHelperLogo"
app:layout_constraintBottom_toTopOf="@+id/authenticationForm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/authenticationForm"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintHeight_min="wrap"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/piHelperLogo">
<TextView
android:id="@+id/connectionSuccess"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/info_connection_success"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="@+id/authRequired"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/authRequired"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/info_authentication_required"
android:textAlignment="center"
app:layout_constraintBottom_toTopOf="@+id/orDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/connectionSuccess" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/passwordContainer"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/prompt_password"
app:layout_constraintBottom_toTopOf="@+id/connectWithPasswordButton"
app:layout_constraintEnd_toStartOf="@+id/orDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/orDivider"
app:layout_constraintVertical_chainStyle="packed">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionGo"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/connectWithPasswordButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/action_authenticate_password"
app:layout_constraintBottom_toBottomOf="@+id/orDivider"
app:layout_constraintEnd_toStartOf="@+id/orDivider"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/passwordContainer" />
<include
android:id="@+id/orDivider"
layout="@layout/or_divider"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHeight_min="200dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/authRequired" />
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/apiKeyContainer"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:hint="@string/prompt_api_key"
app:layout_constraintBottom_toTopOf="@+id/connectWithApiKeyButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/orDivider"
app:layout_constraintTop_toTopOf="@+id/orDivider"
app:layout_constraintVertical_chainStyle="packed">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/apiKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionGo"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/connectWithApiKeyButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/action_authenticate_api_key"
app:layout_constraintBottom_toBottomOf="@+id/orDivider"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/orDivider"
app:layout_constraintTop_toBottomOf="@+id/apiKeyContainer" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:background="@color/colorSurface">
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1"
android:scaleType="fitXY"
android:src="@drawable/vertical_rule"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="16dp"
android:text="@string/or"
android:textAlignment="center"
android:textAllCaps="true" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="1"
android:scaleType="fitXY"
android:src="@drawable/vertical_rule"
tools:ignore="ContentDescription" />
</LinearLayout>

View file

@ -24,49 +24,55 @@
android:tint="@color/colorOnSurface"
android:transitionName="piHelperLogo" />
<TextView
<LinearLayout
android:id="@+id/connectionForm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/info_scan_network"
android:textAlignment="center" />
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="@+id/scanNetworkButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/action_scan_network" />
<include layout="@layout/or_divider" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/info_connect"
android:textAlignment="center" />
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_ip_address">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/ipAddress"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="pi.hole"
android:inputType="text"
android:maxLines="1"
android:imeOptions="actionGo"
tools:ignore="HardcodedText" />
</com.google.android.material.textfield.TextInputLayout>
android:text="@string/info_scan_network"
android:textAlignment="center" />
<com.google.android.material.button.MaterialButton
android:id="@+id/connectButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/action_connect_pihole" />
<com.google.android.material.button.MaterialButton
android:id="@+id/scanNetworkButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/action_scan_network" />
<include layout="@layout/or_divider" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/info_connect"
android:textAlignment="center" />
<com.google.android.material.textfield.TextInputLayout
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/prompt_ip_address">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/ipAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionGo"
android:inputType="text"
android:maxLines="1"
android:text="pi.hole"
tools:ignore="HardcodedText" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/connectButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/action_connect_pihole" />
</LinearLayout>
</LinearLayout>
</ScrollView>

View file

@ -14,6 +14,21 @@
android:layout_height="wrap_content"
android:layout_gravity="center">
<ImageView
android:id="@+id/piHelperLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_description_pi_helper_logo"
android:src="@drawable/ic_app_logo"
android:tint="@color/colorOnSurface"
android:transitionName="piHelperLogo"
app:layout_constraintBottom_toTopOf="@+id/authenticationForm"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<LinearLayout
android:id="@+id/authenticationForm"
android:layout_width="match_parent"
@ -23,17 +38,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<ImageView
android:id="@+id/piHelperLogo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:contentDescription="@string/accessibility_description_pi_helper_logo"
android:src="@drawable/ic_app_logo"
android:tint="@color/colorOnSurface"
android:transitionName="piHelperLogo" />
app:layout_constraintTop_toBottomOf="@id/piHelperLogo">
<TextView
android:layout_width="match_parent"
@ -92,15 +97,6 @@
</LinearLayout>
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>