继承ViewGoup,重写onInterceptTouchEvent截拦触摸事件并按条件分发给子View。
package
com.example.viewdemo;
import
android.content.Context;
import
android.util.AttributeSet;
import
android.view.MotionEvent;
import
android.view.VelocityTracker;
import
android.view.View;
import
android.view.ViewGroup;
import
android.widget.Scroller;
public
class
SliderView
extends
ViewGroup {
/**
* 速度边界
*/
private
static
final
int
VELOCITY_X_SPEED =
800
;
/**
* 最后一次触摸的x位置
*/
private
float
x;
private
Scroller scroller;
/**
* 触摸事件是否已分发给子view
*/
private
boolean
dispatched;
private
boolean
slided;
private
int
startScrollLeftOffset;
private
VelocityTracker mVelocityTracker;
public
SliderView(Context context, AttributeSet attrs) {
super
(context, attrs);
scroller =
new
Scroller(context);
}
@Override
protected
void
onLayout(
boolean
arg0,
int
arg1,
int
arg2,
int
arg3,
int
arg4) {
int
childCount = getChildCount();
for
(
int
i =
0
; i < childCount; ++i) {
View view = getChildAt(i);
if
(view.getVisibility() != View.GONE) {
view.layout(
0
,
0
, view.getMeasuredWidth(),
view.getMeasuredHeight());
}
}
}
@Override
public
boolean
onInterceptTouchEvent(MotionEvent ev) {
return
true
;
}
@Override
public
boolean
onTouchEvent(MotionEvent event) {
if
(mVelocityTracker ==
null
) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
int
action = event.getAction();
if
(action == MotionEvent.ACTION_DOWN) {
x = event.getX();
//分发事件
if
(isSlided()) {
dispatched = dispatchTouchEventToView(getChildAt(
0
), event);
}
else
{
dispatched = dispatchTouchEventToView(getChildAt(
1
), event);
}
}
else
if
(action == MotionEvent.ACTION_MOVE) {
if
(dispatched) {
//分发事件
if
(isSlided()) {
dispatchTouchEventToView(getChildAt(
0
), event);
}
else
{
dispatchTouchEventToView(getChildAt(
1
), event);
}
}
else
{
//重置第一个子view位置
float
dx = event.getX() - x;
View view = getChildAt(
1
);
int
left = (
int
) (view.getLeft() + dx);
if
(left >=
0
) {
view.layout(left, view.getTop(), view.getWidth() + left,
view.getTop() + view.getHeight());
}
}
x = event.getX();
}
else
if
(action == MotionEvent.ACTION_CANCEL
|| action == MotionEvent.ACTION_UP) {
if
(dispatched) {
//分发事件
if
(isSlided()) {
dispatchTouchEventToView(getChildAt(
0
), event);
}
else
{
dispatchTouchEventToView(getChildAt(
1
), event);
}
}
else
{
//判断速度
mVelocityTracker.computeCurrentVelocity(
1000
);
int
velocityX = (
int
) mVelocityTracker.getXVelocity();
if
(velocityX > VELOCITY_X_SPEED) {
setSlided(
true
);
}
else
if
(velocityX < -VELOCITY_X_SPEED) {
setSlided(
false
);
}
else
{
View view = getChildAt(
1
);
if
(view.getLeft() >= view.getWidth() /
2
) {
setSlided(
true
);
}
else
{
setSlided(
false
);
}
}
if
(mVelocityTracker !=
null
) {
mVelocityTracker.recycle();
}
}
}
return
true
;
}
public
boolean
isSlided() {
return
slided;
}
/**
* 设置是否滑动显示菜单状态,并动画滑动效果
* @param slided
*/
public
void
setSlided(
boolean
slided) {
View view = getChildAt(
1
);
startScrollLeftOffset = view.getLeft();
if
(slided) {
scroller.startScroll(
0
, getTop(), view.getWidth() *
3
/
4
- startScrollLeftOffset,
0
);
}
else
{
scroller.startScroll(
0
, getTop(), -startScrollLeftOffset,
0
);
}
this
.slided = slided;
postInvalidate();
}
@Override
public
void
computeScroll() {
if
(scroller.computeScrollOffset()) {
View view = getChildAt(
1
);
int
left = startScrollLeftOffset + scroller.getCurrX();
view.layout(left, view.getTop(), left + view.getWidth(),
view.getHeight());
postInvalidate();
}
}
@Override
protected
void
onMeasure(
int
widthMeasureSpec,
int
heightMeasureSpec) {
super
.onMeasure(widthMeasureSpec, heightMeasureSpec);
for
(
int
i =
0
; i < getChildCount(); ++i) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
}
public
boolean
dispatchTouchEventToView(View view, MotionEvent ev) {
try
{
return
view.dispatchTouchEvent(ev);
}
catch
(Exception e) {
// 部分机型会抛异常
e.printStackTrace();
}
return
false
;
}
}
|
------------------------------------------------------例子
package
com.example.viewdemo;
import
android.app.Activity;
import
android.os.Bundle;
import
android.view.Menu;
import
android.view.View;
import
android.view.View.OnClickListener;
import
android.widget.AdapterView;
import
android.widget.AdapterView.OnItemClickListener;
import
android.widget.ArrayAdapter;
import
android.widget.Button;
import
android.widget.ListView;
import
android.widget.Toast;
public
class
MainActivity
extends
Activity
implements
OnClickListener,
OnItemClickListener {
SliderView sliderView;
ListView listView;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sliderView = (SliderView) findViewById(R.id.slider_view);
Button button1 = (Button) findViewById(R.id.button1);
Button button2 = (Button) findViewById(R.id.button2);
button1.setOnClickListener(
this
);
button2.setOnClickListener(
this
);
listView = (ListView) findViewById(R.id.listView);
ArrayAdapter<String> adapter =
new
ArrayAdapter<String>(
this
,
android.R.layout.simple_list_item_1,
new
String[] {
"GOOD"
,
"HAHA"
,
"What is that?"
,
"FUUUUCK"
});
listView.setAdapter(adapter);
listView.setOnItemClickListener(
this
);
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
return
true
;
}
@Override
public
boolean
onPrepareOptionsMenu(Menu menu) {
sliderView.setSlided(!sliderView.isSlided());
return
true
;
}
@Override
public
void
onClick(View v) {
Toast.makeText(
this
, ((Button) v).getText().toString(),
Toast.LENGTH_LONG).show();
}
@Override
public
void
onItemClick(AdapterView<?> arg0, View arg1,
int
arg2,
long
arg3) {
String string = (String) arg0.getItemAtPosition(arg2);
Toast.makeText(
this
, string, Toast.LENGTH_LONG).show();
}
}
|
----------------------------------------------布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.viewdemo.SliderView
android:id="@+id/slider_view"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="3"
android:orientation="vertical" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="hello" />
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1" >
</ListView>
</LinearLayout>
<LinearLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="1" >
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/black"
android:gravity="center" >
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="world" />
</LinearLayout>
</com.example.viewdemo.SliderView>
</LinearLayout>