您的位置:首页 > 移动开发 > Android开发

Android自定义View示例(三)—滑动控件

2014-02-04 13:27 746 查看


MainActivity如下:

package cc.testview4;
import cc.testview4.SlideView.SwitchChangedListener;
import android.app.Activity;
import android.os.Bundle;
/**
* Demo描述:
* 自定义滑动控件
*
* 参考资料:
* http://blog.csdn.net/lfdfhl/article/details/8195441 *
* 备注说明:
* 在CopyOfSlideView中使用了另外一种方式:
* 主要涉及到自定义控件的Touch和GestureDetector的处理
* 详细代码请参见SlideView是一种很好的方式和思路!!!
* 该方式中有一点点点(很微小)BUG参见其中代码的第71行
*/
public class MainActivity extends Activity {
private SlideView mSlideView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
init();
}

private void init(){
mSlideView=(SlideView) findViewById(R.id.slideView);
mSlideView.setSwitchChangedListener(new SwitchChangedListenerImpl());
}

private class SwitchChangedListenerImpl implements SwitchChangedListener{
@Override
public void OnChanged(String info) {
System.out.println("info="+info);
}

}
}


SlideView如下:

package cc.testview4;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

public class SlideView extends RelativeLayout{
private SwitchChangedListener mSwitchChangedListener;
private Context mContext;
private View mSlideView;
private int dotRawLeft;
private int dotRawRight;
private int dotRawTop;
private int dotRawBottom;

private int downX;
private int downY;
private int dotCurrentLeft;
private int dotCurrentRight;
private int dotCurrentTop;
private int dotCurrentBottom;

// 中间圆球
private ImageView mDotImageView;
// 上一步
private ImageView mPreStepImageView;
// 下一步
private ImageView mNextStepImageView;
// 上一步箭头线
private ImageView mPreArrowImageView;
// 下一步箭头线
private ImageView mNextArrowImageView;
// 上一步箭头的左边相对于parent左边的位置
private int preArrowLeft;
private int preArrowWidth;
// 上一步箭头的右边相对于parent左边的位置
private int preArrowRight;
// 下一步箭头的左边相对于parent左边的位置
private int nextArrowLeft;
// 下一步箭头的右边相对于parent左边的位置
private int nextArrowWidth;
private int nextArrowRight;

public SlideView(Context context) {
super(context);
init(context);
}

public SlideView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

private void init(Context context){
mContext=context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSlideView = inflater.inflate(R.layout.slideview, this);

mDotImageView = (ImageView) mSlideView.findViewById(R.id.dotImageView);
mPreStepImageView = (ImageView) mSlideView.findViewById(R.id.preStepImageView);
mNextStepImageView = (ImageView) mSlideView.findViewById(R.id.nextStepImageView);
mNextArrowImageView = (ImageView) mSlideView.findViewById(R.id.nextArrowImageView);
mPreArrowImageView = (ImageView) mSlideView.findViewById(R.id.preArrowImageView);

this.getRawLocation();

// 自定义组件添加触摸监听事件
mDotImageView.setOnTouchListener(new TouchListenerImpl());
}

//利用Post方式获取一些位置坐标
private void getRawLocation(){
mNextArrowImageView.post(new Runnable() {
@Override
public void run() {
dotRawLeft = mDotImageView.getLeft();
dotRawRight = mDotImageView.getRight();
dotRawTop = mDotImageView.getTop();
dotRawBottom = mDotImageView.getBottom();

preArrowWidth=mPreArrowImageView.getWidth();
nextArrowWidth=mNextArrowImageView.getWidth();
}
});
}

private class TouchListenerImpl implements OnTouchListener{
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) event.getRawX();
downY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
//手指向左滑动,dx<0
//手指向右滑动,dx>0
int distanceX =(int)event.getRawX() - downX;//移动的距离
int distanceY =(int)event.getRawY() - downY;//移动的距离

//防止越界
if (distanceX<0) {
if (Math.abs(distanceX)>=preArrowWidth) {
distanceX=-preArrowWidth;
}
} else {
if (distanceX>=nextArrowWidth) {
distanceX=nextArrowWidth;
}
}

dotCurrentLeft= dotRawLeft + distanceX;
dotCurrentRight = dotRawRight + distanceX;

System.out.println("dotCurrentLeft="+dotCurrentLeft+",dotCurrentRight="+dotCurrentRight);

if (distanceX<0&&Math.abs(distanceX)==preArrowWidth) {
mSwitchChangedListener.OnChanged("上一步");
}
if (distanceX>0&&distanceX==nextArrowWidth) {
mSwitchChangedListener.OnChanged("下一步");
}

mDotImageView.layout(dotCurrentLeft, dotRawTop, dotCurrentRight,dotRawBottom);

break;
case MotionEvent.ACTION_UP:
mDotImageView.layout(dotRawLeft, dotRawTop, dotRawRight,dotRawBottom);
break;
default:
break;
}

return true;
}
}

// 回调接口
public interface SwitchChangedListener {
public void OnChanged(String info);
}

public void setSwitchChangedListener(SwitchChangedListener switchChangedListener) {
this.mSwitchChangedListener=switchChangedListener;
}

}


CopyOfSlideView如下:

package cc.testview4;
import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.Toast;

public class CopyOfSlideView extends RelativeLayout{
private SwitchChangedListener mSwitchChangedListener;
private Context mContext;
private View mSlideView;
private int dotRawLeft;
private int dotRawRight;
private int dotRawTop;
private int dotRawBottom;
// 中间圆球
private ImageView mDotImageView;
// 上一步
private ImageView mPreStepImageView;
// 下一步
private ImageView mNextStepImageView;
// 上一步箭头线
private ImageView mPreArrowImageView;
// 下一步箭头线
private ImageView mNextArrowImageView;
// 上一步箭头的左边相对于parent左边的位置
private int preArrowLeft;
// 上一步箭头的右边相对于parent左边的位置
private int preArrowRight;
// 下一步箭头的左边相对于parent左边的位置
private int nextArrowLeft;
// 下一步箭头的右边相对于parent左边的位置
private int nextArrowRight;

// 在X轴上一共移动的距离
private int sliddingSumX = 0;
private RelativeLayout mSlideViewRelativeLayout;
private GestureDetector mGestureDetector;
private SlideViewGestureListener mSlideViewGestureListener;
public CopyOfSlideView(Context context) {
super(context);
init(context);
}

public CopyOfSlideView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}

private void init(Context context){
mContext=context;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mSlideView = inflater.inflate(R.layout.slideview, this);

mDotImageView = (ImageView) mSlideView.findViewById(R.id.dotImageView);
mPreStepImageView = (ImageView) mSlideView.findViewById(R.id.preStepImageView);
mNextStepImageView = (ImageView) mSlideView.findViewById(R.id.nextStepImageView);
mNextArrowImageView = (ImageView) mSlideView.findViewById(R.id.nextArrowImageView);
mPreArrowImageView = (ImageView) mSlideView.findViewById(R.id.preArrowImageView);
mSlideViewRelativeLayout = (RelativeLayout) findViewById(R.id.slideView_RelativeLayout);

this.getRawLocation();

mSlideViewGestureListener = new SlideViewGestureListener();
mGestureDetector = new GestureDetector(mContext,mSlideViewGestureListener);

// 自定义组件添加触摸监听事件
// 利用以下一句是对整个自定义控件实现了Touch监听,滑块滑动时正常
mSlideView.setOnTouchListener(new TouchListenerImpl());
// 利用以下一句是对滑块实现了Touch监听,滑块滑动时有抖动现象,原因不明待查
//mDotImageView.setOnTouchListener(new TouchListenerImpl());
}

//利用Post方式获取一些位置坐标
private void getRawLocation(){
mNextArrowImageView.post(new Runnable() {
@Override
public void run() {
dotRawLeft = mDotImageView.getLeft();
dotRawRight = mDotImageView.getRight();
dotRawTop = mDotImageView.getTop();
dotRawBottom = mDotImageView.getBottom();
preArrowLeft = mPreArrowImageView.getLeft();
preArrowRight = mPreArrowImageView.getRight();
nextArrowLeft = mNextArrowImageView.getLeft();
nextArrowRight = mNextArrowImageView.getRight();
}
});
}

private class TouchListenerImpl implements OnTouchListener{
@Override
public boolean onTouch(View view, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_UP:
// 滑动距离小于五分之四,回到原位
if (Math.abs(sliddingSumX) < (preArrowRight - preArrowLeft) * 4 / 5) {
mDotImageView.layout(dotRawLeft, dotRawTop, dotRawRight,dotRawBottom);
sliddingSumX = 0;
} else {
if (mDotImageView.getLeft() < dotRawLeft) {
Toast.makeText(mContext, "上一步", 0).show();
mSwitchChangedListener.OnChanged("到达了上一步");
mDotImageView.layout(dotRawLeft, dotRawTop,dotRawRight, dotRawBottom);
sliddingSumX = 0;
} else {
Toast.makeText(mContext, "下一步", 0).show();
mSwitchChangedListener.OnChanged("到达了下一步");
mDotImageView.layout(dotRawLeft, dotRawTop,dotRawRight, dotRawBottom);
sliddingSumX = 0;
}

}
break;
default:
break;
}

/**
* 注意:
* 在OnTouchListener中把move和down事件处理都转交给了mGestureDetector.
* 在OnTouchListener中只处理了up事件---在手指抬起后显示dotImageView.
*/
return mGestureDetector.onTouchEvent(event);
}
}

// 自定义控件的手势
// 注意:在相应的方法中返回true,表示已经消费完事件
private class SlideViewGestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
return true;
}

// 在自定义控件滑动时候执行此方法
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,float distanceX, float distanceY) {

sliddingSumX = sliddingSumX + (int) distanceX;
// 再次显示dotImageView时只需要改变X轴方向的值
// 往左拉动,X增大;往右拉动,x减小
// 注意:往右拉动,distanceX为负值;往左拉动,distanceX为正值.
// 所以不是:rawLeft+sumX, rawTop, rawRight+sumX, rawBottom
// 而应该是:rawLeft-sumX, rawTop, rawRight-sumX, rawBottom
if (dotRawLeft - sliddingSumX >= (preArrowLeft - (mDotImageView.getWidth() * 0.5))&&
dotRawRight - sliddingSumX <= nextArrowRight+ ((mDotImageView.getWidth() * 0.5))) {
System.out.println("==> distanceX="+distanceX+",sliddingSumX="+sliddingSumX);
mDotImageView.layout
(dotRawLeft - sliddingSumX, dotRawTop,dotRawRight - sliddingSumX, dotRawBottom);
} else {
System.out.println("超过了两头的边界");
}

return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
return false;
}

@Override
public void onLongPress(MotionEvent e) {
}

@Override
public void onShowPress(MotionEvent e) {
}

@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
}

// 回调接口
public interface SwitchChangedListener {
public void OnChanged(String info);
}

public void setSwitchChangedListener(SwitchChangedListener switchChangedListener) {
this.mSwitchChangedListener=switchChangedListener;
}

}


main.xml如下:

<RelativeLayout 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" >

<cc.testview4.SlideView
android:id="@+id/slideView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
/>

</RelativeLayout>


slideview.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slideView_RelativeLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/step_bg"
android:orientation="horizontal" >

<ImageView
android:id="@+id/dotImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:background="@drawable/step_ball"
android:clickable="false" />

<ImageView
android:id="@+id/preArrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_toLeftOf="@id/dotImageView"
android:background="@drawable/step_preline" />

<ImageView
android:id="@+id/preStepImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginRight="10dip"
android:layout_toLeftOf="@id/preArrowImageView"
android:background="@drawable/step_pre" />

<ImageView
android:id="@+id/nextArrowImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_toRightOf="@id/dotImageView"
android:background="@drawable/step_nextline" />

<ImageView
android:id="@+id/nextStepImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginLeft="10dip"
android:layout_toRightOf="@id/nextArrowImageView"
android:background="@drawable/step_next" />

</RelativeLayout>
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐