Skip to content

Commit 5f46ccd

Browse files
committed
sync
1 parent 4b1cfb1 commit 5f46ccd

File tree

7 files changed

+270
-12
lines changed

7 files changed

+270
-12
lines changed

app/src/main/java/com/ooftf/verticalpager/MainActivity.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,14 @@ class MainActivity : AppCompatActivity() {
1111
super.onCreate(savedInstanceState)
1212
setContentView(R.layout.activity_main)
1313
verticalViewPager.adapter = VerticalPagerAdapter(this, supportFragmentManager)
14-
verticalViewPager.setScrollEdgeAnalyzer { i, view ->
14+
/*verticalViewPager.setScrollEdgeAnalyzer { i, view ->
1515
when (i) {
1616
0 -> ScrollEdgeEngine(view.findViewById(R.id.scrollView))
1717
1 -> ScrollEdgeEngine(view.findViewById(R.id.recyclerView))
1818
2 -> ScrollEdgeEngine(view)
1919
else -> ScrollEdgeEngine(view)
2020
}
21-
}
22-
verticalViewPager.setCurrentItem(3)
21+
}*/
22+
verticalViewPager.setCurrentItem(2)
2323
}
2424
}

app/src/main/res/layout/activity_main.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
android:layout_height="match_parent"
66
tools:context="com.ooftf.verticalpager.MainActivity">
77

8-
<com.ooftf.vertical.VerticalPagerLayout
8+
<com.ooftf.vertical.nested.VerticalPagerLayout
99
android:id="@+id/verticalViewPager"
1010
android:layout_width="match_parent"
1111
android:layout_height="match_parent"

app/src/main/res/layout/fragment_first.xml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
2+
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
33
xmlns:app="http://schemas.android.com/apk/res-auto"
44
android:id="@+id/scrollView"
55
android:layout_width="match_parent"
@@ -155,4 +155,4 @@
155155
android:paddingTop="8dp"
156156
android:text="占位符数据" />
157157
</LinearLayout>
158-
</ScrollView>
158+
</android.support.v4.widget.NestedScrollView>
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<?xml version="1.0" encoding="utf-8"?>
2-
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
2+
<android.support.v4.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
33
android:layout_width="match_parent"
44
android:layout_height="match_parent"
55
android:gravity="center">
@@ -9,4 +9,4 @@
99
android:layout_width="wrap_content"
1010
android:layout_height="wrap_content"
1111
android:text="第三个Item" />
12-
</LinearLayout>
12+
</android.support.v4.widget.NestedScrollView>

build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
buildscript {
2-
ext.kotlin_version = '1.3.11'
2+
ext.kotlin_version = '1.3.31'
33
repositories {
44
google()
55
jcenter()
66
}
77
dependencies {
8-
classpath 'com.android.tools.build:gradle:3.2.1'
8+
classpath 'com.android.tools.build:gradle:3.4.1'
99
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
1010

1111
// NOTE: Do not place your application dependencies here; they belong
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
#Mon Jan 14 15:47:19 CST 2019
1+
#Fri Jun 14 16:47:49 CST 2019
22
distributionBase=GRADLE_USER_HOME
33
distributionPath=wrapper/dists
44
zipStoreBase=GRADLE_USER_HOME
55
zipStorePath=wrapper/dists
6-
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip
6+
distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip
Lines changed: 258 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,258 @@
1+
package com.ooftf.vertical.nested
2+
3+
import android.content.Context
4+
import android.os.Build
5+
import android.support.annotation.RequiresApi
6+
import android.support.v4.view.NestedScrollingParent2
7+
import android.support.v4.view.NestedScrollingParentHelper
8+
import android.support.v4.view.PagerAdapter
9+
import android.util.AttributeSet
10+
import android.util.Log
11+
import android.view.MotionEvent
12+
import android.view.View
13+
import android.widget.FrameLayout
14+
import android.widget.Scroller
15+
16+
17+
/**
18+
* 高仿淘宝商品页上下分页布局
19+
* Created by master on 2016/3/28.
20+
*/
21+
class VerticalPagerLayout : FrameLayout, NestedScrollingParent2 {
22+
var helper = NestedScrollingParentHelper(this)
23+
override fun onNestedPreScroll(target: View, dx: Int, dy: Int, consumed: IntArray?, type: Int) {
24+
moved = true
25+
Log.e("onNestedPreScroll", "dy::" + dy)
26+
if (scrollY % height != 0) {
27+
scrollBy(0, dy)
28+
consumed?.set(1, dy)
29+
}
30+
}
31+
32+
override fun onStopNestedScroll(target: View, type: Int) {
33+
helper.onStopNestedScroll(target, type)
34+
Log.e("onStopNestedScroll", "onStopNestedScroll")
35+
judgePage(true)
36+
}
37+
38+
override fun onStartNestedScroll(child: View, target: View, axes: Int, type: Int): Boolean {
39+
mScroller.forceFinished(true)
40+
Log.e("onStartNestedScroll", "onStartNestedScroll")
41+
moved = false
42+
return true
43+
}
44+
45+
override fun onNestedScrollAccepted(child: View, target: View, axes: Int, type: Int) {
46+
Log.e("onNestedScrollAccepted", "onNestedScrollAccepted")
47+
helper.onNestedScrollAccepted(child, target, axes, type)
48+
}
49+
50+
var moved = false
51+
override fun onNestedScroll(target: View, dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, type: Int) {
52+
Log.e("onNestedScroll", "dyConsumed::" + dyConsumed + ",dyUnconsumed::" + dyUnconsumed)
53+
scrollBy(0, dyUnconsumed)
54+
}
55+
56+
57+
/**
58+
* 松开时布局滑动动画时间
59+
*/
60+
private var SCROLL_DURATION = 700
61+
62+
var offscreenPageLimit = 1;
63+
private var mScroller: Scroller
64+
private var items = ArrayList<ItemInfo>()
65+
var adapter: PagerAdapter? = null
66+
set(value) {
67+
field = value
68+
resetLayout()
69+
}
70+
71+
override fun onInterceptHoverEvent(event: MotionEvent?): Boolean {
72+
Log.e("onInterceptHoverEvent", "...")
73+
return super.onInterceptHoverEvent(event)
74+
}
75+
76+
/**
77+
* 当更换adapter之后,重置所有信息
78+
*/
79+
private fun resetLayout() {
80+
removeAllItem()
81+
scrollTo(0, 0)
82+
refreshViews()
83+
}
84+
85+
constructor(context: Context) : super(context)
86+
87+
88+
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
89+
90+
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
91+
92+
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
93+
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes)
94+
95+
init {
96+
mScroller = Scroller(context)
97+
}
98+
99+
/**
100+
* 获取到点击事件的Page 如要是为了防止一次滑动翻超过一页
101+
*/
102+
private var actionDownPage = 0
103+
104+
105+
override fun scrollTo(x: Int, y: Int) {
106+
refreshViews()
107+
super.scrollTo(x, y)
108+
}
109+
110+
private fun refreshViews() {
111+
//移除不必要View
112+
adapter ?: return
113+
adapter?.startUpdate(this)
114+
items
115+
.filter { it.position < getCurrentPage() - offscreenPageLimit || it.position > getCurrentPage() + offscreenPageLimit }
116+
.forEach {
117+
removeForItemInfo(it)
118+
}
119+
(getCurrentPage() - offscreenPageLimit..getCurrentPage() + offscreenPageLimit).forEach {
120+
addNewView(it)
121+
}
122+
adapter?.setPrimaryItem(this, getCurrentPage(), itemInfoForPosition(getCurrentPage()).obj)
123+
adapter?.finishUpdate(this)
124+
125+
}
126+
127+
/**
128+
* 移除所有的View
129+
*/
130+
private fun removeAllItem() {
131+
adapter?.startUpdate(this)
132+
items.forEach {
133+
adapter?.destroyItem(this, it.position, it.obj)
134+
}
135+
items.clear()
136+
adapter?.finishUpdate(this)
137+
}
138+
139+
/**
140+
* 根据ItemInfo 移除View
141+
*/
142+
private fun removeForItemInfo(item: ItemInfo) {
143+
adapter?.destroyItem(this, item.position, item.obj)
144+
items.remove(item)
145+
}
146+
147+
/**
148+
* 根据位置信息 添加新的view
149+
*/
150+
private fun addNewView(position: Int) {
151+
if (position < 0 && position >= adapter!!.count) return
152+
items.forEach { if (it.position == position) return }
153+
items.add(ItemInfo(position, adapter!!.instantiateItem(this, position)))
154+
}
155+
156+
/**
157+
* 获取到指定位置的View
158+
*/
159+
private fun viewForPosition(position: Int): View {
160+
val item = itemInfoForPosition(position)
161+
return viewForItemInfo(item)
162+
}
163+
164+
private fun viewForItemInfo(itemInfo: ItemInfo): View {
165+
(0 until childCount).forEach {
166+
if (adapter!!.isViewFromObject(getChildAt(it), itemInfo.obj)) {
167+
return getChildAt(it)
168+
}
169+
}
170+
throw NullPointerException()
171+
}
172+
173+
private fun itemInfoForPosition(position: Int): ItemInfo {
174+
items.forEach {
175+
if (position == it.position) {
176+
return it
177+
}
178+
}
179+
throw NullPointerException()
180+
}
181+
182+
183+
/**
184+
* 判断应该停留在哪一页
185+
*/
186+
private fun judgePage(smooth: Boolean) {
187+
setCurrentItem(getCurrentPage(), smooth)
188+
}
189+
190+
/**
191+
* 滚动到指定页面
192+
*/
193+
fun setCurrentItem(page: Int, smooth: Boolean = true) {
194+
if (height == 0) {
195+
post { setCurrentItem(page, smooth) }
196+
return
197+
}
198+
if (smooth) {
199+
mScroller.startScroll(0, scrollY, 0, height * pageController(page) - scrollY, SCROLL_DURATION)
200+
invalidate()
201+
} else {
202+
scrollTo(0, height * pageController(page))
203+
}
204+
}
205+
206+
/**
207+
* 防止position超出边缘
208+
*/
209+
private fun pageController(src: Int): Int {
210+
if (src < 0) {
211+
return 0
212+
}
213+
return if (src > adapter!!.count - 1) {
214+
adapter!!.count - 1
215+
} else src
216+
}
217+
218+
/**
219+
* 得到的是当前占有试图最大的页面
220+
*/
221+
private fun getCurrentPage(): Int {
222+
if (height == 0) return 0
223+
return Math.round(scrollY.toFloat() / height)
224+
}
225+
226+
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
227+
val height = b - t
228+
(0 until childCount).forEach {
229+
var itemInfo = itemInfoForView(getChildAt(it))
230+
getChildAt(it).layout(0, itemInfo.position * height, r - l, (itemInfo.position + 1) * height)
231+
}
232+
}
233+
234+
private fun itemInfoForView(child: View): ItemInfo {
235+
items.forEach {
236+
if (adapter!!.isViewFromObject(child, it.obj)) {
237+
return it
238+
}
239+
}
240+
throw NullPointerException()
241+
}
242+
243+
override fun computeScroll() {
244+
if (mScroller.computeScrollOffset() && !mScroller.isFinished) {
245+
scrollTo(mScroller.currX, mScroller.currY)
246+
postInvalidate()
247+
}
248+
}
249+
250+
/* fun getCurrentPage(): Int {
251+
if (height == 0) return 0
252+
return Math.round(scrollY.toFloat() / height)
253+
}*/
254+
255+
class ItemInfo(var position: Int, var obj: Any)
256+
257+
258+
}

0 commit comments

Comments
 (0)