最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義View實(shí)現(xiàn)角度選擇器

 更新時間:2016年11月06日 11:26:26   投稿:daisy  
前幾天在Google Photos查看照片,用了一下它的圖片剪裁功能,于是我馬上就被其界面和操作吸引。后來想模仿做一個和Google Photos裁圖頁面幾乎一模一樣的角度選擇器,本文比較基礎(chǔ),在閱讀本文前只需要掌握最基礎(chǔ)的自定義View知識和Android事件知識。下面來一起學(xué)習(xí)下吧。

首先來看一下Google Photos的效果

實(shí)現(xiàn)最終的效果:

實(shí)現(xiàn)思路

仔細(xì)觀察這個效果,先分析構(gòu)成結(jié)構(gòu),我把它分成三部分:

    1、表示刻度的點(diǎn)

    2、相應(yīng)點(diǎn)上方的數(shù)字

    3、控件中央的當(dāng)前刻度與三角

可以看出,構(gòu)成元素十分簡單,不涉及圖片,Drawable,那么只需要用Canvas畫出來就好了。

接下來觀察手勢的操作,查看隨著手指滑動,控件做出的變化,這里的變化有:

     1、手指按上去時,部分區(qū)域變亮(部分區(qū)域即為可見區(qū)域)

     2、隨著手指滑動,相應(yīng)的數(shù)字發(fā)生移動,當(dāng)前角度值也發(fā)生改變

     3、離中心越近,透明度越低,且0°的下方的點(diǎn)要大一些

好了,我們對這個控件已經(jīng)分析的很透徹了,根據(jù)分析,首先我們要在View的onDraw()方法中畫出構(gòu)成元素,之后要讓它動起來,在onTouchEvent()方法中監(jiān)聽手勢,改變一些值并重繪我們的View,這里很明顯,我們要改變的肯定是當(dāng)前角度這個值。

動手

既然有了思路,那么就要馬上動手,不然下次忘記掉了怎么辦?

畫點(diǎn)

首先,先把點(diǎn)給畫出來,位置很簡單,肯定是從視圖中心開始畫,往左往右分別畫點(diǎn)。

for (int i = 0; i < mPointCount; i++) {
 canvas.getClipBounds(mCanvasClipBounds);
 canvas.drawPoint(mCanvasClipBounds.centerX() + (i - mPointCount / 2) * mPointMargin,
     mCanvasClipBounds.centerY(), mPointPaint);
}

其中mPointCount為所要畫的點(diǎn)個數(shù),這里默認(rèn)為51個,mPointMargin為兩點(diǎn)間的邊距,長度為View的寬度除以點(diǎn)的個數(shù)。

看看效果

嗯,成功的把點(diǎn)給畫出來了。

畫刻度上方的數(shù)字

既然把點(diǎn)給畫出來了,根據(jù)我們的思路,我們要把數(shù)字給畫到正確的位置上,畫數(shù)字當(dāng)然很簡單,這里難的是找到正確的位置。

首先,我們的數(shù)字是會移動的,隨著當(dāng)前角度的不同,所展示的數(shù)字大小位置都不同。但毫無疑問的是,這個位置(x坐標(biāo))肯定是關(guān)于當(dāng)前角度的一個函數(shù)。至于具體是一個什么樣的函數(shù),相信聰明的你很快就可以分析出來,畢竟只是一個線性關(guān)系,這里就直接貼代碼了。

private void drawDegreeText(int degrees, Canvas canvas, boolean canReach) {
 canvas.drawText(degrees + "°",
    getWidth() / 2 + mPointMargin * degrees / 2 - mTextWidths[0] / 2 * 3 - mCurrentDegrees / 2 * mPointMargin,
     getHeight() / 2 - 10,
     mTextPaint);
 }
}

按照我們的效果,我們需要畫出-90°~90°的刻度,其中-45°~45°是可到達(dá)角度,另外的角度不可到達(dá)。

drawDegreeText(0, canvas, true);
drawDegreeText(15, canvas, true);
drawDegreeText(30, canvas, true);
drawDegreeText(45, canvas, true);
drawDegreeText(-15, canvas, true);
drawDegreeText(-30, canvas, true);
drawDegreeText(-45, canvas, true);

drawDegreeText(60, canvas, false);
drawDegreeText(75, canvas, false);
drawDegreeText(90, canvas, false);
drawDegreeText(-60, canvas, false);
drawDegreeText(-75, canvas, false);
drawDegreeText(-90, canvas, false);

好了,來看一下效果,可以看到,數(shù)字被畫在了正確的位置。

畫當(dāng)前角度

這個超級簡單呢,位置也特別好確定,上方三角形的Path也非常好知道,但是這里要注意的是,當(dāng)當(dāng)前角度為0°左右時,不應(yīng)該把0°刻度顯示出來。

//畫當(dāng)前角度
if (mCurrentDegrees >= 10) {
 canvas.drawText(mCurrentDegrees + "°", getWidth() / 2 - mTextWidths[0], mBaseLine, mTextPaint);
} else if (mCurrentDegrees <= -10) {
 canvas.drawText(mCurrentDegrees + "°", getWidth() / 2 - mTextWidths[0] / 2 * 3, mBaseLine, mTextPaint);
} else if (mCurrentDegrees < 0) {
 canvas.drawText(mCurrentDegrees + "°", getWidth() / 2 - mTextWidths[0], mBaseLine, mTextPaint);
} else {
 canvas.drawText(mCurrentDegrees + "°", getWidth() / 2 - mTextWidths[0] / 2, mBaseLine, mTextPaint);
}

//三角指示器的Path
mIndicatorPath.moveTo(w / 2, h / 2 + mFontMetrics.top / 2 - 18);
mIndicatorPath.rLineTo(-8, -8);
mIndicatorPath.rLineTo(16, 0);

還有一個小細(xì)節(jié),就是離中心越近,其透明度越來越低,也就是說,我們要根據(jù)離中心的位置,來改變畫筆Paint的alpha值,再將點(diǎn)畫出。

 for (int i = 0; i < mPointCount; i++) {

  if (i > zeroIndex - 22 && i < zeroIndex + 22 && mScrollStarted) {
   mPointPaint.setAlpha(255);
  } else {
   mPointPaint.setAlpha(100);
  }

  if (i > mPointCount / 2 - 8 && i < mPointCount / 2 + 8
    && i > zeroIndex - 22 && i < zeroIndex + 22) {
   if (mScrollStarted)
    mPointPaint.setAlpha(Math.abs(mPointCount / 2 - i) * 255 / 8);
   else
    mPointPaint.setAlpha(Math.abs(mPointCount / 2 - i) * 100 / 8);
  }
  ……
 }

這時,已經(jīng)很像了,只是還不能動。

動起來

該繪制的部分我們已經(jīng)都繪制起來了,是時候讓這個View動起來了,角度選擇器的觸摸事件不復(fù)雜,我們只需要在我們移動手指的時候根據(jù)滑動距離來改變當(dāng)前角度值并重繪視圖就可以看到移動效果了。為什么呢?因?yàn)槲覀冎霸诋嫈?shù)字的時候,位置都是由當(dāng)前角度這個值決定的,所以它一發(fā)生變化,數(shù)字的位置也會發(fā)生改變。

@Override
public boolean onTouchEvent(MotionEvent event) {
 switch (event.getAction()) {
  ……
  case MotionEvent.ACTION_MOVE:
   float distance = event.getX() - mLastTouchedPosition;
   ……
   if (distance != 0) {
    onScrollEvent(event, distance);
   }
   break;
  }
  ……
  return true;
}

private void onScrollEvent(MotionEvent event, float distance) {
 mTotalScrollDistance -= distance;
 postInvalidate();
 mLastTouchedPosition = event.getX();
 mCurrentDegrees = (int) ((mTotalScrollDistance * mDragFactor) / mPointMargin);
 if (mScrollingListener != null) {
  mScrollingListener.onScroll(mCurrentDegrees);
 }
}

當(dāng)然你還需要處理一些細(xì)節(jié)性的東西,比如在數(shù)字移動的時候,靠近中心一定范圍就會消失(透明度變?yōu)?),這些都是很容易控制的,只要改變畫筆的透明度就好了,但是正是對細(xì)節(jié)的把控,才能做出一個效果讓用戶滿意的自定義View。最后,再來看一下效果。

擴(kuò)展

到這里,我們做的角度選擇器已經(jīng)和Google Photos的幾乎一模一樣了,但是,僅僅這樣就夠了。不,不夠,我們還要繼續(xù)擴(kuò)展,為什么只能達(dá)到正負(fù)45°,我們要所有的范圍自由選擇,也就是-180°~180°,然后數(shù)字顏色啊,點(diǎn)的顏色啊都要讓人自由選擇。所以我們要擴(kuò)展我們的角度選擇器,把一切可以變化的接口暴露出來。

最后看一下我們多種多樣的角度選擇器,還是挺好看呀~

總結(jié)

以上就是這篇文章的全部內(nèi)容了,這次的自定義View相對于前兩次的來說,無疑是簡單了很多,只運(yùn)用了最基礎(chǔ)的繪圖知識和事件機(jī)制,但是看起來效果也還不錯哦,嘿嘿,反正我特別喜歡這個角度選擇器,雖然我還不知道除了裁圖頁面可以用到還有哪里可以用到。所以說運(yùn)用最簡單的知識,也可以組合出比較復(fù)雜的效果,希望大家多發(fā)揮自己的想象力,一起自定義出更多好玩的,實(shí)用的,酷炫的控件吧。希望這篇文章對你有幫助,哪怕只是一些啟發(fā),也是值得的。如果有疑問大家也可以留言交流。

相關(guān)文章

  • Android中顏色選擇器和改變字體顏色的實(shí)例教程

    Android中顏色選擇器和改變字體顏色的實(shí)例教程

    這篇文章主要介紹了Android中顏色選擇器和改變字體顏色的實(shí)例教程,其中改變字體顏色用到了ColorPicker顏色選擇器,需要的朋友可以參考下
    2016-04-04
  • Android 自定義彈出菜單和對話框功能實(shí)例代碼

    Android 自定義彈出菜單和對話框功能實(shí)例代碼

    Android 開發(fā)當(dāng)中,可能會存在許多自定義布局的需求,比如自定義彈出菜單(popupWindow),以及自定義對話框(Dialog)。下面通過本文給大家介紹Android 自定義彈出菜單和對話框功能實(shí)例代碼,感興趣的朋友一起看看吧
    2017-08-08
  • Flutter監(jiān)聽當(dāng)前頁面可見與隱藏狀態(tài)的代碼詳解

    Flutter監(jiān)聽當(dāng)前頁面可見與隱藏狀態(tài)的代碼詳解

    文章介紹了如何在Flutter中使用路由觀察者來監(jiān)聽?wèi)?yīng)用進(jìn)入前臺或后臺狀態(tài)以及頁面的顯示和隱藏,并通過代碼示例講解的非常詳細(xì),需要的朋友可以參考下
    2025-03-03
  • Android橫豎屏幕切換生命周期詳解

    Android橫豎屏幕切換生命周期詳解

    這篇文章主要為大家詳細(xì)介紹了Android橫豎屏幕切換生命周期,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android shape標(biāo)簽使用方法介紹

    Android shape標(biāo)簽使用方法介紹

    shape算是我們常用的一個標(biāo)簽,他可以生成線條,矩形, 圓形, 圓環(huán),像我們圓角的按鈕就可以通過shape來實(shí)現(xiàn),最終Android會把這個帶有shape標(biāo)簽的圖片解析成一個Drawable對象,這個Drawable對象本質(zhì)是GradientDrawable
    2022-09-09
  • Android自定義View仿騰訊TIM下拉刷新View

    Android自定義View仿騰訊TIM下拉刷新View

    這篇文章主要給大家介紹了關(guān)于Android自定義View仿騰訊TIM下拉刷新View的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-01-01
  • Android中圖片壓縮方案詳解及源碼下載

    Android中圖片壓縮方案詳解及源碼下載

    這篇文章主要介紹了Android中圖片壓縮方案詳解及源碼下載的相關(guān)資料,需要的朋友可以參考下
    2017-03-03
  • Android中使用Bitmap類將矩形圖片轉(zhuǎn)為圓形的方法

    Android中使用Bitmap類將矩形圖片轉(zhuǎn)為圓形的方法

    這篇文章主要介紹了Android中使用Bitmap類將矩形圖片轉(zhuǎn)為圓形的方法,同時文中也介紹了如何利用矩形直接來畫圓角,需要的朋友可以參考下
    2016-03-03
  • Flutter?Ping檢查服務(wù)器通訊信號強(qiáng)度實(shí)現(xiàn)步驟

    Flutter?Ping檢查服務(wù)器通訊信號強(qiáng)度實(shí)現(xiàn)步驟

    這篇文章主要為大家介紹了Flutter?Ping檢查服務(wù)器通訊信號強(qiáng)度實(shí)現(xiàn)步驟詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • 基于Android-Skin-Loader實(shí)現(xiàn)換膚效果

    基于Android-Skin-Loader實(shí)現(xiàn)換膚效果

    這篇文章主要為大家詳細(xì)介紹了基于Android-Skin-Loader實(shí)現(xiàn)換膚效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03

最新評論

汨罗市| 新龙县| 蒙山县| 黄山市| 自贡市| 岢岚县| 陆河县| 扎赉特旗| 大同市| 隆子县| 马公市| 忻州市| 仙桃市| 会东县| 垣曲县| 新乐市| 富阳市| 台前县| 黑水县| 府谷县| 奇台县| 阜平县| 海淀区| 晋中市| 友谊县| 嘉兴市| 台州市| 鹤岗市| 高雄县| 合水县| 聂荣县| 梅州市| 马山县| 延寿县| 通州区| 潞西市| 治县。| 孟津县| 绩溪县| 锡林郭勒盟| 常德市|