Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
门心叼龙
android-custom-view
提交
4754b9ce
A
android-custom-view
项目概览
门心叼龙
/
android-custom-view
通知
2
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
A
android-custom-view
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
4754b9ce
编写于
10月 22, 2019
作者:
门心叼龙
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
code perfect
上级
55dc0738
变更
5
隐藏空白更改
内联
并排
Showing
5 changed file
with
757 addition
and
5 deletion
+757
-5
app/src/main/java/com/mxdl/customview/MainActivity.java
app/src/main/java/com/mxdl/customview/MainActivity.java
+3
-3
app/src/main/java/com/mxdl/customview/refer/HorizontalScrollViewEx.java
...ava/com/mxdl/customview/refer/HorizontalScrollViewEx.java
+208
-0
app/src/main/java/com/mxdl/customview/refer/PinnedHeaderExpandableListView.java
...mxdl/customview/refer/PinnedHeaderExpandableListView.java
+256
-0
app/src/main/java/com/mxdl/customview/refer/StickyLayout.java
...src/main/java/com/mxdl/customview/refer/StickyLayout.java
+286
-0
app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java
...java/com/mxdl/customview/view/HorizontalScrollViewEx.java
+4
-2
未找到文件。
app/src/main/java/com/mxdl/customview/MainActivity.java
浏览文件 @
4754b9ce
...
...
@@ -47,12 +47,12 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe
case
R
.
id
.
btn_horizontal_scroll_view_ex
:
startActivity
(
new
Intent
(
this
,
HorizontalScrollViewExActivity
.
class
));
break
;
case
R
.
id
.
btn_sticky_layout
:
startActivity
(
new
Intent
(
this
,
StickyLayoutActivity
.
class
));
break
;
case
R
.
id
.
btn_pinned_header
:
startActivity
(
new
Intent
(
this
,
PinnedHeaderActivity
.
class
));
break
;
case
R
.
id
.
btn_sticky_layout
:
startActivity
(
new
Intent
(
this
,
StickyLayoutActivity
.
class
));
break
;
case
R
.
id
.
btn_capture_rect
:
startActivity
(
new
Intent
(
this
,
CaptureRectViewActivity
.
class
));
break
;
...
...
app/src/main/java/com/mxdl/customview/refer/HorizontalScrollViewEx.java
0 → 100644
浏览文件 @
4754b9ce
package
com.mxdl.customview.refer
;
/**
* Description: <HorizontalScrollViewEx><br>
* Author: mxdl<br>
* Date: 2019/10/22<br>
* Version: V1.0.0<br>
* Update: <br>
*/
import
android.content.Context
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.MotionEvent
;
import
android.view.VelocityTracker
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.Scroller
;
public
class
HorizontalScrollViewEx
extends
ViewGroup
{
private
static
final
String
TAG
=
"HorizontalScrollViewEx"
;
private
int
mChildrenSize
;
private
int
mChildWidth
;
private
int
mChildIndex
;
// 分别记录上次滑动的坐标
private
int
mLastX
=
0
;
private
int
mLastY
=
0
;
// 分别记录上次滑动的坐标(onInterceptTouchEvent)
private
int
mLastXIntercept
=
0
;
private
int
mLastYIntercept
=
0
;
private
Scroller
mScroller
;
private
VelocityTracker
mVelocityTracker
;
public
HorizontalScrollViewEx
(
Context
context
)
{
super
(
context
);
init
();
}
public
HorizontalScrollViewEx
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
init
();
}
public
HorizontalScrollViewEx
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
);
init
();
}
private
void
init
()
{
mScroller
=
new
Scroller
(
getContext
());
mVelocityTracker
=
VelocityTracker
.
obtain
();
}
@Override
public
boolean
onInterceptTouchEvent
(
MotionEvent
event
)
{
boolean
intercepted
=
false
;
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
{
intercepted
=
false
;
if
(!
mScroller
.
isFinished
())
{
mScroller
.
abortAnimation
();
intercepted
=
true
;
}
break
;
}
case
MotionEvent
.
ACTION_MOVE
:
{
int
deltaX
=
x
-
mLastXIntercept
;
int
deltaY
=
y
-
mLastYIntercept
;
if
(
Math
.
abs
(
deltaX
)
>
Math
.
abs
(
deltaY
))
{
intercepted
=
true
;
}
else
{
intercepted
=
false
;
}
break
;
}
case
MotionEvent
.
ACTION_UP
:
{
intercepted
=
false
;
break
;
}
default
:
break
;
}
Log
.
d
(
TAG
,
"intercepted="
+
intercepted
);
mLastX
=
x
;
mLastY
=
y
;
mLastXIntercept
=
x
;
mLastYIntercept
=
y
;
return
intercepted
;
}
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
)
{
mVelocityTracker
.
addMovement
(
event
);
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
{
if
(!
mScroller
.
isFinished
())
{
mScroller
.
abortAnimation
();
}
break
;
}
case
MotionEvent
.
ACTION_MOVE
:
{
int
deltaX
=
x
-
mLastX
;
int
deltaY
=
y
-
mLastY
;
scrollBy
(-
deltaX
,
0
);
break
;
}
case
MotionEvent
.
ACTION_UP
:
{
int
scrollX
=
getScrollX
();
int
scrollToChildIndex
=
scrollX
/
mChildWidth
;
mVelocityTracker
.
computeCurrentVelocity
(
1000
);
float
xVelocity
=
mVelocityTracker
.
getXVelocity
();
if
(
Math
.
abs
(
xVelocity
)
>=
50
)
{
mChildIndex
=
xVelocity
>
0
?
mChildIndex
-
1
:
mChildIndex
+
1
;
}
else
{
mChildIndex
=
(
scrollX
+
mChildWidth
/
2
)
/
mChildWidth
;
}
mChildIndex
=
Math
.
max
(
0
,
Math
.
min
(
mChildIndex
,
mChildrenSize
-
1
));
int
dx
=
mChildIndex
*
mChildWidth
-
scrollX
;
smoothScrollBy
(
dx
,
0
);
mVelocityTracker
.
clear
();
break
;
}
default
:
break
;
}
mLastX
=
x
;
mLastY
=
y
;
return
true
;
}
@Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
super
.
onMeasure
(
widthMeasureSpec
,
heightMeasureSpec
);
int
measuredWidth
=
0
;
int
measuredHeight
=
0
;
final
int
childCount
=
getChildCount
();
measureChildren
(
widthMeasureSpec
,
heightMeasureSpec
);
int
widthSpaceSize
=
MeasureSpec
.
getSize
(
widthMeasureSpec
);
int
widthSpecMode
=
MeasureSpec
.
getMode
(
widthMeasureSpec
);
int
heightSpaceSize
=
MeasureSpec
.
getSize
(
heightMeasureSpec
);
int
heightSpecMode
=
MeasureSpec
.
getMode
(
heightMeasureSpec
);
if
(
childCount
==
0
)
{
setMeasuredDimension
(
0
,
0
);
}
else
if
(
heightSpecMode
==
MeasureSpec
.
AT_MOST
)
{
final
View
childView
=
getChildAt
(
0
);
measuredHeight
=
childView
.
getMeasuredHeight
();
setMeasuredDimension
(
widthSpaceSize
,
childView
.
getMeasuredHeight
());
}
else
if
(
widthSpecMode
==
MeasureSpec
.
AT_MOST
)
{
final
View
childView
=
getChildAt
(
0
);
measuredWidth
=
childView
.
getMeasuredWidth
()
*
childCount
;
setMeasuredDimension
(
measuredWidth
,
heightSpaceSize
);
}
else
{
final
View
childView
=
getChildAt
(
0
);
measuredWidth
=
childView
.
getMeasuredWidth
()
*
childCount
;
measuredHeight
=
childView
.
getMeasuredHeight
();
setMeasuredDimension
(
measuredWidth
,
measuredHeight
);
}
}
@Override
protected
void
onLayout
(
boolean
changed
,
int
l
,
int
t
,
int
r
,
int
b
)
{
int
childLeft
=
0
;
final
int
childCount
=
getChildCount
();
mChildrenSize
=
childCount
;
for
(
int
i
=
0
;
i
<
childCount
;
i
++)
{
final
View
childView
=
getChildAt
(
i
);
if
(
childView
.
getVisibility
()
!=
View
.
GONE
)
{
final
int
childWidth
=
childView
.
getMeasuredWidth
();
mChildWidth
=
childWidth
;
childView
.
layout
(
childLeft
,
0
,
childLeft
+
childWidth
,
childView
.
getMeasuredHeight
());
childLeft
+=
childWidth
;
}
}
}
private
void
smoothScrollBy
(
int
dx
,
int
dy
)
{
mScroller
.
startScroll
(
getScrollX
(),
0
,
dx
,
0
,
500
);
invalidate
();
}
@Override
public
void
computeScroll
()
{
if
(
mScroller
.
computeScrollOffset
())
{
scrollTo
(
mScroller
.
getCurrX
(),
mScroller
.
getCurrY
());
postInvalidate
();
}
}
@Override
protected
void
onDetachedFromWindow
()
{
mVelocityTracker
.
recycle
();
super
.
onDetachedFromWindow
();
}
}
\ No newline at end of file
app/src/main/java/com/mxdl/customview/refer/PinnedHeaderExpandableListView.java
0 → 100644
浏览文件 @
4754b9ce
package
com.mxdl.customview.refer
;
/**
* Description: <PinnedHeaderExpandableListView><br>
* Author: mxdl<br>
* Date: 2019/10/22<br>
* Version: V1.0.0<br>
* Update: <br>
*/
import
android.content.Context
;
import
android.graphics.Canvas
;
import
android.graphics.Rect
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewGroup
;
import
android.widget.AbsListView
;
import
android.widget.ExpandableListView
;
import
android.widget.AbsListView.OnScrollListener
;
public
class
PinnedHeaderExpandableListView
extends
ExpandableListView
implements
OnScrollListener
{
private
static
final
String
TAG
=
"PinnedListView"
;
private
static
final
boolean
DEBUG
=
true
;
public
interface
OnHeaderUpdateListener
{
/**
* 返回一个view对象即可
* 注意:view必须要有LayoutParams
*/
public
View
getPinnedHeader
();
public
void
updatePinnedHeader
(
View
headerView
,
int
firstVisibleGroupPos
);
}
private
View
mHeaderView
;
private
int
mHeaderWidth
;
private
int
mHeaderHeight
;
private
View
mTouchTarget
;
private
OnScrollListener
mScrollListener
;
private
OnHeaderUpdateListener
mHeaderUpdateListener
;
private
boolean
mActionDownHappened
=
false
;
protected
boolean
mIsHeaderGroupClickable
=
true
;
public
PinnedHeaderExpandableListView
(
Context
context
)
{
super
(
context
);
initView
();
}
public
PinnedHeaderExpandableListView
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
initView
();
}
public
PinnedHeaderExpandableListView
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
);
initView
();
}
private
void
initView
()
{
setFadingEdgeLength
(
0
);
setOnScrollListener
(
this
);
}
@Override
public
void
setOnScrollListener
(
OnScrollListener
l
)
{
if
(
l
!=
this
)
{
mScrollListener
=
l
;
}
else
{
mScrollListener
=
null
;
}
super
.
setOnScrollListener
(
this
);
}
/**
* 给group添加点击事件监听
* @param onGroupClickListener 监听
* @param isHeaderGroupClickable 表示header是否可点击<br/>
* note : 当不想group可点击的时候,需要在OnGroupClickListener#onGroupClick中返回true,
* 并将isHeaderGroupClickable设为false即可
*/
public
void
setOnGroupClickListener
(
OnGroupClickListener
onGroupClickListener
,
boolean
isHeaderGroupClickable
)
{
mIsHeaderGroupClickable
=
isHeaderGroupClickable
;
super
.
setOnGroupClickListener
(
onGroupClickListener
);
}
public
void
setOnHeaderUpdateListener
(
OnHeaderUpdateListener
listener
)
{
mHeaderUpdateListener
=
listener
;
if
(
listener
==
null
)
{
mHeaderView
=
null
;
mHeaderWidth
=
mHeaderHeight
=
0
;
return
;
}
mHeaderView
=
listener
.
getPinnedHeader
();
int
firstVisiblePos
=
getFirstVisiblePosition
();
int
firstVisibleGroupPos
=
getPackedPositionGroup
(
getExpandableListPosition
(
firstVisiblePos
));
listener
.
updatePinnedHeader
(
mHeaderView
,
firstVisibleGroupPos
);
requestLayout
();
postInvalidate
();
}
@Override
protected
void
onMeasure
(
int
widthMeasureSpec
,
int
heightMeasureSpec
)
{
super
.
onMeasure
(
widthMeasureSpec
,
heightMeasureSpec
);
if
(
mHeaderView
==
null
)
{
return
;
}
measureChild
(
mHeaderView
,
widthMeasureSpec
,
heightMeasureSpec
);
mHeaderWidth
=
mHeaderView
.
getMeasuredWidth
();
mHeaderHeight
=
mHeaderView
.
getMeasuredHeight
();
}
@Override
protected
void
onLayout
(
boolean
changed
,
int
l
,
int
t
,
int
r
,
int
b
)
{
super
.
onLayout
(
changed
,
l
,
t
,
r
,
b
);
if
(
mHeaderView
==
null
)
{
return
;
}
int
delta
=
mHeaderView
.
getTop
();
mHeaderView
.
layout
(
0
,
delta
,
mHeaderWidth
,
mHeaderHeight
+
delta
);
}
@Override
protected
void
dispatchDraw
(
Canvas
canvas
)
{
super
.
dispatchDraw
(
canvas
);
if
(
mHeaderView
!=
null
)
{
drawChild
(
canvas
,
mHeaderView
,
getDrawingTime
());
}
}
@Override
public
boolean
dispatchTouchEvent
(
MotionEvent
ev
)
{
int
x
=
(
int
)
ev
.
getX
();
int
y
=
(
int
)
ev
.
getY
();
int
pos
=
pointToPosition
(
x
,
y
);
if
(
mHeaderView
!=
null
&&
y
>=
mHeaderView
.
getTop
()
&&
y
<=
mHeaderView
.
getBottom
())
{
if
(
ev
.
getAction
()
==
MotionEvent
.
ACTION_DOWN
)
{
mTouchTarget
=
getTouchTarget
(
mHeaderView
,
x
,
y
);
mActionDownHappened
=
true
;
}
else
if
(
ev
.
getAction
()
==
MotionEvent
.
ACTION_UP
)
{
View
touchTarget
=
getTouchTarget
(
mHeaderView
,
x
,
y
);
if
(
touchTarget
==
mTouchTarget
&&
mTouchTarget
.
isClickable
())
{
mTouchTarget
.
performClick
();
invalidate
(
new
Rect
(
0
,
0
,
mHeaderWidth
,
mHeaderHeight
));
}
else
if
(
mIsHeaderGroupClickable
){
int
groupPosition
=
getPackedPositionGroup
(
getExpandableListPosition
(
pos
));
if
(
groupPosition
!=
INVALID_POSITION
&&
mActionDownHappened
)
{
if
(
isGroupExpanded
(
groupPosition
))
{
collapseGroup
(
groupPosition
);
}
else
{
expandGroup
(
groupPosition
);
}
}
}
mActionDownHappened
=
false
;
}
return
true
;
}
return
super
.
dispatchTouchEvent
(
ev
);
}
private
View
getTouchTarget
(
View
view
,
int
x
,
int
y
)
{
if
(!(
view
instanceof
ViewGroup
))
{
return
view
;
}
ViewGroup
parent
=
(
ViewGroup
)
view
;
int
childrenCount
=
parent
.
getChildCount
();
final
boolean
customOrder
=
isChildrenDrawingOrderEnabled
();
View
target
=
null
;
for
(
int
i
=
childrenCount
-
1
;
i
>=
0
;
i
--)
{
final
int
childIndex
=
customOrder
?
getChildDrawingOrder
(
childrenCount
,
i
)
:
i
;
final
View
child
=
parent
.
getChildAt
(
childIndex
);
if
(
isTouchPointInView
(
child
,
x
,
y
))
{
target
=
child
;
break
;
}
}
if
(
target
==
null
)
{
target
=
parent
;
}
return
target
;
}
private
boolean
isTouchPointInView
(
View
view
,
int
x
,
int
y
)
{
if
(
view
.
isClickable
()
&&
y
>=
view
.
getTop
()
&&
y
<=
view
.
getBottom
()
&&
x
>=
view
.
getLeft
()
&&
x
<=
view
.
getRight
())
{
return
true
;
}
return
false
;
}
public
void
requestRefreshHeader
()
{
refreshHeader
();
invalidate
(
new
Rect
(
0
,
0
,
mHeaderWidth
,
mHeaderHeight
));
}
protected
void
refreshHeader
()
{
if
(
mHeaderView
==
null
)
{
return
;
}
int
firstVisiblePos
=
getFirstVisiblePosition
();
int
pos
=
firstVisiblePos
+
1
;
int
firstVisibleGroupPos
=
getPackedPositionGroup
(
getExpandableListPosition
(
firstVisiblePos
));
int
group
=
getPackedPositionGroup
(
getExpandableListPosition
(
pos
));
if
(
DEBUG
)
{
Log
.
d
(
TAG
,
"refreshHeader firstVisibleGroupPos="
+
firstVisibleGroupPos
);
}
if
(
group
==
firstVisibleGroupPos
+
1
)
{
View
view
=
getChildAt
(
1
);
if
(
view
==
null
)
{
Log
.
w
(
TAG
,
"Warning : refreshHeader getChildAt(1)=null"
);
return
;
}
if
(
view
.
getTop
()
<=
mHeaderHeight
)
{
int
delta
=
mHeaderHeight
-
view
.
getTop
();
mHeaderView
.
layout
(
0
,
-
delta
,
mHeaderWidth
,
mHeaderHeight
-
delta
);
}
else
{
//TODO : note it, when cause bug, remove it
mHeaderView
.
layout
(
0
,
0
,
mHeaderWidth
,
mHeaderHeight
);
}
}
else
{
mHeaderView
.
layout
(
0
,
0
,
mHeaderWidth
,
mHeaderHeight
);
}
if
(
mHeaderUpdateListener
!=
null
)
{
mHeaderUpdateListener
.
updatePinnedHeader
(
mHeaderView
,
firstVisibleGroupPos
);
}
}
@Override
public
void
onScrollStateChanged
(
AbsListView
view
,
int
scrollState
)
{
if
(
mScrollListener
!=
null
)
{
mScrollListener
.
onScrollStateChanged
(
view
,
scrollState
);
}
}
@Override
public
void
onScroll
(
AbsListView
view
,
int
firstVisibleItem
,
int
visibleItemCount
,
int
totalItemCount
)
{
if
(
totalItemCount
>
0
)
{
refreshHeader
();
}
if
(
mScrollListener
!=
null
)
{
mScrollListener
.
onScroll
(
view
,
firstVisibleItem
,
visibleItemCount
,
totalItemCount
);
}
}
}
\ No newline at end of file
app/src/main/java/com/mxdl/customview/refer/StickyLayout.java
0 → 100644
浏览文件 @
4754b9ce
package
com.mxdl.customview.refer
;
/**
* Description: <StickyLayout><br>
* Author: mxdl<br>
* Date: 2019/10/22<br>
* Version: V1.0.0<br>
* Update: <br>
*/
import
java.util.NoSuchElementException
;
import
android.annotation.TargetApi
;
import
android.content.Context
;
import
android.os.Build
;
import
android.util.AttributeSet
;
import
android.util.Log
;
import
android.view.MotionEvent
;
import
android.view.View
;
import
android.view.ViewConfiguration
;
import
android.widget.LinearLayout
;
public
class
StickyLayout
extends
LinearLayout
{
private
static
final
String
TAG
=
"StickyLayout"
;
private
static
final
boolean
DEBUG
=
true
;
public
interface
OnGiveUpTouchEventListener
{
public
boolean
giveUpTouchEvent
(
MotionEvent
event
);
}
private
View
mHeader
;
private
View
mContent
;
private
OnGiveUpTouchEventListener
mGiveUpTouchEventListener
;
// header的高度 单位:px
private
int
mOriginalHeaderHeight
;
private
int
mHeaderHeight
;
private
int
mStatus
=
STATUS_EXPANDED
;
public
static
final
int
STATUS_EXPANDED
=
1
;
public
static
final
int
STATUS_COLLAPSED
=
2
;
private
int
mTouchSlop
;
// 分别记录上次滑动的坐标
private
int
mLastX
=
0
;
private
int
mLastY
=
0
;
// 分别记录上次滑动的坐标(onInterceptTouchEvent)
private
int
mLastXIntercept
=
0
;
private
int
mLastYIntercept
=
0
;
// 用来控制滑动角度,仅当角度a满足如下条件才进行滑动:tan a = deltaX / deltaY > 2
private
static
final
int
TAN
=
2
;
private
boolean
mIsSticky
=
true
;
private
boolean
mInitDataSucceed
=
false
;
private
boolean
mDisallowInterceptTouchEventOnHeader
=
true
;
public
StickyLayout
(
Context
context
)
{
super
(
context
);
}
public
StickyLayout
(
Context
context
,
AttributeSet
attrs
)
{
super
(
context
,
attrs
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
HONEYCOMB
)
public
StickyLayout
(
Context
context
,
AttributeSet
attrs
,
int
defStyle
)
{
super
(
context
,
attrs
,
defStyle
);
}
@Override
public
void
onWindowFocusChanged
(
boolean
hasWindowFocus
)
{
super
.
onWindowFocusChanged
(
hasWindowFocus
);
if
(
hasWindowFocus
&&
(
mHeader
==
null
||
mContent
==
null
))
{
initData
();
}
}
private
void
initData
()
{
int
headerId
=
getResources
().
getIdentifier
(
"sticky_header"
,
"id"
,
getContext
().
getPackageName
());
int
contentId
=
getResources
().
getIdentifier
(
"sticky_content"
,
"id"
,
getContext
().
getPackageName
());
if
(
headerId
!=
0
&&
contentId
!=
0
)
{
mHeader
=
findViewById
(
headerId
);
mContent
=
findViewById
(
contentId
);
mOriginalHeaderHeight
=
mHeader
.
getMeasuredHeight
();
mHeaderHeight
=
mOriginalHeaderHeight
;
mTouchSlop
=
ViewConfiguration
.
get
(
getContext
()).
getScaledTouchSlop
();
if
(
mHeaderHeight
>
0
)
{
mInitDataSucceed
=
true
;
}
if
(
DEBUG
)
{
Log
.
d
(
TAG
,
"mTouchSlop = "
+
mTouchSlop
+
"mHeaderHeight = "
+
mHeaderHeight
);
}
}
else
{
throw
new
NoSuchElementException
(
"Did your view with id \"sticky_header\" or \"sticky_content\" exists?"
);
}
}
public
void
setOnGiveUpTouchEventListener
(
OnGiveUpTouchEventListener
l
)
{
mGiveUpTouchEventListener
=
l
;
}
@Override
public
boolean
onInterceptTouchEvent
(
MotionEvent
event
)
{
int
intercepted
=
0
;
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
{
mLastXIntercept
=
x
;
mLastYIntercept
=
y
;
mLastX
=
x
;
mLastY
=
y
;
intercepted
=
0
;
break
;
}
case
MotionEvent
.
ACTION_MOVE
:
{
int
deltaX
=
x
-
mLastXIntercept
;
int
deltaY
=
y
-
mLastYIntercept
;
if
(
mDisallowInterceptTouchEventOnHeader
&&
y
<=
getHeaderHeight
())
{
intercepted
=
0
;
}
else
if
(
Math
.
abs
(
deltaY
)
<=
Math
.
abs
(
deltaX
))
{
intercepted
=
0
;
}
else
if
(
mStatus
==
STATUS_EXPANDED
&&
deltaY
<=
-
mTouchSlop
)
{
intercepted
=
1
;
}
else
if
(
mGiveUpTouchEventListener
!=
null
)
{
if
(
mGiveUpTouchEventListener
.
giveUpTouchEvent
(
event
)
&&
deltaY
>=
mTouchSlop
)
{
intercepted
=
1
;
}
}
break
;
}
case
MotionEvent
.
ACTION_UP
:
{
intercepted
=
0
;
mLastXIntercept
=
mLastYIntercept
=
0
;
break
;
}
default
:
break
;
}
if
(
DEBUG
)
{
Log
.
d
(
TAG
,
"intercepted="
+
intercepted
);
}
return
intercepted
!=
0
&&
mIsSticky
;
}
@Override
public
boolean
onTouchEvent
(
MotionEvent
event
)
{
if
(!
mIsSticky
)
{
return
true
;
}
int
x
=
(
int
)
event
.
getX
();
int
y
=
(
int
)
event
.
getY
();
switch
(
event
.
getAction
())
{
case
MotionEvent
.
ACTION_DOWN
:
{
break
;
}
case
MotionEvent
.
ACTION_MOVE
:
{
int
deltaX
=
x
-
mLastX
;
int
deltaY
=
y
-
mLastY
;
if
(
DEBUG
)
{
Log
.
d
(
TAG
,
"mHeaderHeight="
+
mHeaderHeight
+
" deltaY="
+
deltaY
+
" mlastY="
+
mLastY
);
}
mHeaderHeight
+=
deltaY
;
setHeaderHeight
(
mHeaderHeight
);
break
;
}
case
MotionEvent
.
ACTION_UP
:
{
// 这里做了下判断,当松开手的时候,会自动向两边滑动,具体向哪边滑,要看当前所处的位置
int
destHeight
=
0
;
if
(
mHeaderHeight
<=
mOriginalHeaderHeight
*
0.5
)
{
destHeight
=
0
;
mStatus
=
STATUS_COLLAPSED
;
}
else
{
destHeight
=
mOriginalHeaderHeight
;
mStatus
=
STATUS_EXPANDED
;
}
// 慢慢滑向终点
this
.
smoothSetHeaderHeight
(
mHeaderHeight
,
destHeight
,
500
);
break
;
}
default
:
break
;
}
mLastX
=
x
;
mLastY
=
y
;
return
true
;
}
public
void
smoothSetHeaderHeight
(
final
int
from
,
final
int
to
,
long
duration
)
{
smoothSetHeaderHeight
(
from
,
to
,
duration
,
false
);
}
public
void
smoothSetHeaderHeight
(
final
int
from
,
final
int
to
,
long
duration
,
final
boolean
modifyOriginalHeaderHeight
)
{
final
int
frameCount
=
(
int
)
(
duration
/
1000
f
*
30
)
+
1
;
final
float
partation
=
(
to
-
from
)
/
(
float
)
frameCount
;
new
Thread
(
"Thread#smoothSetHeaderHeight"
)
{
@Override
public
void
run
()
{
for
(
int
i
=
0
;
i
<
frameCount
;
i
++)
{
final
int
height
;
if
(
i
==
frameCount
-
1
)
{
height
=
to
;
}
else
{
height
=
(
int
)
(
from
+
partation
*
i
);
}
post
(
new
Runnable
()
{
public
void
run
()
{
setHeaderHeight
(
height
);
}
});
try
{
sleep
(
10
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
if
(
modifyOriginalHeaderHeight
)
{
setOriginalHeaderHeight
(
to
);
}
};
}.
start
();
}
public
void
setOriginalHeaderHeight
(
int
originalHeaderHeight
)
{
mOriginalHeaderHeight
=
originalHeaderHeight
;
}
public
void
setHeaderHeight
(
int
height
,
boolean
modifyOriginalHeaderHeight
)
{
if
(
modifyOriginalHeaderHeight
)
{
setOriginalHeaderHeight
(
height
);
}
setHeaderHeight
(
height
);
}
public
void
setHeaderHeight
(
int
height
)
{
if
(!
mInitDataSucceed
)
{
initData
();
}
if
(
DEBUG
)
{
Log
.
d
(
TAG
,
"setHeaderHeight height="
+
height
);
}
if
(
height
<=
0
)
{
height
=
0
;
}
else
if
(
height
>
mOriginalHeaderHeight
)
{
height
=
mOriginalHeaderHeight
;
}
if
(
height
==
0
)
{
mStatus
=
STATUS_COLLAPSED
;
}
else
{
mStatus
=
STATUS_EXPANDED
;
}
if
(
mHeader
!=
null
&&
mHeader
.
getLayoutParams
()
!=
null
)
{
mHeader
.
getLayoutParams
().
height
=
height
;
mHeader
.
requestLayout
();
mHeaderHeight
=
height
;
}
else
{
if
(
DEBUG
)
{
Log
.
e
(
TAG
,
"null LayoutParams when setHeaderHeight"
);
}
}
}
public
int
getHeaderHeight
()
{
return
mHeaderHeight
;
}
public
void
setSticky
(
boolean
isSticky
)
{
mIsSticky
=
isSticky
;
}
public
void
requestDisallowInterceptTouchEventOnHeader
(
boolean
disallowIntercept
)
{
mDisallowInterceptTouchEventOnHeader
=
disallowIntercept
;
}
}
\ No newline at end of file
app/src/main/java/com/mxdl/customview/view/HorizontalScrollViewEx.java
浏览文件 @
4754b9ce
...
...
@@ -35,9 +35,10 @@ import android.widget.Scroller;
* 4.对速度检测器没有添加事件,知道获取的速度一直是0
* 5.computeScroll()方法里面没有postinvlate
* 6.对于正在滑动中再次进行滑动没有做优化
* 7.Math.abs(dx) >= Math.abs(dy) 加上等于会导致0,0的情况也被拦截,上滑,下滑会翻页
*/
public
class
HorizontalScrollViewEx
extends
ViewGroup
{
public
static
final
String
TAG
=
HorizontalScrollViewEx
.
class
.
getSimpleName
();
private
Scroller
mScroller
;
private
VelocityTracker
mVelocityTracker
;
private
int
mLastX
;
...
...
@@ -127,11 +128,12 @@ public class HorizontalScrollViewEx extends ViewGroup {
case
MotionEvent
.
ACTION_MOVE
:
int
dx
=
x
-
mLastInterceptX
;
int
dy
=
y
-
mLastInterceptY
;
if
(
Math
.
abs
(
dx
)
>
=
Math
.
abs
(
dy
))
{
if
(
Math
.
abs
(
dx
)
>
Math
.
abs
(
dy
))
{
intercept
=
true
;
}
else
{
intercept
=
false
;
}
Log
.
v
(
TAG
,
"dx:"
+
dx
+
";dy:"
+
dy
+
"intercept:"
+
intercept
);
break
;
case
MotionEvent
.
ACTION_UP
:
intercept
=
false
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录