編輯:關於Android編程
由於個人技術還比較薄弱,就在這個自定義控件的基礎上做了個拓展,支持水平和垂直的
下面是主要代碼;
GuideView:
import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Point; import android.graphics.PointF; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.Log; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.Scroller; import android.widget.Toast; @SuppressLint(ClickableViewAccessibility) public class GuideView extends ViewGroup { /** ***/ /** 滑動方向 */ private int mOrientation = 0; /** 水平方向 */ private int mHorientation = 0; /** 垂直方向 */ private int mVertical = 1; /** 屏幕寬度 */ private int mScreenWidth; /** 屏幕高度 */ private int mScreenHeight; /** 滑動狀態 */ private boolean isScrolling; /** 滑動輔助類 */ private Scroller mScroller; /** 記錄當前的x/y的值 */ private PointF mPointF; /** 記錄上一次的x、y值 */ private PointF mLastPointF; /** Scroller 對應的開始坐標 */ private Point mScrollStartPoint; /** Scroller 對應的結束坐標 */ private Point mScrollStopPoint; /** 記錄滑動的距離 */ private PointF mDistancePointF; /**ScrollXY 的差值*/ private Point mDistanceScrollPoint; /** 加速度檢測 */ private VelocityTracker mVelocityTracker; /**切換屏幕時的回調函數*/ private OnPageChangeListener mOnPageChangeListener; /** * 記錄當前頁 */ private int currentPage = 0; public GuideView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub // 獲取自定義屬性 TypedArray mTypeArray = context.obtainStyledAttributes( attrs, R.styleable.GuideView_orientation); mOrientation = mTypeArray.getInteger( R.styleable.GuideView_orientation_orientation, mOrientation); mTypeArray.recycle(); // 獲取屏幕寬高 initialScreen(context); mScroller = new Scroller(context); mPointF = new PointF(); mLastPointF = new PointF(); mScrollStartPoint = new Point(); mScrollStopPoint = new Point(); mDistancePointF = new PointF(); mDistanceScrollPoint=new Point(); } public GuideView(Context context, AttributeSet attrs) { this(context, attrs, 1); // TODO Auto-generated constructor stub } public GuideView(Context context) { this(context, null); // TODO Auto-generated constructor stub } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // TODO Auto-generated method stub super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 獲取子布局,重新測量子布局寬高 int count = getChildCount(); for (int i = 0; i < count; i++) { measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec); } } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub if (changed) { // 重新測量layout的位置 MarginLayoutParams params = (MarginLayoutParams) getLayoutParams(); int childCount = getChildCount(); if (mOrientation == mHorientation) { params.width = mScreenWidth * getChildCount(); setLayoutParams(params); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); if (view.getVisibility() != View.GONE) { view.layout(i * mScreenWidth, t, i * mScreenWidth + mScreenWidth, b); } } } else if (mOrientation == mVertical) { params.height = mScreenHeight * getChildCount(); setLayoutParams(params); for (int i = 0; i < childCount; i++) { View view = getChildAt(i); // view 沒有隱藏掉,就重新定位 if (view.getVisibility() != View.GONE) { view.layout(l, i * mScreenHeight, r, i * mScreenHeight + mScreenHeight); } } } } } @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub // 先進行事件判斷攔截 if(currentPage==getChildCount()-1){ Toast.makeText(getContext(), finish, Toast.LENGTH_SHORT).show(); return super.onTouchEvent(event); } if (isScrolling) return super.onTouchEvent(event); mPointF.x = event.getX(); mPointF.y = event.getY(); // 初始化加速度檢測器 initialVelocity(event); if (event.getAction() == MotionEvent.ACTION_DOWN) { // 當用戶觸摸時記錄下坐標信息 Log.i(info, *******mPoint value****+x:+mPointF.x+y:+mPointF.y); getStartScrollXY(); mLastPointF.x = mPointF.x; mLastPointF.y = mPointF.y; } else if (event.getAction() == MotionEvent.ACTION_MOVE) { Log.i(info, *******mLastPoint value****+x:+mLastPointF.x+y:+mLastPointF.y); Log.i(info, *******mPoint value****+x:+mPointF.x+y:+mPointF.y); Log.i(info, *******************************************); Log.i(info, *******************************************); /** * Stops the animation. Contrary to * {@link #forceFinished(boolean)}, aborting the animating cause * the scroller to move to the final x and y position 源碼說明: * mScroller.abortAnimation() 如果滑動還沒有結束,那麼就終止滑動。 * * @see #forceFinished(boolean) */ if (!mScroller.isFinished()) { mScroller.abortAnimation(); } mDistancePointF.x = mLastPointF.x - mPointF.x; mDistancePointF.y = mLastPointF.y - mPointF.y; Log.i(info, *******mDistancePointF value ******+dx: +mDistancePointF.x+ dy: +mDistancePointF.y); getStopScrollXY(); // 先判斷滑動的方向確定滑動的距離 scrollBy(x,y) // 1.y軸---向上滑動--下一個視圖 // 2.y軸---向下滑動--上一個視圖 // 3.x軸---向左滑動--下一個視圖 // 4.x軸---向右滑動--上一個視圖 /** * 320*480 -8 mlasty=-10 currenty=-2 * distance=mlasty-currenty=-8《0 scrolly+distance<0? * * 條件都滿足時,確定視圖向上滑動,加載 下一個視圖 * * 重新定義distanceY的值以便於ScrollBy(x,y)調用 * * 補充說明: * getScrollX()說明:=手機屏幕顯示區域左上角x坐標減去MultiViewGroup視圖左上角x坐標=320 * * getScrollY()說明:=手機屏幕顯示區域左上角y坐標減去MultiViewGroup視圖左上角y坐標=0( * 因為子視圖的高度和手機屏幕高度一樣) * * **/ if (mOrientation == mHorientation) { if (mDistancePointF.x > 0 && mScrollStopPoint.x + mDistancePointF.x > getWidth()-mScreenWidth) { mDistancePointF.x = getWidth() - mScreenWidth -mScrollStopPoint.x; } else if (mDistancePointF.x < 0 && mScrollStopPoint.x + mDistancePointF.x < 0) { mDistancePointF.x = - mScrollStopPoint.x; } scrollBy((int) mDistancePointF.x, 0); } else if (mOrientation == mVertical) { if (mDistancePointF.y < 0 && mScrollStopPoint.y + mDistancePointF.y < 0) { mDistancePointF.y = -mScrollStopPoint.y; } if (mDistancePointF.y > 0 && mScrollStopPoint.y + mDistancePointF.y > getHeight() - mScreenHeight) { mDistancePointF.y = getHeight() - mScreenHeight - mScrollStopPoint.y; } scrollBy(0, (int) mDistancePointF.y); } mLastPointF.x = mPointF.x; mLastPointF.y = mPointF.y; } else if (event.getAction() == MotionEvent.ACTION_UP) { getStopScrollXY(); getDistanceScrollXY(); //比較滑動方向趨勢 //判斷是上滑動還是下滑動 if(checkDirection()){ //上滑動《加載更多》 if(isScrollToNext()){ //能滑動到下一頁 if(mOrientation==mHorientation){ mScroller.startScroll(getScrollX(), 0,mScreenWidth - mDistanceScrollPoint.x,0); }else if (mOrientation==mVertical){ mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - mDistanceScrollPoint.y); } }else{ //不能滑動到下一頁 if(mOrientation==mHorientation){ mScroller.startScroll(getScrollX(), 0,-mDistanceScrollPoint.x,0); }else if (mOrientation==mVertical){ mScroller.startScroll(0, getScrollY(), 0, -mDistanceScrollPoint.y); } } }else{ //《下滑動,刷新》 if(isScrollToprivew()){ //能滑動到上一頁 if(mOrientation==mHorientation){ mScroller.startScroll( getScrollX(), 0, -mScreenWidth - mDistanceScrollPoint.x,0); }else if (mOrientation==mVertical){ mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - mDistanceScrollPoint.y); } }else{ //不能滑動到上一頁 if(mOrientation==mHorientation){ mScroller.startScroll(getScrollX(),0, -mDistanceScrollPoint.x, 0); }else if (mOrientation==mVertical){ mScroller.startScroll(0, getScrollY(), 0, -mDistanceScrollPoint.y); } } } isScrolling = true; postInvalidate(); recycleVelocity(); } return true; } /** * Called by a parent to request that a child update its values for mScrollX * and mScrollY if necessary. This will typically be done if the child is * animating a scroll using a {@link android.widget.Scroller Scroller} * object. * * 為了易於控制滑屏控制,Android框架提供了 computeScroll()方法去控制這個流程。在繪制View時,會在draw()過程調用該 * 方法。因此, 再配合使用Scroller實例,我們就可以獲得當前應該的偏移坐標,手動使View/ViewGroup偏移至該處。 * computeScroll()方法原型如下,該方法位於ViewGroup.java類中 */ @Override public void computeScroll() { // TODO Auto-generated method stub super.computeScroll(); if (mOrientation== mVertical) { if (mScroller.computeScrollOffset()) { scrollTo(0, mScroller.getCurrY()); postInvalidate(); } else { int position = getScrollY() / mScreenHeight; if (position != currentPage) { if (mOnPageChangeListener != null) { currentPage = position; mOnPageChangeListener.onPageChange(currentPage); } } } } else if (mOrientation== mHorientation) { if (mScroller.computeScrollOffset()) { scrollTo(mScroller.getCurrX(), 0); postInvalidate(); } else { int position = getScrollX() / mScreenWidth; if (position != currentPage) { if (mOnPageChangeListener != null) { currentPage = position; mOnPageChangeListener.onPageChange(currentPage); } } } } isScrolling = false; } /************************************ Method *********************************************/ /** * 獲取屏幕寬高 */ public void initialScreen(Context context) { WindowManager mWindowManager = (WindowManager) context .getSystemService(Context.WINDOW_SERVICE); DisplayMetrics outMetrics = new DisplayMetrics(); mWindowManager.getDefaultDisplay().getMetrics(outMetrics); mScreenWidth = outMetrics.widthPixels; mScreenHeight = outMetrics.heightPixels; } /** * 初始化加速度檢測器 * * @param event */ private void initialVelocity(MotionEvent event) { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } mVelocityTracker.addMovement(event); } /** * 初始化scrollX scrollY */ private void getStartScrollXY(){ mScrollStartPoint.x = getScrollX(); mScrollStartPoint.y = getScrollY(); } /** * 停止滑動後的ScrollX ScrollY */ private void getStopScrollXY(){ mScrollStopPoint.x = getScrollX(); mScrollStopPoint.y = getScrollY(); } /** * 比較滑動的ScrollX ScrollY差值 */ private void getDistanceScrollXY(){ mDistanceScrollPoint.x = mScrollStopPoint.x-mScrollStartPoint.x; mDistanceScrollPoint.y = mScrollStopPoint.y-mScrollStartPoint.y; } /** * 檢查滑動方向 * @return true 加載更多 false 刷新 */ public boolean checkDirection(){ boolean mDirection =false; if (mOrientation == mVertical) { mDirection = mDistanceScrollPoint.y > 0 ? true : false; } else if (mOrientation== mHorientation) { mDirection = - mDistanceScrollPoint.x < 0 ? true : false; } return mDirection; } /** * 根據滑動距離判斷 是否能夠滑動到下一屏 * 加載跟多 * @return */ private boolean isScrollToNext() { boolean isScrollTo = false; if (mOrientation == mVertical) { isScrollTo = mDistanceScrollPoint.y > mScreenHeight / 2 || Math.abs(getVelocity()) > 600; } else if (mOrientation == mHorientation) { isScrollTo = mDistanceScrollPoint.x > mScreenWidth / 2 || Math.abs(getVelocitx()) > 600; } return isScrollTo; } /** * 根據滑動距離判斷 是否能夠滑動到上一屏 * 刷新 * @return */ private boolean isScrollToprivew() { boolean isScrollTo = false; if (mOrientation == mVertical) { isScrollTo = -mDistanceScrollPoint.y > mScreenHeight / 2 || Math.abs(getVelocity()) > 600; } else if (mOrientation == mHorientation) { isScrollTo = -mDistanceScrollPoint.x > mScreenWidth / 2 || Math.abs(getVelocitx()) > 600; } return isScrollTo; } /** * 獲取x方向的加速度 * * @return */ private int getVelocitx() { mVelocityTracker.computeCurrentVelocity(1000); int velocitx = (int) mVelocityTracker.getXVelocity(1000); velocitx = (int) mVelocityTracker.getXVelocity(1000); return velocitx; } /** * 獲取y方向的加速度 * * @return */ private int getVelocity() { mVelocityTracker.computeCurrentVelocity(1000); int velocity = (int) mVelocityTracker.getYVelocity(1000); velocity = (int) mVelocityTracker.getYVelocity(1000); return velocity; } /** * 釋放資源 */ private void recycleVelocity() { if (mVelocityTracker != null) { mVelocityTracker.recycle(); mVelocityTracker = null; } } /** * 設置回調接口 * * @param onPageChangeListener */ public void setOnPageChangeListener( OnPageChangeListener onPageChangeListener) { mOnPageChangeListener = onPageChangeListener; } /** * 回調接口 * * @author zhy * */ public interface OnPageChangeListener { void onPageChange(int currentPage); } }
本文實例講述了Android編程實現調用系統圖庫與裁剪圖片功能。分享給大家供大家參考,具體如下:在Android開發中,調用系統圖庫和裁剪照片是很常見的需求。相對於自己實
File file = new File(“hah.txt”);//只是創建了一個對象file, file指向了hah.txt這個文件,hah.t
很多無線路由器都支持防蹭網,但想將那些蹭網設備踢出局的前提是,你要區分哪些設備是你的,哪些設備是別人的。然而,在路由器DHCP列表中所顯示的設備名稱卻多以一
引言布局是直接影響用戶體驗的關鍵部分。如果實現的不好,那麼布局很有可能會導致內存的緊張。Android的SDK包含的一些工具可以用來檢查布局性能上的問題。結合本章的課程學