色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

基于安卓的滑動拼圖驗(yàn)證組件實(shí)現(xiàn)鴻蒙化遷移和重構(gòu)

OpenHarmony技術(shù)社區(qū) ? 來源:鴻蒙技術(shù)社區(qū) ? 作者:朱偉ISRC ? 2021-11-01 14:23 ? 次閱讀

基于安卓平臺的滑動拼圖驗(yàn)證組件 SwipeCaptcha,實(shí)現(xiàn)了鴻蒙化遷移和重構(gòu),代碼已經(jīng)開源,目前已經(jīng)獲得了很多人的 Star 和 Fork ,歡迎各位下載使用并提出寶貴意見!

開源地址:
https://gitee.com/isrc_ohos/swipe-captcha_ohos

在頁面登錄或者注冊的時(shí)候,為了確保不是機(jī)器人操作,會讓用戶手動驗(yàn)證。

驗(yàn)證方式分為滑動拼圖驗(yàn)證和滑動驗(yàn)證兩種:

  • 滑動拼圖驗(yàn)證:有圖片作為背景,通過圖塊拼接實(shí)現(xiàn)安全驗(yàn)證。

  • 滑動驗(yàn)證:無圖片背景,只拖動滑塊便可實(shí)現(xiàn)安全驗(yàn)證。

本文的 SwipeCaptcha_ohos2.0 組件屬于滑動拼圖驗(yàn)證,操作簡單,安全性強(qiáng),可被應(yīng)用于各種網(wǎng)站的登錄、注冊、找回密碼或投票等場景中。

我們之前已經(jīng)實(shí)現(xiàn)了滑動拼圖驗(yàn)證組件 SwipeCaptcha_ohos,相關(guān)文章可查看《鴻蒙頁面滑動組件,代碼已開源!》 。

本次 SwipeCaptcha_ohos2.0 是基于之前移植的項(xiàng)目進(jìn)行了相關(guān)功能的優(yōu)化,具體優(yōu)化內(nèi)容將在下文中詳細(xì)介紹。

組件效果展示

SwipeCaptcha_ohos2.0 的主要功能和之前的 SwipeCaptcha_ohos 基本一致,組件在使用時(shí),有兩個(gè)較為重要的元素:滑塊和原圖。

二者被放置于同一水平線上,用戶拖動滑塊至原圖處使二者重合,誤差小于提前設(shè)定的驗(yàn)證閾值,即可驗(yàn)證成功。每次調(diào)用組件,滑塊和原圖的位置都會發(fā)生隨機(jī)變化。

SwipeCaptcha_ohos2.0 相較于之前的版本,大幅提升了組件功能的完整性以及使用體驗(yàn)。

下面將依次從組件驗(yàn)證失敗和驗(yàn)證成功兩個(gè)狀態(tài),展示 SwipeCaptcha_ohos2.0 與之前版本的效果對比。

①驗(yàn)證失敗

通過圖 1(a) 和圖 1(b) 的對比可以看出,新版本移除了舊版本中“當(dāng)前進(jìn)度值預(yù)覽”的不必要功能以及下方的狀態(tài)欄。

取而代之的功能如下:
  • 驗(yàn)證滑塊由正方形小塊升級為“拼圖塊”樣式。

  • 待驗(yàn)證背景圖塊增加了陰影遮罩效果。

  • 驗(yàn)證失敗后增加了滑塊閃爍效果以及“驗(yàn)證失敗,請重新驗(yàn)證!”的彈窗提醒。

②驗(yàn)證成功

通過圖 2(a) 和圖 2(b) 的對比可以看出,新版本移除了舊版本中“當(dāng)前進(jìn)度值預(yù)覽”的不必要功能以及下方的狀態(tài)欄。

取而代之的功能如下:
  • 點(diǎn)擊“重新生成驗(yàn)證碼”按鈕后,滑塊和原圖的位置都會發(fā)生隨機(jī)變化。

  • 驗(yàn)證成功后增加了反光條劃過的動畫效果以及“驗(yàn)證成功!”的彈窗提醒。

除了上述直觀的功能優(yōu)化外,SwipeCaptcha_ohos2.0 還實(shí)現(xiàn)了以下功能:
  • 滑塊大小和容錯閾值的用戶自定義:滑塊大小自定義是指用戶可以通過代碼自定義滑塊的寬高;容錯閾值自定義是指用戶可以通過代碼自定義匹配時(shí)的容錯率,即相差多少視作匹配成功。

  • 拼圖背景在指定范圍內(nèi)的自適應(yīng)填充:原組件的圖片不能在指定組件寬高的前提下自動填充圖片,如果強(qiáng)行適配寬高會出現(xiàn)拼圖塊內(nèi)容錯位的情況;經(jīng)過改進(jìn)后,驗(yàn)證圖片已經(jīng)能夠適配布局中規(guī)定的組件寬高。

Sample 解析

通過上文相信大家已經(jīng)了解 SwipeCaptcha_ohos2.0 組件的使用效果,下面將具體講解 SwipeCaptcha_ohos2.0 組件的使用方法。

共分為如下 5 個(gè)步驟:
  • 步驟 1:導(dǎo)入 SwipeCaptchaView 類并聲明類對象。

  • 步驟 2:在 xml 文件中添加 SwipeCaptchaView 控件。

  • 步驟 3:綁定 SwipeCaptchaView 控件。

  • 步驟 4:設(shè)置回調(diào)處理函數(shù)。

  • 步驟 5:設(shè)置 Button 控件監(jiān)聽事件,重新生成驗(yàn)證區(qū)域。

①導(dǎo)入 SwipeCaptchaView 類并聲明類對象

在 MainAbilitySlice.java 文件中,通過 import 關(guān)鍵字導(dǎo)入 SwipeCaptchaView 類。

//導(dǎo)入SwipeCaptchaView類
importcom.huawei.swipecaptchaview.lib.SwipeCaptchaView;
publicclassMainAbilitySliceextendsAbilitySlice{
//聲明SwipeCaptchaView類對象
SwipeCaptchaViewswipeCaptchaView;
......
}

②在 xml 文件中添加 SwipeCaptchaView 控件

在 xml 文件中添加 SwipeCaptchaView 控件,用于顯示滑動驗(yàn)證的背景圖和動態(tài)效果。設(shè)置控件高和寬、滑塊的高和寬以及驗(yàn)證閾值等屬性。

"http://schemas.huawei.com/res/ohos-auto"//聲明一個(gè)用于傳輸自定義參數(shù)的命名空間
ohos:id="$+id:swipeCaptchaView"//規(guī)定控件id
ohos:height="220vp"//控件的高
ohos:width="330vp"//控件的寬
captcha:captchaHeight="30vp"//拼圖滑塊高
captcha:captchaWidth="30vp"//拼圖滑塊寬
captcha:matchDeviation="9"/>//驗(yàn)證失敗的閾值

③綁定 SwipeCaptchaView 控件

在 MainAbilitySlice.java 的 onStart() 方法中,使用 findComponentById() 方法將 xml 文件中 SwipeCaptchaView 控件與 SwipeCaptchaView 類對象綁定;再調(diào)用 setImageId() 方法設(shè)置組件的背景圖片。

//根據(jù)id找到相應(yīng)的控件
swipeCaptchaView=(SwipeCaptchaView)findComponentById(ResourceTable.Id_swipeCaptchaView);
...
button=(Button)findComponentById(ResourceTable.Id_btn_change);

//設(shè)置背景圖片
swipeCaptchaView.setImageId(ResourceTable.Media_pic01);

④設(shè)置回調(diào)處理函數(shù)

設(shè)置 SwipeCaptchaView 組件的回調(diào)處理函數(shù),來提示用戶滑動驗(yàn)證結(jié)果。

以提示用戶驗(yàn)證成功為例:首先重寫 matchSuccess() 方法,設(shè)置驗(yàn)證成功后的提示信息,然后實(shí)例化一個(gè) ToastDialog 提示框?qū)ο螅褂?setText() 方法設(shè)置顯示文字為“驗(yàn)證成功!”。

setAlignment() 方法設(shè)置提示框的布局位置在整體布局的中央;show() 方法用于顯示提示框。

設(shè)置驗(yàn)證失敗的情況和驗(yàn)證成功同理,只需重寫 matchFailed() 方法將文字信息設(shè)置為“驗(yàn)證失敗!”即可。

//每次滑動結(jié)束后會根據(jù)判定結(jié)果回調(diào)
swipeCaptchaView.setOnCaptchaMatchCallback(newSwipeCaptchaView.OnCaptchaMatchCallback(){
@Override
publicvoidmatchSuccess(SwipeCaptchaViewswipeCaptchaView){
newToastDialog(getContext())
.setText("驗(yàn)證成功!")
.setAlignment(LayoutAlignment.CENTER)
.show();
}
});

⑤設(shè)置 Button 控件監(jiān)聽事件,重新生成驗(yàn)證區(qū)域

綁定 button 對象和 xml 文件中“重新生成驗(yàn)證碼”Button控件;為 button 設(shè)置監(jiān)聽事件,每次點(diǎn)擊按鈕,都會調(diào)用 createCaptcha() 方法隨機(jī)生成滑塊和原圖的位置。

button=(Button)findComponentById(ResourceTable.Id_btn_change);//綁定Button
button.setClickedListener(newComponent.ClickedListener(){//設(shè)置監(jiān)聽
@Override
publicvoidonClick(Componentcomponent){
swipeCaptchaView.createCaptcha();//隨機(jī)生成滑塊和原圖的位置
...
}
});

Library解析

本部分將要重點(diǎn)介紹的類是圖 3 中框出的 2 個(gè)類,分別是 DrawHelperUtils 和 SwipeCaptchaView。

它們向開發(fā)者提供設(shè)置 SwipeCaptcha_ohos2.0 組件相關(guān)屬性的具體執(zhí)行方法,其中 DrawHelperUtils 是工具類,SwipeCaptchaView 是具體實(shí)現(xiàn)滑塊滑動效果的類,本節(jié)將分別講解這兩個(gè)類的內(nèi)部邏輯實(shí)現(xiàn)。

①DrawHelperUtils 類

Swipeptcha_ohos2.0 升級實(shí)現(xiàn)的拼圖滑塊的原理是在方塊的左、右兩條豎邊中點(diǎn)處分別繪制一個(gè)凸半圓或凹半圓(隨機(jī)),可參考圖 4。

DrawHelperUtils 類的 drawPartCircle() 方法具體用于繪制拼圖滑塊兩條豎邊上的半圓。

先來解釋一下該方法涉及變量和參數(shù)的含義:
  • 起點(diǎn)坐標(biāo):開始繪制半圓的起點(diǎn)坐標(biāo),在圖中由A表示,規(guī)定為方塊豎邊的前 1/3 處,由入?yún)魅搿?/span>

  • 終點(diǎn)坐標(biāo):開始繪制半圓的起點(diǎn)坐標(biāo),在圖中由 C 表示,規(guī)定為方塊豎邊的后 1/3 處,由入?yún)魅搿?/span>

  • 中點(diǎn)坐標(biāo):半圓直徑的中點(diǎn)坐標(biāo),在圖中由 B 表示,由起點(diǎn) A 和終點(diǎn) C 的 X、Y 坐標(biāo)計(jì)算得到。

  • r1:半圓半徑 = AB 長度 = AC 長度/2 = 1/6 方塊豎邊長度。

  • gap1:由 r1 乘以貝塞爾曲線(cubicTo() 方法)系數(shù) c 得到,用于確定控制點(diǎn) D 和 F 的坐標(biāo),控制點(diǎn)作用是控制半圓繪制的軌跡。

  • flag:半圓的旋轉(zhuǎn)系數(shù),用來控制凹、凸半圓的繪制。當(dāng)為 1 時(shí),A、B、C 坐標(biāo)與變量相加,繪制向外的凸半圓;當(dāng)為 -1 時(shí),其坐標(biāo)與變量相減,得到向內(nèi)的凹半圓。

以豎直繪制一個(gè)凸半圓為例,根據(jù) A、B、C 點(diǎn)計(jì)算得到上述變量后,調(diào)用兩次貝塞爾曲線 cubicTo(x1,y1,x2,y2,x3,y3)分別繪制前 1/2 和后 1/2 半圓。

此方法中需要使用到兩個(gè)控制點(diǎn),共有 6 個(gè)參數(shù),分別表示控制點(diǎn) 1(x1,y1)、控制點(diǎn) 2(x2,y2)和繪制終點(diǎn)(x3,y3)。

如圖 4-1,繪制前 1/2 半圓時(shí)以起點(diǎn) A 右側(cè)平行 gap1flag1 距離處作為第一個(gè)控制點(diǎn) D、中點(diǎn) B 右側(cè)平行 r1 距離的半圓頂點(diǎn)第二個(gè)控制點(diǎn) E、中點(diǎn) B 作為繪制終點(diǎn)。

繪制后 1/2 半圓同理,以 E 點(diǎn)作為第一個(gè)控制點(diǎn),終點(diǎn) C 右側(cè)平行 gap1flag1 距離處作為第二個(gè)控制點(diǎn) F、終點(diǎn) C 作為繪制終點(diǎn)。

其他繪制方向同理,若為從下向上繪制,則將 flag 設(shè)為 -1;若繪制凹半圓,則在計(jì)算坐標(biāo)時(shí)橫坐標(biāo)反方向計(jì)算即可可參考圖 4-2。

publicstaticvoiddrawPartCircle(Pointstart,Pointend,Pathpath,booleanouter){
floatc=0.551915024494f;
Pointmiddle=newPoint(start.getPointX()+(end.getPointX()-start.getPointX())/2,start.getPointY()+(end.getPointY()-start.getPointY())/2);//根據(jù)起點(diǎn)坐標(biāo)A和終點(diǎn)坐標(biāo)C算出中點(diǎn)B坐標(biāo)
//半徑
floatr1=(float)Math.sqrt(Math.pow((middle.getPointX()-start.getPointX()),2)+Math.pow((middle.getPointY()-start.getPointY()),2));
floatgap1=r1*c;//距離gap

if(start.getPointX()==end.getPointX()){//繪制豎直方向
booleantopToBottom=end.getPointY()-start.getPointY()>0;
intflag;//旋轉(zhuǎn)系數(shù)
if(topToBottom){//若從上到下繪制
flag=1;//旋轉(zhuǎn)系數(shù)設(shè)為1
}else{flag=-1;}//若從下到上繪制,設(shè)為-1
if(outer){//若為凸半圓,相加
path.cubicTo(start.getPointX()+gap1*flag,start.getPointY(),middle.getPointX()+r1*flag,middle.getPointY()-gap1*flag,middle.getPointX()+r1*flag,middle.getPointY());
path.cubicTo(middle.getPointX()+r1*flag,middle.getPointY()+gap1*flag,end.getPointX()+gap1*flag,end.getPointY(),end.getPointX(),end.getPointY());
}...}//若為凹半圓,則相減
}

②SwipteCaptchaView 類

SwipeCaptchaView 是具體實(shí)現(xiàn)滑塊滑動效果的類,下文將從初始化滑動條并設(shè)置滑動條監(jiān)聽、初始化驗(yàn)證區(qū)域背景、設(shè)置驗(yàn)證后的動畫效果、生成滑動驗(yàn)證區(qū)域四個(gè)方面具體講解實(shí)現(xiàn)邏輯。

接下來將按類型講解類中各方法間的調(diào)用邏輯,可參考圖 4:

①初始化滑動條并設(shè)置滑動條監(jiān)聽

在 SwipteCaptchaView 類的構(gòu)造函數(shù)中,調(diào)用 init() 方法進(jìn)行初始化。其中,獲取 xml 文件中控件參數(shù)即寬、高和系統(tǒng)屏幕寬度;通過 switch-case 判斷來獲取滑塊的寬、高和滑動誤差值。

mHeight=getHeight();//獲取控件高和款
mWidth=getWidth();//獲取系統(tǒng)屏幕寬度
if(mWidth==0){//mWidth=0為設(shè)置了match_parent的情況
mWidth=DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes().width;
}

for(inti=0;iattr=attrSet.getAttr(i);
if(attr.isPresent()){
switch(attr.get().getName()){
case"captchaHeight"://獲取滑塊高度
mCaptchaHeight=attr.get().getDimensionValue();
break;
case"captchaWidth"://獲取滑塊寬度
...
case"matchDeviation"://獲取滑動誤差值
...
}
}
}

實(shí)例化 Image 類得到驗(yàn)證區(qū)域圖片對象,并為其設(shè)置圖片縮放模式以及位圖格式等屬性;實(shí)例化 Slider 類得到拖動條對象,為其設(shè)置寬、高、進(jìn)度值、進(jìn)度顏色等屬性,以及監(jiān)聽事件。

mImage=newImage(context);//表示驗(yàn)證區(qū)域圖片
...
mImage.setScaleMode(Image.ScaleMode.CLIP_CENTER);
mImage.setPixelMap(ResourceTable.Media_no_resource);
...
mSlider=newSlider(mLayout.getContext());//實(shí)例化Slider類表示拖動條
mSlider.setWidth(mWidth);//設(shè)置寬、高
mSlider.setHeight(SLIDER_HEIGHT);
mSlider.setMarginTop(mHeight-SLIDER_HEIGHT);
mSlider.setMinValue(0);//進(jìn)度最小、最大值、當(dāng)前進(jìn)度值、進(jìn)度顏色
mSlider.setMaxValue(10000);
mSlider.setProgressValue(0)
mSlider.setProgressColor(Color.BLACK);
setSlideListener();//設(shè)置拖動條的監(jiān)聽事件
...

在拖動條監(jiān)聽事件 setSlideListener() 方法中,重寫 onTouchEnd() 方法,判斷滑動結(jié)束后滑塊位置的誤差值是否小于規(guī)定誤差值。

若小于則驗(yàn)證成功,取消滑塊的陰影并設(shè)置回調(diào);否則驗(yàn)證失敗,直接設(shè)置回調(diào)。

@Override
publicvoidonTouchEnd(Sliderslider){
if(onCaptchaMatchCallback!=null){
if(Math.abs(mSlider.getProgress()*(mWidth-mCaptchaWidth)/10000-mCaptchaX)//滑動結(jié)束后滑塊位置誤差值小于規(guī)定誤差值驗(yàn)證成功
mCaptchaPaint.setMaskFilter(null);//取消滑塊的陰影
slider.setEnabled(false);
onCaptchaMatchCallback.matchSuccess(SwipeCaptchaView.this);//設(shè)置驗(yàn)證成功后的回調(diào)
mSuccessAnim.start();//播放驗(yàn)證成功動畫
}else{//滑動誤差值大于規(guī)定誤差值驗(yàn)證失敗
slider.setProgressValue(0);
onCaptchaMatchCallback.matchFailed(SwipeCaptchaView.this);//設(shè)置驗(yàn)證失敗后的回調(diào)
mFailAnim.start();//播放驗(yàn)證失敗動畫
}
}
}

②初始化滑動驗(yàn)證區(qū)域

在通過 Image 類對象調(diào)用 setPixelMap() 方法設(shè)置完驗(yàn)證圖片后,由 initCaptcha() 方法完成驗(yàn)證區(qū)域的初始化。 實(shí)例化兩個(gè) Paint 類分別得到畫筆對象和滑塊目標(biāo)區(qū)域?qū)ο螅瑸槠湓O(shè)置畫筆抗鋸齒和陰影、滑塊樣式和顏色等屬性。

再分別調(diào)用 createMatchAnim() 和 createCaptcha() 方法設(shè)置驗(yàn)證后的動畫效果和生成滑動驗(yàn)證區(qū)域。

privatevoidinitCaptcha(){
mRandom=newRandom(System.nanoTime());
//設(shè)置畫筆
mCaptchaPaint=newPaint();//畫筆對象
mCaptchaPaint.setAntiAlias(true);//抗鋸齒
mCaptchaPaint.setDither(true);//使位圖進(jìn)行有利的抖動的位掩碼標(biāo)志
mCaptchaPaint.setStyle(Paint.Style.FILL_STYLE);
mCaptchaPaint.setMaskFilter(newMaskFilter(10,MaskFilter.Blur.SOLID));//陰影
//滑塊目標(biāo)區(qū)域
mMaskPaint=newPaint();//滑塊目標(biāo)區(qū)域?qū)ο?/span>
mMaskPaint.setAntiAlias(true);
mMaskPaint.setDither(true);
mMaskPaint.setStyle(Paint.Style.FILL_STYLE);//填充樣式
mMaskPaint.setColor(newColor(Color.argb(188,0,0,0)));//填充顏色
mMaskPaint.setMaskFilter(newMaskFilter(20,MaskFilter.Blur.INNER));//陰影
mCaptchaPath=newPath();

createMatchAnim();//設(shè)置驗(yàn)證后的動畫效果
createCaptcha();//生成驗(yàn)證碼區(qū)域
}

③設(shè)置驗(yàn)證后的動畫效果

由 createMatchAnim() 方法實(shí)現(xiàn),能夠設(shè)置驗(yàn)證成功或失敗后的動畫效果。

驗(yàn)證成功:通過 AnimatorValue 類對象設(shè)置動畫間隔時(shí)間為 500 毫秒;并為其設(shè)置當(dāng)值更新時(shí)的監(jiān)聽事件,重寫 onUpdate() 方法,設(shè)置成功動畫中拼圖的偏移量。

//成功動畫
intwidth=AttrHelper.vp2px(60,mLayout.getContext());
mSuccessAnim=newAnimatorValue();
mSuccessAnim.setDuration(500);//間隔時(shí)間為500毫秒
mSuccessAnim.setValueUpdateListener(newAnimatorValue.ValueUpdateListener(){
@Override//設(shè)置監(jiān)聽
publicvoidonUpdate(AnimatorValueanimatorValue,floatv){
mSuccessAnimOffset=(int)(v*(mWidth+width));//拼圖偏移量
invalidate();
}
});

通過 Paint 類和 Path 類對象分別調(diào)用相關(guān)函數(shù)來完成陰影效果和動畫路徑的繪制。

mSuccessPaint=newPaint();
mSuccessPaint.setShader(newLinearShader(//設(shè)置陰影
newPoint[]{newPoint(0,0),newPoint(width*3/2,mHeight)},
newfloat[]{0,0.5f},
newColor[]{newColor(0x00FFFFFF),newColor(0x66FFFFFF)},
Shader.TileMode.MIRROR_TILEMODE),Paint.ShaderType.LINEAR_SHADER);
mSuccessPath=newPath();//繪制動畫路徑
mSuccessPath.moveTo(0,0);
mSuccessPath.rLineTo(width,0);
mSuccessPath.rLineTo(width/2,mHeight-SLIDER_HEIGHT);
mSuccessPath.rLineTo(-width,0);
mSuccessPath.close();//關(guān)閉

驗(yàn)證失敗:與設(shè)置驗(yàn)證成功的前半部分流程相似,不同之處是將動畫間隔設(shè)為 200 毫秒、還要設(shè)置畫圈次數(shù)為 2 次。

在值更新時(shí)的監(jiān)聽事件中,需要判斷當(dāng)更新值小于 0.5f 時(shí),將 isDrawMask 置為 false 即不繪制滑塊,反之為 true 則繪制。

//設(shè)置驗(yàn)證失敗動畫
mFailAnim=newAnimatorValue();//實(shí)例化驗(yàn)證失敗的動畫對象
mFailAnim.setDuration(200);//設(shè)置間隔時(shí)間為200毫秒
mFailAnim.setLoopedCount(2);//設(shè)置畫圈次數(shù)為2次
mFailAnim.setValueUpdateListener(newAnimatorValue.ValueUpdateListener(){
@Override
publicvoidonUpdate(AnimatorValueanimatorValue,floatv){
if(v0.5f){
isDrawMask=false;//不繪制滑塊
}else{isDrawMask=true;}//繪制滑塊
invalidate();
}});
}

④生成滑動驗(yàn)證區(qū)域

由 createCaptcha() 方法實(shí)現(xiàn)。先調(diào)用 createCaptchaPath() 方法繪制拼圖塊的輪廓路徑。

其中通過 Random 類的 nextInt() 方法隨機(jī)生成驗(yàn)證區(qū)域坐標(biāo),使滑塊和原圖位置隨機(jī)變化。

再使用工具類 DrawHelperUtils 的 DrawPartCircle() 方法繪制拼圖塊左上角、右上角、右下角和左下角的圖形。

privatevoidcreateCaptchaPath(){//繪制拼圖塊輪廓路徑path
intgap=mCaptchaWidth/3;//拼圖缺口的位置,設(shè)置在中間1/3處
mCaptchaX=mRandom.nextInt(mWidth-(mCaptchaWidth*3)-gap)+(mCaptchaWidth*2);//隨機(jī)生成驗(yàn)證區(qū)域左上角的坐標(biāo)
mCaptchaY=mRandom.nextInt(mHeight-SLIDER_HEIGHT-mCaptchaHeight-gap);
mCaptchaPath.reset();
mCaptchaPath.lineTo(0,0);
//開始繪制圖形
mCaptchaPath.moveTo(mCaptchaX,mCaptchaY);//左上角
mCaptchaPath.lineTo(mCaptchaX+gap,mCaptchaY);
drawPartCircle(newPoint(mCaptchaX+gap,mCaptchaY),newPoint(mCaptchaX+gap*2,mCaptchaY),
mCaptchaPath,mRandom.nextBoolean());
...//右上角、右下角和左下角同理
mCaptchaPath.close();//繪制完成后及時(shí)關(guān)閉
}

接著生成滑動驗(yàn)證區(qū)域,前面介紹過,SwipeCaptcha_ohos2.0 版升級實(shí)現(xiàn)了驗(yàn)證區(qū)域背景圖片自適應(yīng)填充的效果。

其實(shí)現(xiàn)原理是先獲取位圖;根據(jù)圖片的寬高和控件實(shí)際的寬高分別計(jì)算出水平方向和豎直方向上的縮放比例,兩者中較大的是圖片真實(shí)的縮放比例。

這是由于上文介紹的 Image 控件將圖片縮放模式設(shè)為了 CLIP_CENTER,該模式會將圖片的短邊縮放至合適的大小并對長邊進(jìn)行裁剪。

因此較小的縮放比例代表被裁剪的邊,較大的即在填充進(jìn)控件時(shí)的真實(shí)縮放比例;接著繪制滑塊目標(biāo)區(qū)域的陰影,其不隨拖動條的移動而更新。

最后繪制滑塊區(qū)域,根據(jù)拖動條的數(shù)值計(jì)算畫布偏移量,調(diào)用 drawPath() 方法繪制邊框,獲取圖片 PixelMapHolder。

根據(jù)路徑裁剪并將畫布縮放至跟圖片縮放程度一致,根據(jù)比例計(jì)算出垂直方向上由于 CLIP_CENTER 裁剪掉的圖片的高度以及水平方向上被裁掉的寬度,即可繪制內(nèi)容。

publicvoidcreateCaptcha(){//生成驗(yàn)證區(qū)域
if(mImage.getPixelMap()!=null){
createCaptchaPath();//繪制拼圖塊輪廓路徑Path
...}

PixelMapmCaptchaPixelMap=mImage.getPixelMap();//getPixelMap(mLayout.getContext(),ResourceTable.Media_pic01);
//根據(jù)圖片的原寬度和控件寬度算出縮放比例
intoriginWidth=mCaptchaPixelMap.getImageInfo().size.width;
intoriginHeight=mCaptchaPixelMap.getImageInfo().size.height;
floatratioWidth=(float)mWidth/originWidth;
floatratioHeight=(float)(mHeight-SLIDER_HEIGHT)/originHeight;
floatratio=Math.max(ratioWidth,ratioHeight);//更大的ratio

mImage.addDrawTask((component,canvas)->{//滑塊目標(biāo)區(qū)域陰影的繪制
canvas.drawPath(mCaptchaPath,mMaskPaint);
});
mLayout.addDrawTask((component,canvas)->{//滑塊區(qū)域的繪制
if(isDrawMask){
canvas.translate(mSlider.getProgress()*(mWidth-mCaptchaWidth)/10000-mCaptchaX,0);//根據(jù)拖動條的數(shù)值計(jì)算畫布的偏移量
canvas.drawPath(mCaptchaPath,mCaptchaPaint);//繪制邊框
PixelMapHoldermCaptchaPixelMapHolder=newPixelMapHolder(mCaptchaPixelMap);//獲取圖片的PixelMapHolder
canvas.clipPath(mCaptchaPath,Canvas.ClipOp.INTERSECT);//根據(jù)路徑裁剪
canvas.scale(ratio,ratio);//畫布縮放至跟圖片縮放程度一致
if(ratio==ratioWidth){
floatheightErr=(originHeight*ratio-(mHeight-SLIDER_HEIGHT))/2;//根據(jù)比例計(jì)算出垂直方向上由于CLIP_CENTER裁剪掉的圖片的高度
canvas.drawPixelMapHolder(mCaptchaPixelMapHolder,0,-heightErr/ratio,mCaptchaPaint);//繪制內(nèi)容
}
else{
floatwidthErr=(originWidth*ratio-mWidth)/2;//根據(jù)比例計(jì)算出水平方向上由于CLIP_CENTER裁剪掉的圖片的寬度
canvas.drawPixelMapHolder(mCaptchaPixelMapHolder,-widthErr/ratio,0,mCaptchaPaint);//繪制內(nèi)容
}
}});
}
責(zé)任編輯:haq

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • 鴻蒙系統(tǒng)
    +關(guān)注

    關(guān)注

    183

    文章

    2636

    瀏覽量

    66468
  • HarmonyOS
    +關(guān)注

    關(guān)注

    79

    文章

    1980

    瀏覽量

    30291

原文標(biāo)題:鴻蒙滑動拼圖驗(yàn)證組件,已開源!

文章出處:【微信號:gh_834c4b3d87fe,微信公眾號:OpenHarmony技術(shù)社區(qū)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    鴻蒙原生頁面高性能解決方案上線OpenHarmony社區(qū) 助力打造高性能原生應(yīng)用

    全局自定義組件復(fù)用,讓原生容器組件組件復(fù)用子組件,降低了頁面丟幀率和白屏?xí)r間。這一方案已在多個(gè)頭部鴻蒙原生應(yīng)用中得到使用和
    發(fā)表于 01-02 18:00

    鴻蒙ArkTS容器組件:Swiper

    滑塊視圖容器,提供子組件滑動輪播顯示的能力。
    的頭像 發(fā)表于 07-15 09:51 ?690次閱讀
    <b class='flag-5'>鴻蒙</b>ArkTS容器<b class='flag-5'>組件</b>:Swiper

    鴻蒙ArkTS聲明式組件:TextPicker

    滑動選擇文本內(nèi)容的組件
    的頭像 發(fā)表于 07-03 15:07 ?533次閱讀
    <b class='flag-5'>鴻蒙</b>ArkTS聲明式<b class='flag-5'>組件</b>:TextPicker

    最新開源代碼證實(shí)!“鴻蒙原生版”微信正在積極開發(fā)中

    立刻保存,不需要同步或刷新調(diào)用。共享內(nèi)存一般用于后臺開發(fā)。 HarmonyOS NEXT 也就是鴻蒙星河版——俗稱“純血鴻蒙”,其采用華為自研內(nèi)核,拋棄了傳統(tǒng)的 Linux 內(nèi)核以及 AOSP
    發(fā)表于 05-08 17:08

    華為鴻蒙操作系統(tǒng)發(fā)展戰(zhàn)略:2024年完成安應(yīng)用全面遷移

    徐直軍指出,2024 年,鴻蒙操作系統(tǒng)的主要任務(wù)是打造原生應(yīng)用生態(tài)。目前,鴻蒙操作系統(tǒng)已基本適配各種終端設(shè)備,但在應(yīng)用開發(fā)方面仍依賴生態(tài)。
    的頭像 發(fā)表于 04-18 15:38 ?823次閱讀

    鴻蒙OS開發(fā)實(shí)例:【組件模式】

    組件一直是移動端比較流行的開發(fā)方式,有著編譯運(yùn)行快,業(yè)務(wù)邏輯分明,任務(wù)劃分清晰等優(yōu)點(diǎn),針對Android端的組件;與Android端的組件
    的頭像 發(fā)表于 04-07 17:44 ?672次閱讀
    <b class='flag-5'>鴻蒙</b>OS開發(fā)實(shí)例:【<b class='flag-5'>組件</b><b class='flag-5'>化</b>模式】

    深圳市24年,實(shí)現(xiàn)鴻蒙原生應(yīng)用數(shù)占全國總量10%以上

    操作系統(tǒng)。部分的高校已經(jīng)取消了課程,從而開設(shè)鴻蒙課程;企業(yè)紛紛跟進(jìn)啟動了鴻蒙研發(fā)。 并且鴻蒙是完全具備無與倫比的機(jī)遇和潛力的。
    發(fā)表于 03-04 21:42

    面對如今的就業(yè)環(huán)境,vs鴻蒙……

    對于鴻蒙如今的發(fā)展勢頭,可謂是如火如荼。無論是最近發(fā)布的鴻蒙操作系統(tǒng)HarmonyOS NEXT,摒棄了Linux內(nèi)核和AOSP開放源代碼項(xiàng)目的代碼, 不再兼容
    的頭像 發(fā)表于 03-01 15:49 ?609次閱讀
    面對如今的就業(yè)環(huán)境,<b class='flag-5'>安</b><b class='flag-5'>卓</b>vs<b class='flag-5'>鴻蒙</b>……

    沒有“成份“的鴻蒙還能行嗎?

    一、鴻蒙的前世今生 早前,就有關(guān)鴻蒙系統(tǒng)不兼容的消息引發(fā)了許多人的關(guān)注。由于2019年
    的頭像 發(fā)表于 02-26 13:56 ?503次閱讀
    沒有“<b class='flag-5'>安</b><b class='flag-5'>卓</b>成份“的<b class='flag-5'>鴻蒙</b>還能行嗎?

    華為鴻蒙系統(tǒng)怎么樣 華為鴻蒙系統(tǒng)和系統(tǒng)的區(qū)別

    和穩(wěn)定性。與此同時(shí),鴻蒙系統(tǒng)與系統(tǒng)在架構(gòu)、功能和生態(tài)系統(tǒng)方面都存在一些區(qū)別和特點(diǎn),下面將詳細(xì)探討這些方面的差異。 首先,華為鴻蒙系統(tǒng)在架構(gòu)上與
    的頭像 發(fā)表于 02-02 14:54 ?1799次閱讀

    鴻蒙OS和開源鴻蒙什么關(guān)系?

    內(nèi)核,其他功能都以模塊的形式存在。 ? ? 華為用的是鴻蒙OS 我們都知道,華為手機(jī)的鴻蒙OS是可以運(yùn)行軟件的,是因?yàn)橄到y(tǒng)中有
    的頭像 發(fā)表于 01-30 15:44 ?1171次閱讀
    <b class='flag-5'>鴻蒙</b>OS和開源<b class='flag-5'>鴻蒙</b>什么關(guān)系?

    鴻蒙ArkUI開發(fā)-Tabs組件的使用

    鴻蒙ArkUI開發(fā)-Tabs組件的使用
    的頭像 發(fā)表于 01-19 16:01 ?1957次閱讀
    <b class='flag-5'>鴻蒙</b>ArkUI開發(fā)-Tabs<b class='flag-5'>組件</b>的使用

    鴻蒙系統(tǒng)和的區(qū)別 鴻蒙系統(tǒng)有什么特別之處

    了分布式架構(gòu),可以在不同設(shè)備上實(shí)現(xiàn)無縫連接和協(xié)同工作。而系統(tǒng)采用的是集中式架構(gòu),設(shè)備之間的連接和協(xié)同工作相對較為困難。 鴻蒙系統(tǒng)具備高度靈活性和可擴(kuò)展性,支持設(shè)備與設(shè)備之間的直接通
    的頭像 發(fā)表于 01-18 11:45 ?1.2w次閱讀

    鴻蒙開發(fā)OpenHarmony組件復(fù)用案例

    復(fù)用能力。 環(huán)境準(zhǔn)備 準(zhǔn)備一個(gè)DevEco Studio,使用真機(jī)或者Simulator模擬器來驗(yàn)證組件復(fù)用接口 OpenHarmony SDK文件ets\\\\component
    發(fā)表于 01-15 17:37

    鴻蒙開發(fā)基礎(chǔ)-Web組件之cookie操作

    }) ... } ... 本文章主要是對鴻蒙開發(fā)當(dāng)中ArkTS語言的基礎(chǔ)應(yīng)用實(shí)戰(zhàn),Web組件里的cookie操作。更多的鴻蒙應(yīng)用開發(fā)技術(shù),可以前往我的主頁學(xué)習(xí)更多,下面是一張鴻蒙
    發(fā)表于 01-14 21:31
    主站蜘蛛池模板: 国产午夜精AV在线麻豆| 亚洲欧洲精品成人久久曰影片| 四虎视频最新视频在线观看| 伊人久久亚洲综合天堂| 动漫美女和男人下载| 久久视热频国只有精品| 手机在线国产视频| 91天堂国产在线 在线播放| 国产熟妇无码一区二| 秋霞电影网午夜一级鲁丝片| 一级片mp4| 国产免费播放一区二区三区| 欧美亚洲国产免费高清视频| 一本久道久久综合狠狠躁AV| 国产精品久久久久久久久齐齐| 女性BBWBBWBBWBBW| 一久久| 国产欧美一区二区精品仙草咪| 青青伊人网| 91av电影在线观看| 寂寞夜晚免费观看视频| 甜性涩爱在线看| 边摸边吃奶边做激情叫床视| 美女被艹网站| 伊人久久综合网站| 国产在线一区二区AV视频| 色狠狠xx| 被窝伦理午夜电影网| 嗯好舒服嗯好大好猛好爽| 怡春院院日本一区二区久久| 国产亚洲日韩欧美视频| 天堂tv免费tv在线tv香蕉| 成人精品在线视频| 欧美成人国产| 5G在线观看免费年龄确认| 久久精品视在线观看85| 亚洲无吗在线视频| 国产亚洲精品字幕在线观看| 乌克兰16~18sex| 国产SUV精品一区二区883| 彭丹吃奶门|