Skip to content

Commit

Permalink
修复横竖屏切换崩溃问题
Browse files Browse the repository at this point in the history
增加支持Nested联动的NestVerticalPagerLayout,不用编写边界分析器
联动效果略有不同
  • Loading branch information
ooftf committed Jun 17, 2019
1 parent 5f46ccd commit 41f9e64
Show file tree
Hide file tree
Showing 4 changed files with 201 additions and 58 deletions.
2 changes: 1 addition & 1 deletion app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
android:layout_height="match_parent"
tools:context="com.ooftf.verticalpager.MainActivity">

<com.ooftf.vertical.nested.VerticalPagerLayout
<com.ooftf.vertical.nested.NestVerticalPagerLayout
android:id="@+id/verticalViewPager"
android:layout_width="match_parent"
android:layout_height="match_parent"
Expand Down
37 changes: 21 additions & 16 deletions lib/src/main/java/com/ooftf/vertical/VerticalPagerLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import android.util.Log
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.widget.FrameLayout
import android.widget.Scroller

Expand All @@ -22,7 +21,7 @@ class VerticalPagerLayout : FrameLayout {
/**
* 松开时布局滑动动画时间
*/
private var SCROLL_DURATION = 700
private var SCROLL_DURATION = 600
/**
* 触发拦截的距离
*/
Expand Down Expand Up @@ -125,18 +124,21 @@ class VerticalPagerLayout : FrameLayout {
private fun refreshViews() {
//移除不必要View
adapter ?: return
adapter?.startUpdate(this)
items
.filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit }
.forEach {
removeForItemInfo(it)
}
(getCurrentPage() - offscreenPageLimit..getCurrentPage() + offscreenPageLimit).forEach {
addNewView(it)
adapter?.let {
it.startUpdate(this)
items
.filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit }
.forEach {
removeForItemInfo(it)
}
var start = Math.max(0, getCurrentPage() - offscreenPageLimit)
var end = Math.min(it.count - 1, getCurrentPage() + offscreenPageLimit)
(start..end).forEach {
addNewView(it)
}
it.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj)
it.finishUpdate(this)
}
adapter?.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj)
adapter?.finishUpdate(this)

}

/**
Expand Down Expand Up @@ -279,17 +281,20 @@ class VerticalPagerLayout : FrameLayout {
val height = b - t
(0 until childCount).forEach {
var itemInfo = itemInfoForView(getChildAt(it))
getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height)
itemInfo?.let { itemInfo ->
getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height)
}

}
}

private fun itemInfoForView(child: View): ItemInfo {
private fun itemInfoForView(child: View): ItemInfo? {
items.forEach {
if (adapter!!.isViewFromObject(child, it.obj)) {
return it
}
}
throw NullPointerException()
return null
}

override fun computeScroll() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import android.content.Context
import android.os.Build
import android.support.annotation.RequiresApi
import android.support.v4.view.NestedScrollingParent2
import android.support.v4.view.NestedScrollingParentHelper
import android.support.v4.view.PagerAdapter
import android.util.AttributeSet
import android.util.Log
Expand All @@ -18,27 +17,56 @@ import android.widget.Scroller
* 高仿淘宝商品页上下分页布局
* Created by master on 2016/3/28.
*/
class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
var helper = NestedScrollingParentHelper(this)
class NestVerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
var helper = NestedScrollingParentHelperPro(this)
override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray?, type: Int) {
moved = true
Log.e("onNestedPreScroll", "dy::" + dy)
if (scrollY % height != 0) {
scrollBy(0, dy)
consumed?.set(1, dy)
helper.onNestedPreScroll(target, dx, dy, consumed, type)
if (isIntecepted && type == 0) {
var consumedY: Int
val expect = scrollY + dy
when {
expect <= 0 -> {
consumedY = 0 - scrollY;
scrollBy(0, consumedY)
}
expect >= height * (adapter!!.count - 1) -> {
consumedY = height * (adapter!!.count - 1) - scrollY
scrollBy(0, consumedY)
}
else -> {
consumedY = dy
scrollBy(0, consumedY)
}
}
consumed?.set(1, consumedY)
}
Log.e("onNestedPreScroll", "dy:$dy,type::$type")
}

override fun onStopNestedScroll(target: View, type: Int) {
helper.onStopNestedScroll(target, type)
Log.e("onStopNestedScroll", "onStopNestedScroll")
judgePage(true)
Log.e("onStopNestedScroll", "type:$type,speedY::${helper.speedY}")
if (isIntecepted && type == 0) {
if (helper.speedY > 3) {
setCurrentItem(getCurrentPage() + 1)
} else if (helper.speedY < -3) {
setCurrentItem(getCurrentPage() - 1)
} else {
setCurrentItem(getCurrentPage())
}
isIntecepted = false
}
}

override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean {
mScroller.forceFinished(true)
Log.e("onStartNestedScroll", "onStartNestedScroll")
moved = false
Log.e("onStartNestedScroll", "type::$type")
if (type == 0) {
mScroller.forceFinished(true)
if (scrollY % height != 0) {
isIntecepted = true
}
}

return true
}

Expand All @@ -47,17 +75,36 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
helper.onNestedScrollAccepted(child, target, axes, type)
}

var moved = false
var isIntecepted = false
override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int) {
Log.e("onNestedScroll", "dyConsumed::" + dyConsumed + ",dyUnconsumed::" + dyUnconsumed)
scrollBy(0, dyUnconsumed)
helper.onNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type)
Log.e("onNestedScroll", "dyConsumed::$dyConsumed,dyUnconsumed::$dyUnconsumed")
if (type == 0 && dyUnconsumed != 0) {
var consumedY: Int
val expect = scrollY + dyUnconsumed
when {
expect <= 0 -> {
consumedY = 0 - scrollY;
scrollBy(0, consumedY)
}
expect >= height * (adapter!!.count - 1) -> {
consumedY = height * (adapter!!.count - 1) - scrollY
scrollBy(0, consumedY)
}
else -> {
consumedY = dyUnconsumed
scrollBy(0, consumedY)
}
}
isIntecepted = true
}
}


/**
* 松开时布局滑动动画时间
*/
private var SCROLL_DURATION = 700
private var SCROLL_DURATION = 600

var offscreenPageLimit = 1;
private var mScroller: Scroller
Expand All @@ -68,9 +115,10 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
resetLayout()
}

override fun onInterceptHoverEvent(event: MotionEvent?): Boolean {
Log.e("onInterceptHoverEvent", "...")
return super.onInterceptHoverEvent(event)

override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
Log.e("onInterceptTouchEvent", "...")
return super.onInterceptTouchEvent(ev)
}

/**
Expand Down Expand Up @@ -104,23 +152,29 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {

override fun scrollTo(x: Int, y: Int) {
refreshViews()
Log.e("scrollTo", "x:$x,y:$y")
super.scrollTo(x, y)
}

private fun refreshViews() {
//移除不必要View
adapter ?: return
adapter?.startUpdate(this)
items
.filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit }
.forEach {
removeForItemInfo(it)
}
(getCurrentPage() - offscreenPageLimit..getCurrentPage() + offscreenPageLimit).forEach {
addNewView(it)
adapter?.let {
it.startUpdate(this)
items
.filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit }
.forEach {
removeForItemInfo(it)
}
var start = Math.max(0, getCurrentPage() - offscreenPageLimit)
var end = Math.min(it.count - 1, getCurrentPage() + offscreenPageLimit)
(start..end).forEach {
addNewView(it)
}
it.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj)
it.finishUpdate(this)
}
adapter?.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj)
adapter?.finishUpdate(this)


}

Expand Down Expand Up @@ -161,6 +215,7 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
return viewForItemInfo(item)
}


private fun viewForItemInfo(itemInfo: ItemInfo): View {
(0 until childCount).forEach {
if (adapter!!.isViewFromObject(getChildAt(it), itemInfo.obj)) {
Expand All @@ -180,13 +235,6 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
}


/**
* 判断应该停留在哪一页
*/
private fun judgePage(smooth: Boolean) {
setCurrentItem(getCurrentPage(), smooth)
}

/**
* 滚动到指定页面
*/
Expand Down Expand Up @@ -220,24 +268,36 @@ class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
*/
private fun getCurrentPage(): Int {
if (height == 0) return 0
return Math.round(scrollY.toFloat() / height)
val round = Math.round(scrollY.toFloat() / height)
if (round < 0) {
return 0
}
adapter?.let {
if (round > it.count - 1) {
return it.count - 1
}
}
return round
}

override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
val height = b - t
(0 until childCount).forEach {
var itemInfo = itemInfoForView(getChildAt(it))
getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height)
itemInfo?.let { itemInfo ->
getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height)
}

}
}

private fun itemInfoForView(child: View): ItemInfo {
private fun itemInfoForView(child: View): ItemInfo? {
items.forEach {
if (adapter!!.isViewFromObject(child, it.obj)) {
return it
}
}
throw NullPointerException()
return null
}

override fun computeScroll() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.ooftf.vertical.nested;

import android.support.annotation.NonNull;
import android.support.v4.view.NestedScrollingParentHelper;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.view.ViewGroup;

/**
* @author ooftf
* @email 994749769@qq.com
* @date 2019/6/17 0017
*/
public class NestedScrollingParentHelperPro extends NestedScrollingParentHelper {
/**
* Construct a new helper for a given ViewGroup
*
* @param viewGroup
*/
public NestedScrollingParentHelperPro(@NonNull ViewGroup viewGroup) {
super(viewGroup);
}

@Override
public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes) {
super.onNestedScrollAccepted(child, target, axes);
speedY = 0;
lastTime = 0;
}

@Override
public void onNestedScrollAccepted(@NonNull View child, @NonNull View target, int axes, int type) {
super.onNestedScrollAccepted(child, target, axes, type);
if(type == 0){
speedY = 0;
lastTime = 0;
}
}

@Override
public int getNestedScrollAxes() {
return super.getNestedScrollAxes();
}

@Override
public void onStopNestedScroll(@NonNull View target) {
super.onStopNestedScroll(target);
}

@Override
public void onStopNestedScroll(@NonNull View target, int type) {
super.onStopNestedScroll(target, type);
}

double speedY;
long lastTime;

public void onNestedScroll(@NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
super.onStopNestedScroll(target, type);

}


public void onNestedPreScroll(@NonNull View target, int dx, int dy, int[] consumed, int type) {
if(type ==0){
long temp = System.currentTimeMillis();
if (lastTime != 0) {
speedY = (double) dy / (temp - lastTime);
}
lastTime = temp;
}

}

public double getSpeedY() {
return speedY;
}
}

0 comments on commit 41f9e64

Please sign in to comment.