Достичь пункт меню панели инструментов нажмите ripple effect
Я пытаюсь использовать padding
для увеличения сенсорной области кнопки. Я использую
<ImageButton
android:paddingRight="32dp"
android:paddingEnd="32dp"
android:id="@+id/confirm_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:background="?selectableItemBackgroundBorderless"
android:src="?attr/confirmIcon" />
область щелчка увеличивается. Но,selectableItemBackgroundBorderless
нажмите эффект больше не отображается как идеальный круг.
Я пытаюсь использовать duplicateParentState
техника для преодоления.
<FrameLayout
android:clickable="true"
android:paddingRight="32dp"
android:paddingEnd="32dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_centerVertical="true">
<ImageButton
android:duplicateParentState="true"
android:id="@+id/confirm_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:src="?attr/confirmIcon" />
</FrameLayout>
теперь
- область щелчка увеличена.
- на
selectableItemBackgroundBorderless
круг эффект-идеальный круг.
однако, похоже, у него какое-то странное поведение. Когда я нажимаю на фактическую площадь ImageButton
, эффект нажатия круга не отображается.
Примечание, я стараюсь избегать использования TouchDelegate
техника, если я буду вынужден, как это делает наш код более сложный.
дополнительная информация
следующее правильное поведение, показанное кнопкой для Toolbar
.
эффект пульсации отображается, когда область щелчка находится вне кнопки
эффект проявляется при щелчке в районе кнопки
тем не менее, я понятия не имею как они реализуют такое поведение.
4 ответов
потратив некоторое время, я, наконец, нашел, как "панели инструментов тайна" строительство. Это ActionMenuItemView
, который отображается на панели инструментов. И вы можете видеть, что внутри xml-файл это style="?attr/actionButtonStyle"
приложенный к нему. ?attr/actionButtonStyle
соответствует Widget.Material.ActionButton
и в этом стиле мы видим <item name="background">?attr/actionBarItemBackground</item>
.
если вы хотите применить тот же эффект к ImageButton
, то все что вам нужно сделать, это применить android:background="?attr/actionBarItemBackground"
к нему. Таким образом, имея следующий xml макет:
<ImageButton
android:id="@+id/confirm_image_button"
android:layout_width="50dp"
android:layout_height="50dp"
android:background="?attr/actionBarItemBackground"
android:src="@drawable/ic_check_black_24dp" />
вы получите этот вывод:
включен "показать границы макета", так что фактические границы ImageButton
видны
если вам интересно, что ?attr/actionBarItemBackground
на самом деле представляет, вот это:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight"
android:radius="20dp" />
таким образом, вы можете создать свой холст и применить его в качестве фона для ImageButton
.
рябь на Android 5.0 начинается в центре каждого представления. Соответственно к правилам материального дизайна, пульсации должны начать где касание событие происходит, поэтому они, кажется, вытекают наружу из пальца. это был обратился в Android 5.1, но была ошибка в Android 5.0
чтобы исправить это, вам нужно использовать
setHotspot()
метод, добавленный к Drawable в API уровня 21.setHotspot()
предоставляет в папке drawable в "горячая точка", иRippleDrawable
по-видимому, использует это как точку эманации для эффекта пульсации.setHotspot()
займет пару значения float, предположительно с прицелом на использованиеsetHotspot()
внутриOnTouchListener
, какMotionEvent
отчетыX/Y
позиции события touch со значениями float.
благодаря путеводителю занятого Кодера
вы можете использовать этот код для исправления ошибки ряби:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
btn.setOnTouchListener(new View.OnTouchListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouch(View v, MotionEvent event) {
v.getBackground()
.setHotspot(event.getX(), event.getY());
return(false);
}
});
}
другое решение:
как добиться анимация пульсаций с помощью библиотеки поддержки?
другое решение:
С первой попытки:
я пытаюсь использовать прокладку для увеличения сенсорной области кнопки.
вы можете использовать этот код, чтобы поместить центр пульсация в центре ImageButton
:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
btn.setOnTouchListener(new View.OnTouchListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override
public boolean onTouch(View v, MotionEvent event) {
v.getBackground()
.setHotspot(v.getWidth()/2f, v.getHeight()/2f);//setting hot spot at center of ImageButton
return(false);
}
});
}
возможно другое решение, когда FrameLayout
обертывания ImageButton
:
как вы говорите:
однако, похоже, у него какое-то странное поведение. Когда я нажимаю на фактическая площадь ImageButton, эффект кругового нажатия не отображается.
обойти эту проблему можно, чтобы добавить frameLayout.performClick()
на onClick()
метод ImageButton
или вы можете имитировать прикосновение frameLayout
такой код ImageButton
кнопки:
// Obtain MotionEvent object
long downTime = SystemClock.uptimeMillis();
long eventTime = SystemClock.uptimeMillis() + 100;
float x = 0.0f;// or x = frameLayout.getWidth()/2f
float y = 0.0f;// or y = frameLayout.getHeight()/2f
// List of meta states found here: developer.android.com/reference/android/view/KeyEvent.html#getMetaState()
int metaState = 0;
MotionEvent motionEvent = MotionEvent.obtain(
downTime,
eventTime,
MotionEvent.ACTION_UP,
x,
y,
metaState
);
// Dispatch touch event to view
frameLayout.dispatchTouchEvent(motionEvent);
если вы используете android:duplicateParentState="true"
, просто набор android:clickable="false"
на ImageButton
сделает ваш Button
выделяем жмем на него и его родителей
<ImageButton
...
android:duplicateParentState="true"
android:clickable="false"
/>
объяснение
С документ
для дублирования включена, такая точка зрения государственного выигрышного от своих родителей, а не от собственных внутренних свойств
=> просмотр базы изменения состояния в Родительском состоянии.
Значение по умолчанию clickable
of ImageButton
is true => при нажатии кнопки ImageButton
, состояние родителя не изменяется => ImageButton
не выделить
= > Set clickable=false
решит проблему
ЗАМЕТКИ
1) Не забудьте установить clickable=true
по его родителя
2) для TextView
, ImageView
(или некоторые представления, которые имеют clickable=false по умолчанию), вам не нужно устанавливать clickable=false
3) будьте осторожны при использовании setOnClickListener
public void setOnClickListener(@Nullable OnClickListener l) {
if (!isClickable()) {
setClickable(true);
}
getListenerInfo().mOnClickListener = l;
}
при использовании setOnClickListener
он также setClickable(true)
в этом случае вы только установить setOnClickListener
для родительского макета
Я подозреваю, что ваша проблема заключается в том, что у вас есть ImageButton
и ImageView
. Стиль по умолчанию для ImageButton
- это:
<style name="Widget.ImageButton">
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
<item name="android:scaleType">center</item>
<item name="android:background">@android:drawable/btn_default</item>
</style>
заменен был фон, но вы все равно оставили элемент кликабельным и фокусируемым. В вашем примере реальным активным элементом является контейнер, поэтому вы можете использовать обычный ImageView
, или установите элемент, чтобы быть не кликабельным и фокусируемым вручную. Также важно установить прослушиватель кликов на контейнере,не в сама кнопка / изображение, потому что она станет кликабельной.
это один из вариантов:
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="48dp"
android:focusable="true"
android:clickable="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
>
<ImageButton
android:duplicateParentState="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:duplicateParentState="true"
android:src="@drawable/ic_check_black_24dp"
android:clickable="false"
android:focusable="false"
/>
</FrameLayout>
другой такой же, за исключением вида внутри FrameLayout
- это:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?selectableItemBackgroundBorderless"
android:duplicateParentState="true"
android:src="@drawable/ic_check_black_24dp"
/>
вот визуальное доказательство:
это было захвачено на эмуляторе под управлением Android 5.0.2. Я попробовал это на своем телефоне 8.0, также работает.