feat: Use material search view & recyclerview adapter handler is activity

This commit is contained in:
AnranYus
2023-11-04 17:19:07 +08:00
parent b386e87bc8
commit e3336b0458
6 changed files with 80 additions and 216 deletions
+3 -3
View File
@@ -4,12 +4,12 @@ plugins {
}
android {
compileSdkVersion = 33
compileSdkVersion = 34
defaultConfig {
applicationId "com.lsp.view"
minSdkVersion 29
targetSdkVersion 33
targetSdkVersion 34
versionCode 221022
versionName "1.2.7"
@@ -33,7 +33,7 @@ android {
}
dependencies {
implementation("com.google.android.material:material:1.5.0")
implementation("com.google.android.material:material:1.10.0")
implementation 'jp.wasabeef:recyclerview-animators:4.0.2'
implementation "androidx.drawerlayout:drawerlayout:1.1.1"
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
@@ -1,34 +1,20 @@
package com.lsp.view.activity.main
import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.content.Intent
import android.os.*
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.view.inputmethod.EditorInfo
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import androidx.core.view.GravityCompat
import androidx.core.view.WindowCompat
import androidx.core.view.WindowInsetsCompat.Type.ime
import androidx.drawerlayout.widget.DrawerLayout
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.StaggeredGridLayoutManager
import com.google.android.material.navigation.NavigationView
import com.google.android.material.search.SearchBar
import com.google.android.material.search.SearchView
import com.google.android.material.snackbar.Snackbar
import com.lsp.view.YandViewApplication
import com.lsp.view.R
import com.lsp.view.activity.favtag.FavTagActivity
import com.lsp.view.activity.setting.SettingsActivity
import com.lsp.view.YandViewApplication
import com.lsp.view.model.MainViewModel
class MainActivity : AppCompatActivity() {
private lateinit var search: EditText
private var shortAnnotationDuration: Int = 0
private var username: String? = ""
val TAG = javaClass.simpleName
@@ -38,11 +24,13 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
viewModel = MainViewModel.provideFactory((application as YandViewApplication).repository, this,this).create(MainViewModel::class.java)
val adapter by lazy {
viewModel.fetchPostByRefresh()
PostAdapter(this)
}
//刷新
val refresh =
findViewById<androidx.swiperefreshlayout.widget.SwipeRefreshLayout>(R.id.swipeRefreshLayout)
@@ -53,14 +41,26 @@ class MainActivity : AppCompatActivity() {
viewModel.errorMessage.observe(this){
Snackbar.make(refresh,it,Snackbar.LENGTH_SHORT).show()
}
viewModel.postList.observe(this){
search = findViewById(R.id.search)
shortAnnotationDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
search.setOnEditorActionListener { content, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
viewModel.fetchPostBySearch(content.text.toString())
if (adapter.isAppendData){
adapter.appendDate(it)
}else{
adapter.pushNewData(it)
}
}
shortAnnotationDuration = resources.getInteger(android.R.integer.config_shortAnimTime)
val searchBar = findViewById<SearchBar>(R.id.search_bar)
val searchView = findViewById<SearchView>(R.id.search_view)
searchView.editText.setOnEditorActionListener { v, actionId, event ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
viewModel.fetchPostBySearch(searchView.text.toString())
searchBar.setText(searchView.text)
searchView.hide()
}
return@setOnEditorActionListener false
}
@@ -70,31 +70,28 @@ class MainActivity : AppCompatActivity() {
viewModel.uiState.value.nowSearchText.value = stringExtra
}
viewModel.uiState.value.nowSearchText.observe(this){
search.setText(it)
searchView.setText(it)
searchBar.setText(it)
}
// val appbar = findViewById<AppBarLayout>(R.id.appbar)
// val nowHeight = appbar.layoutParams.height
// appbar.layoutParams.height = (application as YandViewApplication).statusBarHeight()+nowHeight
refresh.setOnRefreshListener {
viewModel.fetchPostByRefresh()
}
viewModel.adapter.apply {
adapter.apply {
setLoadMoreListener(object :PostAdapter.OnScrollToBottom{
override fun event(position: Int) {
adapter.isAppendData = true//设置数据状态为追加数据
viewModel.fetchMore()
}
})
}
findViewById<RecyclerView>(R.id.recyclerview).apply {
val layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
this.layoutManager = layoutManager
this.adapter = viewModel.adapter
this.adapter = adapter
}
@@ -108,39 +105,6 @@ class MainActivity : AppCompatActivity() {
val sp = getSharedPreferences("username", 0)
username = sp.getString("username", null)
val nav = findViewById<NavigationView>(R.id.nav)
//加载导航栏列表
nav.setCheckedItem(R.id.photo)
//设置侧边栏点击逻辑
nav.setNavigationItemSelectedListener {
val drawerLayout = findViewById<DrawerLayout>(R.id.drawerLayout)
when (it.itemId) {
//画廊
R.id.photo -> {
viewModel.fetchPostByRefresh()
drawerLayout.closeDrawers()
true
}
//设置
R.id.setting -> {
val intent = Intent(this, SettingsActivity::class.java)
startActivity(intent)
drawerLayout.closeDrawers()
false
}
R.id.taglist -> {
val intent = Intent(this, FavTagActivity::class.java)
startActivity(intent)
drawerLayout.closeDrawers()
false
}
else -> false
}
}
}
override fun onResume() {
@@ -163,74 +127,4 @@ class MainActivity : AppCompatActivity() {
}
//隐藏搜索栏
private fun hiddenSearchBar() {
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_baseline_menu_24)
search.animate()
.alpha(0f)
.setDuration(shortAnnotationDuration.toLong())
.setListener(object : AnimatorListenerAdapter() {
override fun onAnimationEnd(animation: Animator) {
search.visibility = View.GONE
}
})
hideIm()
viewModel.uiState.value.switchShowSearchBar()
}
//现实搜索栏
private fun showSearchBar() {
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_baseline_arrow_back_24)
search.apply {
alpha = 0f
visibility = View.VISIBLE
animate()
.alpha(1f)
.setDuration(shortAnnotationDuration.toLong())
.setListener(null)
}
viewModel.uiState.value.switchShowSearchBar()
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
if (viewModel.uiState.value.showSearchBar){
hiddenSearchBar()
}else {
val drawerLayout = findViewById<DrawerLayout>(R.id.drawerLayout)
drawerLayout.openDrawer(GravityCompat.START)
}
}
R.id.search_nav -> {
if (viewModel.uiState.value.showSearchBar) {
viewModel.fetchPostByRefresh()
hideIm()
}
if (search.visibility == View.GONE) {
showSearchBar()
}
}
}
return true
}
private fun hideIm() {
WindowCompat.getInsetsController(this.window,window.decorView).hide(ime())
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.toolbar_menu, menu)
return true
}
}
@@ -14,13 +14,11 @@ import com.lsp.view.activity.pic.PicActivity
import com.lsp.view.repository.bean.YandPost
class PostAdapter(val context: Context):
class PostAdapter(val context: Context,private val postList: ArrayList<YandPost> = ArrayList()):
RecyclerView.Adapter<PostAdapter.ViewHolder>() {
val TAG = this::class.java.simpleName
private val UA = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"
private var postList = ArrayList<YandPost>()
var isAppendData = false//数据追加标志
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
val picImage: ImageView = view.findViewById(R.id.picImgae)
@@ -39,6 +37,7 @@ class PostAdapter(val context: Context):
val pos = postList.size
postList.addAll(list)
notifyItemRangeInserted(pos-1, list.size)
isAppendData = false
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
@@ -11,6 +11,8 @@ import androidx.lifecycle.viewModelScope
import com.lsp.view.activity.main.PostAdapter
import com.lsp.view.repository.PostRepository
import androidx.savedstate.SavedStateRegistryOwner
import com.lsp.view.repository.bean.Post
import com.lsp.view.repository.bean.YandPost
import com.lsp.view.repository.exception.NetworkErrorException
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
@@ -25,12 +27,14 @@ class MainViewModel(private val repository: PostRepository,context: Context):Vie
val uiState:StateFlow<UiState>
get() = _uiState.asStateFlow()
private var fetchJob: Job? = null
val adapter = PostAdapter(context)
private val TAG = this::class.java.simpleName
private val _errorMessage = MutableLiveData<String>()
val errorMessage
get() = _errorMessage as LiveData<String>
private val _postList = MutableLiveData<ArrayList<YandPost>>()
val postList get() = _postList as LiveData<ArrayList<YandPost>>
companion object {
fun provideFactory(
@@ -77,19 +81,11 @@ class MainViewModel(private val repository: PostRepository,context: Context):Vie
fetchJob = viewModelScope.launch(Dispatchers.IO) {
_uiState.value.isRefreshing.postValue(true)
try {
val postList = repository.fetchPostData(
_postList.postValue(repository.fetchPostData(
_uiState.value.nowSearchText.value,
_uiState.value.isSafe,
_uiState.value.nowPage
)
launch(Dispatchers.Main) {
if (append){
adapter.appendDate(postList)
}else{
adapter.pushNewData(postList)
}
}
))
}catch (e:NetworkErrorException){
_errorMessage.postValue(e.message.toString())
@@ -7,7 +7,7 @@ class PostRepository {
private val dataSource = PostDataSource()
//获取post
suspend fun fetchPostData(searchTarget :String?,safe:Boolean,page:Int): List<YandPost> {
suspend fun fetchPostData(searchTarget :String?,safe:Boolean,page:Int): ArrayList<YandPost> {
var target = searchTarget
var isNum = true
@@ -26,7 +26,7 @@ class PostRepository {
val dataList = dataSource.fetchNewPost(load)
return if (safe){
dataList.filter { it.rating == "s" }
ArrayList(dataList.filter { it.rating == "s" })
}else{
dataList
}
+32 -57
View File
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/drawerLayout"
<androidx.coordinatorlayout.widget.CoordinatorLayout
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"
@@ -8,63 +7,39 @@
android:layout_height="match_parent"
tools:context=".activity.main.MainActivity">
<RelativeLayout
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activity.main.MainActivity">
<androidx.coordinatorlayout.widget.CoordinatorLayout
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/swipeRefreshLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/recyclerview"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
android:layout_height="wrap_content">
<com.google.android.material.search.SearchBar
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:menu="@menu/toolbar_menu"
android:id="@+id/toolbar"
app:layout_scrollFlags="scroll|enterAlways|snap"
>
<EditText
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="20sp"
android:id="@+id/search"
android:imeOptions="actionSearch"
android:singleLine="true"
android:visibility="gone" />
</androidx.appcompat.widget.Toolbar>
<com.google.android.material.search.SearchView
android:id="@+id/search_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_anchor="@id/search_bar">
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/search_tip"
android:visibility="gone"/>
</com.google.android.material.search.SearchView>
</com.google.android.material.appbar.AppBarLayout>
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/swipeRefreshLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<androidx.recyclerview.widget.RecyclerView
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/recyclerview"/>
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</RelativeLayout>
<com.google.android.material.navigation.NavigationView
android:layout_width="240dp"
android:layout_height="match_parent"
android:id="@+id/nav"
android:layout_gravity="start"
app:menu="@menu/nav_menu"
app:headerLayout="@layout/nav_header"
/>
</androidx.drawerlayout.widget.DrawerLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>