Improve search ui

This commit is contained in:
Koitharu
2021-07-21 12:43:20 +03:00
parent 52e136ddef
commit 625b2769c6
5 changed files with 90 additions and 93 deletions

View File

@@ -60,7 +60,7 @@ abstract class BaseActivity<B : ViewBinding> : AppCompatActivity(), OnApplyWindo
toolbar?.let(this::setSupportActionBar)
ViewCompat.setOnApplyWindowInsetsListener(binding.root, this)
val toolbarParams = (toolbar ?: binding.root.findViewById<View>(R.id.toolbar_card))
val toolbarParams = (binding.root.findViewById<View>(R.id.toolbar_card) ?: toolbar)
?.layoutParams as? AppBarLayout.LayoutParams
if (toolbarParams != null) {
if (get<AppSettings>().isToolbarHideWhenScrolling) {

View File

@@ -6,11 +6,18 @@ import android.content.res.Configuration
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.view.*
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AlertDialog
import androidx.core.content.ContextCompat
import androidx.core.graphics.Insets
import androidx.core.view.*
import androidx.core.view.GravityCompat
import androidx.core.view.isVisible
import androidx.core.view.updateLayoutParams
import androidx.core.view.updatePadding
import androidx.drawerlayout.widget.DrawerLayout
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentTransaction
import androidx.fragment.app.commit
@@ -38,18 +45,19 @@ import org.koitharu.kotatsu.search.ui.global.GlobalSearchActivity
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionFragment
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionViewModel
import org.koitharu.kotatsu.search.ui.suggestion.SearchUI
import org.koitharu.kotatsu.settings.AppUpdateChecker
import org.koitharu.kotatsu.settings.SettingsActivity
import org.koitharu.kotatsu.settings.onboard.OnboardDialogFragment
import org.koitharu.kotatsu.tracker.ui.FeedFragment
import org.koitharu.kotatsu.tracker.work.TrackWorker
import org.koitharu.kotatsu.utils.ext.*
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
import org.koitharu.kotatsu.utils.ext.hideKeyboard
import org.koitharu.kotatsu.utils.ext.navigationItemBackground
import org.koitharu.kotatsu.utils.ext.resolveDp
class MainActivity : BaseActivity<ActivityMainBinding>(),
NavigationView.OnNavigationItemSelectedListener,
View.OnClickListener, View.OnFocusChangeListener, SearchSuggestionListener,
MenuItem.OnActionExpandListener {
View.OnClickListener, View.OnFocusChangeListener, SearchSuggestionListener {
private val viewModel by viewModel<MainViewModel>(mode = LazyThreadSafetyMode.NONE)
private val searchSuggestionViewModel by viewModel<SearchSuggestionViewModel>(
@@ -58,11 +66,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
private lateinit var navHeaderBinding: NavigationHeaderBinding
private lateinit var drawerToggle: ActionBarDrawerToggle
private var searchUi: SearchUI? = null
private var searchViewElevation = 0f
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(ActivityMainBinding.inflate(layoutInflater))
searchViewElevation = binding.toolbarCard.cardElevation
navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater)
drawerToggle = ActionBarDrawerToggle(
this,
@@ -71,12 +80,17 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
R.string.open_menu,
R.string.close_menu
)
drawerToggle.setHomeAsUpIndicator(ContextCompat.getDrawable(this, R.drawable.ic_arrow_back))
drawerToggle.setToolbarNavigationClickListener {
binding.searchView.hideKeyboard()
onBackPressed()
}
binding.drawer.addDrawerListener(drawerToggle)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
binding.searchView.apply {
setOnQueryTextFocusChangeListener(this@MainActivity)
searchUi = SearchUI.from(this, this@MainActivity)
onFocusChangeListener = this@MainActivity
searchSuggestionListener = this@MainActivity
}
binding.navigationView.apply {
@@ -114,6 +128,12 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
viewModel.remoteSources.observe(this, this::updateSideMenu)
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
super.onRestoreInstanceState(savedInstanceState)
drawerToggle.isDrawerIndicatorEnabled =
binding.drawer.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED
}
override fun onPostCreate(savedInstanceState: Bundle?) {
super.onPostCreate(savedInstanceState)
drawerToggle.syncState()
@@ -126,13 +146,14 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
override fun onBackPressed() {
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
binding.searchView.setQuery(resources.getString(R.string._empty), false)
binding.searchView.clearFocus()
when {
binding.drawer.isDrawerOpen(binding.navigationView) -> binding.drawer.closeDrawer(
binding.navigationView)
fragment != null -> supportFragmentManager.commit {
remove(fragment)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
runOnCommit { onSearchClosed() }
}
else -> super.onBackPressed()
}
@@ -205,6 +226,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
supportFragmentManager.commit {
add(R.id.container, SearchSuggestionFragment.newInstance(), TAG_SEARCH)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
runOnCommit { onSearchOpened() }
}
}
}
@@ -215,6 +237,7 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}
override fun onQueryClick(query: String, submit: Boolean) {
binding.searchView.query = query
if (submit) {
if (query.isNotEmpty()) {
val source = searchSuggestionViewModel.getLocalSearchSource()
@@ -225,8 +248,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}
searchSuggestionViewModel.saveQuery(query)
}
} else {
searchUi?.query = query
}
}
@@ -244,28 +265,6 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
}.show()
}
override fun onMenuItemActionExpand(item: MenuItem?): Boolean {
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
if (fragment == null) {
supportFragmentManager.commit {
add(R.id.container, SearchSuggestionFragment.newInstance(), TAG_SEARCH)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
}
}
return true
}
override fun onMenuItemActionCollapse(item: MenuItem?): Boolean {
val fragment = supportFragmentManager.findFragmentByTag(TAG_SEARCH)
if (fragment != null) {
supportFragmentManager.commit {
remove(fragment)
setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE)
}
}
return true
}
private fun onOpenReader(manga: Manga) {
val options = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
ActivityOptions.makeClipRevealAnimation(
@@ -334,6 +333,20 @@ class MainActivity : BaseActivity<ActivityMainBinding>(),
binding.fab.isVisible = fragment is HistoryListFragment
}
private fun onSearchOpened() {
binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
drawerToggle.isDrawerIndicatorEnabled = false
binding.toolbarCard.cardElevation = 0f
binding.appbar.elevation = searchViewElevation
}
private fun onSearchClosed() {
binding.drawer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
drawerToggle.isDrawerIndicatorEnabled = true
binding.appbar.elevation = 0f
binding.toolbarCard.cardElevation = searchViewElevation
}
private companion object {
const val TAG_PRIMARY = "primary"

View File

@@ -1,49 +0,0 @@
package org.koitharu.kotatsu.search.ui.suggestion
import android.view.MenuItem
import androidx.appcompat.widget.SearchView
import org.koitharu.kotatsu.R
class SearchUI(
private val searchView: SearchView,
listener: SearchSuggestionListener,
hint: String? = null,
) {
init {
val context = searchView.context
searchView.queryHint = hint ?: context.getString(R.string.search_manga)
searchView.setOnQueryTextListener(QueryListener(listener))
}
var query: String
get() = searchView.query.toString()
set(value) {
searchView.setQuery(value, false)
}
private class QueryListener(
private val listener: SearchSuggestionListener,
) : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean {
return if (!query.isNullOrBlank()) {
listener.onQueryClick(query.trim(), submit = true)
true
} else false
}
override fun onQueryTextChange(newText: String?): Boolean {
listener.onQueryChanged(newText?.trim().orEmpty())
return true
}
}
companion object {
fun from(
searchView: SearchView,
listener: SearchSuggestionListener,
): SearchUI = SearchUI(searchView, listener)
}
}

View File

@@ -3,9 +3,11 @@ package org.koitharu.kotatsu.search.ui.widget
import android.content.Context
import android.util.AttributeSet
import android.view.KeyEvent
import android.view.inputmethod.EditorInfo
import androidx.annotation.AttrRes
import androidx.appcompat.widget.AppCompatEditText
import com.google.android.material.R
import org.koitharu.kotatsu.search.ui.suggestion.SearchSuggestionListener
class SearchEditText @JvmOverloads constructor(
context: Context,
@@ -13,16 +15,44 @@ class SearchEditText @JvmOverloads constructor(
@AttrRes defStyleAttr: Int = R.attr.editTextStyle,
) : AppCompatEditText(context, attrs, defStyleAttr) {
var searchSuggestionListener: SearchSuggestionListener? = null
var query: String
get() = text?.trim()?.toString().orEmpty()
set(value) {
if (value != text?.toString()) {
setText(value)
setSelection(value.length)
}
}
override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
if (hasFocus()) {
clearFocus()
return true
// return true
}
}
return super.onKeyPreIme(keyCode, event)
}
override fun onEditorAction(actionCode: Int) {
super.onEditorAction(actionCode)
if (actionCode == EditorInfo.IME_ACTION_SEARCH) {
searchSuggestionListener?.onQueryClick(query, submit = true)
}
}
override fun onTextChanged(
text: CharSequence?,
start: Int,
lengthBefore: Int,
lengthAfter: Int,
) {
super.onTextChanged(text, start, lengthBefore, lengthAfter)
searchSuggestionListener?.onQueryChanged(query)
}
override fun clearFocus() {
super.clearFocus()
text?.clear()

View File

@@ -17,6 +17,7 @@
style="@style/Widget.Kotatsu.AppBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stateListAnimator="@null"
app:elevation="0dp">
<com.google.android.material.card.MaterialCardView
@@ -35,21 +36,23 @@
style="@style/Widget.Kotatsu.Toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
app:contentInsetStartWithNavigation="0dp"
app:layout_scrollFlags="scroll|enterAlways"
app:titleTextAppearance="@style/TextAppearance.Kotatsu.PersistentToolbarTitle"
app:titleTextColor="?android:colorControlNormal"
android:focusableInTouchMode="true"
android:focusable="true"
tools:title="@string/app_name">
<androidx.appcompat.widget.SearchView
<org.koitharu.kotatsu.search.ui.widget.SearchEditText
android:id="@+id/searchView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:iconifiedByDefault="false"
app:queryHint="@string/search_manga"
android:paddingStart="-12dp"/>
android:layout_height="match_parent"
android:background="@null"
android:gravity="center_vertical"
android:hint="@string/search_manga"
android:imeOptions="actionSearch"
android:importantForAutofill="no"
android:singleLine="true" />
</com.google.android.material.appbar.MaterialToolbar>