pull/37/head
kunfei 5 years ago
parent b9953c2e87
commit f3882b3c5f
  1. 72
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesActivity.kt
  2. 4
      app/src/main/java/io/legado/app/ui/rss/article/RssArticlesViewModel.kt
  3. 77
      app/src/main/java/io/legado/app/ui/widget/recycler/RefreshRecyclerView.kt
  4. 12
      app/src/main/res/layout/activity_rss_artivles.xml
  5. 5
      app/src/main/res/layout/view_load_more.xml
  6. 16
      app/src/main/res/layout/view_refresh_recycler.xml

@ -1,9 +1,10 @@
package io.legado.app.ui.rss.article package io.legado.app.ui.rss.article
import android.annotation.SuppressLint
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.view.LayoutInflater
import android.view.* import android.view.Menu
import android.view.MenuItem
import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.Observer import androidx.lifecycle.Observer
@ -19,6 +20,8 @@ import io.legado.app.ui.rss.read.ReadRssActivity
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
import io.legado.app.utils.getViewModel import io.legado.app.utils.getViewModel
import kotlinx.android.synthetic.main.activity_rss_artivles.* import kotlinx.android.synthetic.main.activity_rss_artivles.*
import kotlinx.android.synthetic.main.view_load_more.view.*
import kotlinx.android.synthetic.main.view_refresh_recycler.*
import org.jetbrains.anko.startActivity import org.jetbrains.anko.startActivity
import org.jetbrains.anko.startActivityForResult import org.jetbrains.anko.startActivityForResult
@ -32,9 +35,7 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
private var adapter: RssArticlesAdapter? = null private var adapter: RssArticlesAdapter? = null
private var rssArticlesData: LiveData<List<RssArticle>>? = null private var rssArticlesData: LiveData<List<RssArticle>>? = null
private var url: String? = null private var url: String? = null
private lateinit var loadMoreView: View
private var durTouchX = -1000000f
private var durTouchY = -1000000f
override fun onActivityCreated(savedInstanceState: Bundle?) { override fun onActivityCreated(savedInstanceState: Bundle?) {
initView() initView()
@ -44,10 +45,8 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
url = intent.getStringExtra("url") url = intent.getStringExtra("url")
url?.let { url?.let {
initData(it) initData(it)
viewModel.loadContent(it) {
refresh_progress_bar.isAutoLoading = false
}
} }
refresh_recycler_view.startLoading()
} }
override fun onCompatCreateOptionsMenu(menu: Menu): Boolean { override fun onCompatCreateOptionsMenu(menu: Menu): Boolean {
@ -72,7 +71,6 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
return super.onCompatOptionsItemSelected(item) return super.onCompatOptionsItemSelected(item)
} }
@SuppressLint("InflateParams")
private fun initView() { private fun initView() {
ATH.applyEdgeEffectColor(recycler_view) ATH.applyEdgeEffectColor(recycler_view)
recycler_view.layoutManager = LinearLayoutManager(this) recycler_view.layoutManager = LinearLayoutManager(this)
@ -84,59 +82,17 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
}) })
adapter = RssArticlesAdapter(this, this) adapter = RssArticlesAdapter(this, this)
recycler_view.adapter = adapter recycler_view.adapter = adapter
val loadMoreView = LayoutInflater.from(this).inflate(R.layout.view_load_more, null) loadMoreView =
LayoutInflater.from(this).inflate(R.layout.view_load_more, recycler_view, false)
adapter?.addFooterView(loadMoreView) adapter?.addFooterView(loadMoreView)
refresh_progress_bar.isAutoLoading = true refresh_progress_bar.isAutoLoading = true
recycler_view.setOnTouchListener(object : View.OnTouchListener { refresh_recycler_view.onRefreshStart = {
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
durTouchX = event.x
durTouchY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (durTouchX == -1000000f) {
durTouchX = event.x
}
if (durTouchY == -1000000f)
durTouchY = event.y
val dY = event.y - durTouchY //>0下拉
durTouchY = event.y
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.getSecondDurProgress() == refresh_progress_bar.secondFinalProgress) {
recycler_view.adapter?.let {
if (it.itemCount > 0) {
if (0 == (recycler_view.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()) {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt())
}
} else {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt())
}
}
return refresh_progress_bar.getSecondDurProgress() > 0
}
}
MotionEvent.ACTION_UP -> {
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.secondMaxProgress > 0 && refresh_progress_bar.getSecondDurProgress() > 0) {
if (refresh_progress_bar.getSecondDurProgress() >= refresh_progress_bar.secondMaxProgress) {
refresh_progress_bar.isAutoLoading = true
url?.let { url?.let {
viewModel.loadContent(it) { viewModel.loadContent(it) {
refresh_progress_bar.isAutoLoading = false refresh_progress_bar.isAutoLoading = false
} }
} }
} else {
refresh_progress_bar.setSecondDurProgressWithAnim(0)
}
}
durTouchX = -1000000f
durTouchY = -1000000f
}
} }
return false
}
})
recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() { recycler_view.addOnScrollListener(object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
@ -156,7 +112,11 @@ class RssArticlesActivity : VMBaseActivity<RssArticlesViewModel>(R.layout.activi
} }
private fun scrollToBottom() { private fun scrollToBottom() {
Log.d("xxxxxx", "scrollToBottom") adapter?.let {
if (it.getActualItemCount() > 0) {
loadMoreView.rotate_loading.show()
}
}
} }
override fun readRss(rssArticle: RssArticle) { override fun readRss(rssArticle: RssArticle) {

@ -50,4 +50,8 @@ class RssArticlesViewModel(application: Application) : BaseViewModel(application
loadContent(url, onFinally) loadContent(url, onFinally)
} }
} }
fun loadMore() {
}
} }

@ -0,0 +1,77 @@
package io.legado.app.ui.widget.recycler
import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import androidx.recyclerview.widget.LinearLayoutManager
import io.legado.app.R
import kotlinx.android.synthetic.main.view_refresh_recycler.view.*
class RefreshRecyclerView(context: Context?, attrs: AttributeSet?) : LinearLayout(context, attrs) {
private var durTouchX = -1000000f
private var durTouchY = -1000000f
var onRefreshStart: (() -> Unit)? = null
init {
LayoutInflater.from(context).inflate(R.layout.view_refresh_recycler, this, true)
recycler_view.setOnTouchListener(object : View.OnTouchListener {
@SuppressLint("ClickableViewAccessibility")
override fun onTouch(v: View?, event: MotionEvent?): Boolean {
when (event?.action) {
MotionEvent.ACTION_DOWN -> {
durTouchX = event.x
durTouchY = event.y
}
MotionEvent.ACTION_MOVE -> {
if (durTouchX == -1000000f) {
durTouchX = event.x
}
if (durTouchY == -1000000f)
durTouchY = event.y
val dY = event.y - durTouchY //>0下拉
durTouchY = event.y
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.getSecondDurProgress() == refresh_progress_bar.secondFinalProgress) {
recycler_view.adapter?.let {
if (it.itemCount > 0) {
if (0 == (recycler_view.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()) {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt())
}
} else {
refresh_progress_bar.setSecondDurProgress((refresh_progress_bar.getSecondDurProgress() + dY / 2).toInt())
}
}
return refresh_progress_bar.getSecondDurProgress() > 0
}
}
MotionEvent.ACTION_UP -> {
if (!refresh_progress_bar.isAutoLoading && refresh_progress_bar.secondMaxProgress > 0 && refresh_progress_bar.getSecondDurProgress() > 0) {
if (refresh_progress_bar.getSecondDurProgress() >= refresh_progress_bar.secondMaxProgress) {
refresh_progress_bar.isAutoLoading = true
onRefreshStart?.invoke()
} else {
refresh_progress_bar.setSecondDurProgressWithAnim(0)
}
}
durTouchX = -1000000f
durTouchY = -1000000f
}
}
return false
}
})
}
fun startLoading() {
refresh_progress_bar.isAutoLoading = true
onRefreshStart?.invoke()
}
}

@ -11,21 +11,15 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<io.legado.app.ui.widget.anima.RefreshProgressBar
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout <io.legado.app.ui.widget.dynamiclayout.DynamicFrameLayout
android:id="@+id/content_view" android:id="@+id/content_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/refresh_progress_bar"> app:layout_constraintTop_toBottomOf="@id/title_bar">
<androidx.recyclerview.widget.RecyclerView <io.legado.app.ui.widget.recycler.RefreshRecyclerView
android:id="@+id/recycler_view" android:id="@+id/refresh_recycler_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" /> android:layout_height="match_parent" />

@ -2,7 +2,6 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_gravity="center"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content"> android:layout_height="wrap_content">
@ -11,16 +10,16 @@
android:layout_width="36dp" android:layout_width="36dp"
android:layout_height="36dp" android:layout_height="36dp"
android:layout_margin="6dp" android:layout_margin="6dp"
android:visibility="gone" android:layout_gravity="center"
app:loading_width="2dp" /> app:loading_width="2dp" />
<TextView <TextView
android:id="@+id/tv_text" android:id="@+id/tv_text"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="?android:attr/textColorSecondary" android:textColor="?android:attr/textColorSecondary"
android:textSize="14sp" android:textSize="14sp"
android:gravity="center"
android:background="?attr/selectableItemBackground" android:background="?attr/selectableItemBackground"
android:visibility="invisible" android:visibility="invisible"
tools:text="加载状态" tools:text="加载状态"

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<io.legado.app.ui.widget.anima.RefreshProgressBar
android:id="@+id/refresh_progress_bar"
android:layout_width="match_parent"
android:layout_height="2dp"
app:layout_constraintTop_toBottomOf="@id/title_bar" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</merge>
Loading…
Cancel
Save