From 08d290562c9c2bc0b035d7541d0f6e43c4d8fdd8 Mon Sep 17 00:00:00 2001 From: YeyeBBC Date: Wed, 27 Mar 2024 13:09:01 +0800 Subject: [PATCH 1/2] - Updated dependencies. - Updated Material Design Components. - Added support for Edge-to-edge display (Android 11 or later) - Added smooth keyboard animation (Android 11 or later) - Changed strings from hard coded into referenced, so that they can be localised. - Added Chinese translations. - Added Japanese translations. --- app/build.gradle | 18 ++--- app/src/main/AndroidManifest.xml | 3 +- .../java/com/slavabarkov/tidy/MainActivity.kt | 9 +++ .../tidy/fragments/IndexFragment.kt | 12 +++- .../tidy/fragments/SearchFragment.kt | 66 +++++++++++++++++++ app/src/main/res/layout/fragment_index.xml | 2 +- app/src/main/res/layout/fragment_search.xml | 45 ++++++++----- app/src/main/res/values-ja/strings.xml | 7 ++ app/src/main/res/values-night/themes.xml | 2 +- app/src/main/res/values-zh-rCN/strings.xml | 8 +++ app/src/main/res/values-zh-rTW/strings.xml | 8 +++ app/src/main/res/values/dimens.xml | 4 ++ app/src/main/res/values/strings.xml | 4 ++ app/src/main/res/values/themes.xml | 2 +- 14 files changed, 158 insertions(+), 32 deletions(-) create mode 100755 app/src/main/res/values-ja/strings.xml create mode 100644 app/src/main/res/values-zh-rCN/strings.xml create mode 100644 app/src/main/res/values-zh-rTW/strings.xml create mode 100644 app/src/main/res/values/dimens.xml diff --git a/app/build.gradle b/app/build.gradle index 31478b4..45054fa 100755 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,7 +6,7 @@ plugins { android { namespace 'com.slavabarkov.tidy' - compileSdk 33 + compileSdk 34 defaultConfig { applicationId "com.slavabarkov.tidy" @@ -34,17 +34,17 @@ android { } dependencies { - implementation 'androidx.navigation:navigation-fragment-ktx:2.5.3' - implementation 'androidx.navigation:navigation-ui-ktx:2.5.3' - implementation 'androidx.room:room-runtime:2.5.0' - kapt 'androidx.room:room-compiler:2.5.0' - implementation 'androidx.room:room-ktx:2.5.0' + implementation 'androidx.navigation:navigation-fragment-ktx:2.7.7' + implementation 'androidx.navigation:navigation-ui-ktx:2.7.7' + implementation 'androidx.room:room-runtime:2.6.1' + kapt 'androidx.room:room-compiler:2.6.1' + implementation 'androidx.room:room-ktx:2.6.1' implementation 'com.google.code.gson:gson:2.10.1' implementation 'com.github.bumptech.glide:glide:4.13.2' - api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1' - implementation 'androidx.core:core-ktx:1.9.0' + api 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0' + implementation 'androidx.core:core-ktx:1.12.0' implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'com.google.android.material:material:1.8.0' + implementation 'com.google.android.material:material:1.11.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ba62580..7928260 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -14,7 +14,8 @@ android:supportsRtl="true" android:theme="@style/Theme.TIDY" tools:targetApi="31" - android:largeHeap="true"> + android:largeHeap="true" + android:windowSoftInputMode="adjustResize"> = 30 ) { + // Code to handle API level 30 (Android 11) + // When Android >= 11, enable “Display content edge-to-edge” + // See more in https://developer.android.com/develop/ui/views/layout/edge-to-edge + enableEdgeToEdge() + } super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) diff --git a/app/src/main/java/com/slavabarkov/tidy/fragments/IndexFragment.kt b/app/src/main/java/com/slavabarkov/tidy/fragments/IndexFragment.kt index db89b76..4c45259 100755 --- a/app/src/main/java/com/slavabarkov/tidy/fragments/IndexFragment.kt +++ b/app/src/main/java/com/slavabarkov/tidy/fragments/IndexFragment.kt @@ -4,6 +4,7 @@ package com.slavabarkov.tidy.fragments +import android.os.Build import android.os.Bundle import android.view.LayoutInflater import android.view.View @@ -41,8 +42,10 @@ class IndexFragment : Fragment() { val view = inflater.inflate(R.layout.fragment_index, container, false) activity?.window?.addFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) // Request required permissions depending on the Android version - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) { - permissionsRequest.launch(android.Manifest.permission.READ_MEDIA_IMAGES) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + permissionsRequest.launch(android.Manifest.permission.READ_MEDIA_IMAGES) + } } else { permissionsRequest.launch(android.Manifest.permission.READ_EXTERNAL_STORAGE) @@ -54,7 +57,10 @@ class IndexFragment : Fragment() { mORTImageViewModel.progress.observe(viewLifecycleOwner) { progress -> var progressPercent: Int = (progress * 100).toInt() progressBarView?.progress = progressPercent - progressBarTextView?.text = "Updating image index: ${progressPercent}%" + + //Reference progress_bar_text in strings.xml for better localisation. + val myString = getString(R.string.progress_bar_text) + "${myString}: ${progressPercent}%".also { progressBarTextView?.text = it } if (progress == 1.0) { activity?.window?.clearFlags(android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) diff --git a/app/src/main/java/com/slavabarkov/tidy/fragments/SearchFragment.kt b/app/src/main/java/com/slavabarkov/tidy/fragments/SearchFragment.kt index 5ff6ede..a20189c 100755 --- a/app/src/main/java/com/slavabarkov/tidy/fragments/SearchFragment.kt +++ b/app/src/main/java/com/slavabarkov/tidy/fragments/SearchFragment.kt @@ -10,6 +10,9 @@ import android.view.View import android.view.ViewGroup import android.widget.Button import android.widget.TextView +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsAnimationCompat +import androidx.core.view.WindowInsetsCompat import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels import androidx.recyclerview.widget.RecyclerView @@ -52,6 +55,69 @@ class SearchFragment : Fragment() { recyclerView.adapter = ImageAdapter(requireContext(), mSearchViewModel.searchResults!!) recyclerView.scrollToPosition(0) + // If Edge-to-edge display is enabled, + // tweak the top margin so that content will not overlap with status bar + ViewCompat.setOnApplyWindowInsetsListener(view) { v, windowInsets -> + // Handle window insets here + val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) + + // Update the layout parameters of the view's parent + (v.layoutParams as? ViewGroup.MarginLayoutParams)?.apply { + topMargin = insets.top + } + + // Use WindowInsets to check the software keyboard visibility. + // val imeVisible = windowInsets.isVisible(WindowInsetsCompat.Type.ime()) + // val imeHeight = windowInsets.getInsets(WindowInsetsCompat.Type.ime()).bottom + + // Return CONSUMED if you don't want want the window insets to keep passing + // down to descendant views. + WindowInsetsCompat.CONSUMED + } + + // New keyboard animation using WindowInsets + ViewCompat.setWindowInsetsAnimationCallback( + view, + object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { + + var startBottom = 0f + override fun onPrepare( + animation: WindowInsetsAnimationCompat + ) { + startBottom = view.bottom.toFloat() + } + + var endBottom = 0f + override fun onStart( + animation: WindowInsetsAnimationCompat, + bounds: WindowInsetsAnimationCompat.BoundsCompat + ): WindowInsetsAnimationCompat.BoundsCompat { + // Record the position of the view after the IME transition. + endBottom = view.bottom.toFloat() + + return bounds + } + + override fun onProgress( + insets: WindowInsetsCompat, + runningAnimations: MutableList + ): WindowInsetsCompat { + // Find an IME animation. + val imeAnimation = runningAnimations.find { + it.typeMask and WindowInsetsCompat.Type.ime() != 0 + } ?: return insets + + // Offset the view based on the interpolated fraction of the IME animation. + view.translationY = + (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction) + + return insets + } + + } + ) + + mORTTextViewModel.init() searchText = view?.findViewById(R.id.searchText) diff --git a/app/src/main/res/layout/fragment_index.xml b/app/src/main/res/layout/fragment_index.xml index ec27ded..1d86cbd 100755 --- a/app/src/main/res/layout/fragment_index.xml +++ b/app/src/main/res/layout/fragment_index.xml @@ -13,7 +13,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:ems="10" - android:text="Updating image index" + android:text="@string/progress_bar_text" android:gravity="center"/> - + android:gravity="center" + android:layout_marginTop="12dp" + android:layout_marginHorizontal="12dp"> - + android:hint="@string/search_text" + android:inputType="textWebEditText|text" + /> - + android:gravity="center" + android:layout_marginTop="6dp"> -