老生常談Android HapticFeedback(震動(dòng)反饋)
Android中長(zhǎng)按一個(gè)控件的時(shí)候,想以震動(dòng)提示用戶,除了用Vibrate類來(lái)做,還可以用到(HapticFeedback)震動(dòng)反饋實(shí)現(xiàn)。
本篇文章,我們就一起來(lái)熟悉一下Android震動(dòng)反饋,首先我們打開手機(jī)上的振動(dòng)模式開光,這里我是以小米手機(jī)來(lái)做模擬的,位置在設(shè)置—>聲音和震動(dòng)—>觸摸時(shí)震動(dòng),如下圖所示:

震動(dòng)強(qiáng)度,我選擇了較強(qiáng),以讓震動(dòng)更明顯。
系統(tǒng)觸發(fā)震動(dòng)
下面從一個(gè)例子,來(lái)開始本篇博客,對(duì)一個(gè)button注冊(cè)長(zhǎng)按:
Button click= (Button) findViewById(R.id.click);
click.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(MainActivity.this,"長(zhǎng)按點(diǎn)擊",Toast.LENGTH_SHORT).show();
//觸發(fā)震動(dòng)反饋
return true;
//return false;
}
});
當(dāng)你長(zhǎng)按此button,彈出一個(gè)toast,并且震動(dòng)了,但是,返回false并不會(huì)觸發(fā)震動(dòng)。
現(xiàn)在看源碼分析一下,這是為何。
button實(shí)現(xiàn)setOnLongClickListener方法,在父類TextView的父類View中,
View.setOnLongClickListener源碼:
/**
* Register a callback to be invoked when this view is clicked and held. If this view is not
* long clickable, it becomes long clickable.
*
* @param l The callback that will run
*
* @see #setLongClickable(boolean)
*/
public void setOnLongClickListener(@Nullable OnLongClickListener l) {
if (!isLongClickable()) {
setLongClickable(true);
}
getListenerInfo().mOnLongClickListener = l;
}
我們要看mOnLongClickListener是在哪里調(diào)用的接口onLongClick方法,最終在View的源碼中找到
View.performLongClick源碼:
/**
* Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
* OnLongClickListener did not consume the event.
*
* @return True if one of the above receivers consumed the event, false otherwise.
*/
public boolean performLongClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
boolean handled = false;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnLongClickListener != null) {
handled = li.mOnLongClickListener.onLongClick(View.this);
}
if (!handled) {
handled = showContextMenu();
}
if (handled) {
performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
return handled;
}
可以看到
第13行執(zhí)行了onLongClick方法,并且將返回值給了變量handled,
在第18行,hangdled為true,執(zhí)行performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);該方法最終觸發(fā)了震動(dòng)反饋。
這就是為什么,onLongClick返回true的時(shí)候,才會(huì)有震動(dòng)效果。
自定義觸發(fā)震動(dòng)
上節(jié)提到,在performHapticFeedback觸發(fā)震動(dòng),觀察源碼得知,用戶可以自己通過(guò)代碼來(lái)觸發(fā)。
如下文所示,點(diǎn)擊也會(huì)觸發(fā)震動(dòng)反饋了:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
}
});
現(xiàn)在我們就去performHapticFeedback源碼看下,都執(zhí)行了什么,
View.performHapticFeedback源碼:
/**
* BZZZTT!!1!
*
* <p>Provide haptic feedback to the user for this view.
*
* <p>The framework will provide haptic feedback for some built in actions,
* such as long presses, but you may wish to provide feedback for your
* own widget.
*
* <p>The feedback will only be performed if
* {@link #isHapticFeedbackEnabled()} is true.
*
* @param feedbackConstant One of the constants defined in
* {@link HapticFeedbackConstants}
*/
public boolean performHapticFeedback(int feedbackConstant) {
return performHapticFeedback(feedbackConstant, 0);
}
這里解釋三個(gè)知識(shí)點(diǎn):
1、只有在isHapticFeedbackEnabled()為true的情況下,才會(huì)觸發(fā)震動(dòng)。之后會(huì)解釋在為false的情況下,為何不會(huì)觸發(fā)震動(dòng)。
在xml里,可以通過(guò)android:hapticFeedbackEnabled=”false|true”來(lái)進(jìn)行設(shè)置
在java代碼里,可以通過(guò)view.setHapticFeedbackEnabled(boolean)來(lái)設(shè)置,
不過(guò)默認(rèn)是true哦。
2、HapticFeedbackConstants的常量值,我們要用到的有三個(gè),一個(gè)是LONG_PRESS(長(zhǎng)按),第二個(gè)是FLAG_IGNORE_VIEW_SETTING(不受view的設(shè)置影響,即不受isHapticFeedbackEnabled()的影響),第三個(gè)是FLAG_IGNORE_GLOBAL_SETTING(不受系統(tǒng)設(shè)置的影響,即不受是否開啟震動(dòng)反饋的影響)
3、我們看到該方法最終是返回的performHapticFeedback(int feedbackConstant, int flags)這個(gè)方法,
View.performHapticFeedback(int feedbackConstant, int flags)源碼:
/**
* BZZZTT!!1!
*
* <p>Like {@link #performHapticFeedback(int)}, with additional options.
*
* @param feedbackConstant One of the constants defined in
* {@link HapticFeedbackConstants}
* @param flags Additional flags as per {@link HapticFeedbackConstants}.
*/
public boolean performHapticFeedback(int feedbackConstant, int flags) {
if (mAttachInfo == null) {
return false;
}
//noinspection SimplifiableIfStatement
if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
&& !isHapticFeedbackEnabled()) {
return false;
}
return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
(flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
}
看第15行的if語(yǔ)句,當(dāng)flags=0時(shí),flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING為0,又isHapticFeedbackEnabled()為false,整個(gè)條件為真,所以會(huì)執(zhí)行17行,直接return。這也是為什么performHapticFeedback(int feedbackConstant)方法一定要在isHapticFeedbackEnabled()為ture的情況下才會(huì)觸發(fā)震動(dòng)。
在這里說(shuō)一下,&是按位與,返回?cái)?shù)值,&&邏輯與,返回布爾值。
第19-20行,就是觸發(fā)底層震動(dòng)的代碼了,之后代碼不做分析。
HapticFeedbackConstants常量
接下來(lái),看下HapticFeedbackConstants三個(gè)常量,還是之前的代碼,如下所示:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS
);
}
});
在單擊后,會(huì)觸發(fā)震動(dòng),但是如果xml加上 android:hapticFeedbackEnabled=”false”這句話,單擊則沒(méi)有震動(dòng)效果了。如下所示:
<Button android:layout_width="wrap_content" android:id="@+id/click" android:layout_height="wrap_content" android:hapticFeedbackEnabled="false" android:text="make" />
如果這時(shí),想讓其震動(dòng),可以用如下方法來(lái)做:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING
);
}
});
忽略view的屬性設(shè)置。
還記得本篇文章之前,說(shuō)去設(shè)置里打開觸摸時(shí)震動(dòng)的開關(guān)嗎,其實(shí),用戶不打開,照樣可以讓其震動(dòng),只需要用如下的方法:
click.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
v.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS,HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING
);
}
});
忽略系統(tǒng)設(shè)置,哈哈,不過(guò)不建議這樣做,畢竟用戶禁止了觸摸反饋,我們就沒(méi)必要繼續(xù)挑戰(zhàn)用戶極限了。
最后,我還要說(shuō)一點(diǎn),就是以上的方法,不需要震動(dòng)權(quán)限,不需要震動(dòng)權(quán)限,不需要震動(dòng)權(quán)限、重要的事情說(shuō)三遍。
以上這篇老生常談Android HapticFeedback(震動(dòng)反饋)就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Android?妙用TextView實(shí)現(xiàn)左邊文字,右邊圖片
這篇文章主要介紹了Android?妙用TextView實(shí)現(xiàn)左邊文字,右邊圖片的相關(guān)資料,需要的朋友可以參考下2023-07-07
Popupwindow 的簡(jiǎn)單實(shí)用案例(顯示在控件下方)
下面小編就為大家?guī)?lái)一篇Popupwindow 的簡(jiǎn)單實(shí)用案例(顯示在控件下方)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
Android編程實(shí)現(xiàn)在自定義對(duì)話框中獲取EditText中數(shù)據(jù)的方法
這篇文章主要介紹了Android編程實(shí)現(xiàn)在自定義對(duì)話框中獲取EditText中數(shù)據(jù)的方法,結(jié)合實(shí)例形式分析了Android對(duì)話框數(shù)據(jù)傳遞相關(guān)操作技巧,需要的朋友可以參考下2018-01-01
Android EdText編輯框禁止輸入表情符號(hào)(使用正則表達(dá)式)
這篇文章主要介紹了Android EdText編輯框禁止輸入表情符號(hào)使用正則表達(dá)式,需要的朋友可以參考下2017-06-06
Android開發(fā)筆記XML數(shù)據(jù)解析方法及優(yōu)缺點(diǎn)
XML數(shù)據(jù)是一種常見的數(shù)據(jù)格式,Android開發(fā)中需要對(duì)其進(jìn)行解析。常用的XML解析方式有DOM、SAX、Pull和Json等,每種方式都有其優(yōu)缺點(diǎn)。開發(fā)者可以根據(jù)具體需求選擇合適的解析方式,提高數(shù)據(jù)解析效率和性能2023-05-05

