Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android自定義View—滑動控件

Android自定義View—滑動控件

編輯:關於Android編程

\

MainActivity如下:<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4KPHByZSBjbGFzcz0="brush:java;">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如下:



    


slideview.xml如下:




    

    

    

    

    



  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved