Improve search ui
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user