【发布时间】:2011-04-14 16:50:48
【问题描述】:
我已经为此工作了一段时间。这个想法一开始很简单,我想要一个 SlidingDrawer 手柄上的按钮,以允许用户查看特定于抽屉内容的设置。所以我做了一个布局,旁边有一个按钮,并将其设置为手柄。抽屉画得很好,但不允许按下按钮(在把手上)。当我尝试点击该东西时,点击被解释为手柄点击,并切换抽屉的状态。
有人知道怎么回事吗?
谢谢~艾顿
【问题讨论】:
标签: android onclick slidingdrawer
我已经为此工作了一段时间。这个想法一开始很简单,我想要一个 SlidingDrawer 手柄上的按钮,以允许用户查看特定于抽屉内容的设置。所以我做了一个布局,旁边有一个按钮,并将其设置为手柄。抽屉画得很好,但不允许按下按钮(在把手上)。当我尝试点击该东西时,点击被解释为手柄点击,并切换抽屉的状态。
有人知道怎么回事吗?
谢谢~艾顿
【问题讨论】:
标签: android onclick slidingdrawer
我将发布我的实现,以免其他人麻烦。
您基本上必须扩展 SlidingDrawer 类并处理 onInterceptTouch 事件,以便当它们位于句柄布局内的项目顶部时通过。
这假设您使用 ViewGroup(例如任何布局)作为句柄,并且其中的所有视图都是可点击的。
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SlidingDrawer;
public class ClickableSlidingDrawer extends SlidingDrawer {
private ViewGroup mHandleLayout;
private final Rect mHitRect = new Rect();
public ClickableSlidingDrawer(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public ClickableSlidingDrawer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
View handle = getHandle();
if (handle instanceof ViewGroup) {
mHandleLayout = (ViewGroup) handle;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
if (mHandleLayout != null) {
int childCount = mHandleLayout.getChildCount();
int handleClickX = (int)(event.getX() - mHandleLayout.getX());
int handleClickY = (int)(event.getY() - mHandleLayout.getY());
Rect hitRect = mHitRect;
for (int i=0;i<childCount;i++) {
View childView = mHandleLayout.getChildAt(i);
childView.getHitRect(hitRect);
if (hitRect.contains(handleClickX, handleClickY)) {
return false;
}
}
}
return super.onInterceptTouchEvent(event);
}
}
然后,在您的布局 .xml 中,只需使用 <my.package.name.ClickableSlidingDrawer> 而不是 <SlidingDrawer>
【讨论】:
我尝试了 d4n3 的实现,但由于我的句柄包含一个嵌套在多个 ViewGroups 中的按钮,我不得不对其进行修改以使其工作。
我的实现还假设您使用ViewGroup 作为句柄,但子视图不必是可点击的。此外,您必须将要在句柄中单击的视图的 tag 设置为“click_intercepted”。只有具有此特定标签集的子视图才会考虑在句柄内进行点击。这样,您可以根据需要对句柄进行布局,并且仍然可以在单击句柄中特定的Views(例如Button)时采取适当的行动。此外,通过此实现,您仍然可以拖动和单击句柄来切换其状态。
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.SlidingDrawer;
public class ClickableSlidingDrawer extends SlidingDrawer
{
private static final String TAG_CLICK_INTERCEPTED = "click_intercepted";
private ViewGroup mHandleLayout;
private final Rect mHitRect = new Rect();
public ClickableSlidingDrawer(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ClickableSlidingDrawer(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
@Override
protected void onFinishInflate()
{
super.onFinishInflate();
View handle = getHandle();
if (handle instanceof ViewGroup)
{
mHandleLayout = (ViewGroup) handle;
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event)
{
if (mHandleLayout != null)
{
int clickX = (int) (event.getX() - mHandleLayout.getLeft());
int clickY = (int) (event.getY() - mHandleLayout.getTop());
if (isAnyClickableChildHit(mHandleLayout, clickX, clickY))
{
return false;
}
}
return super.onInterceptTouchEvent(event);
}
private boolean isAnyClickableChildHit(ViewGroup viewGroup, int clickX, int clickY)
{
for (int i = 0; i < viewGroup.getChildCount(); i++)
{
View childView = viewGroup.getChildAt(i);
if (TAG_CLICK_INTERCEPTED.equals(childView.getTag()))
{
childView.getHitRect(mHitRect);
if (mHitRect.contains(clickX, clickY))
{
return true;
}
}
if (childView instanceof ViewGroup && isAnyClickableChildHit((ViewGroup) childView, clickX, clickY))
{
return true;
}
}
return false;
}
}
【讨论】:
您可以使用布局 XML 中的 SlidingDrawer 元素中的属性抑制将手柄按钮上的单击解释为“打开”的操作。像这样:
<SlidingDrawer android:layout_width="fill_parent"android:id="@+id/SlidingDrawer" android:handle="@+id/slideHandleButton"
android:content="@+id/txtHolder" android:layout_height="fill_parent"
android:orientation="horizontal" android:allowSingleTap="false">
只需创建android:allowSingleTap="false" 然后像往常一样为按钮实现一个点击处理程序。这将阻止它打开/关闭抽屉,但您可能需要拦截按钮的事件以使其执行您希望它执行的操作。
【讨论】:
onClickListener 来拦截 onClickEvent。但是该事件不会被触发。你能告诉我为什么吗?
onClick(View) 方法。希望有帮助,如果不是我还在这里:)
Button 本身上实现了onClickListener。那行不通吗?而且,为什么我需要确保点击是在按钮的范围内,它的按钮的 onClickListener 正在被触发,这不意味着点击是在按钮的范围内吗?
首先制作一个布局并将您的 Handle 内容放入其中(假设您放入了 handle_content.xml)。
第二次用这个替换你当前的句柄handle:
<include android:id="@id/handle"
android:layout="@layout/handle_content.xml"/>
现在按如下操作(我之所以这样说是因为如果您按照上述操作,则以下工作正常)
这是我的实现:
package com.examples.my.views;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SlidingDrawer;
import com.examples.my.MainFragmentActivity;
public class MYSlidingDrawer extends SlidingDrawer {
private View button;
private int height;
private MainFragmentActivity activity;
public MYSlidingDrawer (Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics metrics = this.getResources().getDisplayMetrics();
height = metrics.heightPixels;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int left = button.getLeft();
int top = button.getTop();
int right = button.getRight();
int bottom = button.getBottom();
Rect rect = new Rect(left, top, right, bottom);
int x = (int) event.getX();
int y = (int) event.getY();
if (isOpened()) {
if (rect.contains(x, y)) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (activity != null)
{
//HERE DO YOUR WORK
// Like activity.tooglePlay();
}
}
return true;
}
} else {
y -= height;
if (rect.contains(x, Math.abs(y))) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (activity != null)
{
//HERE DO YOUR WORK
// Like activity.tooglePlay();
}
}
return true;
}
}
return super.onTouchEvent(event);
}
public void setButton(View button) {
this.button = button;
}
public void setActivity(MainFragmentActivity activity) {
this.activity = activity;
}
}
现在定义它,其中包含 MYSlidingDrawer:
MYSlidingDrawer drawer = (MYSlidingDrawer) findViewById(R.id.drawer);
drawer.setActivity(this);
Button btn = (Button) findViewById(R.id.play_btn);//button inside your handle
drawer.setButton(btn);
希望对您有所帮助。
【讨论】: