【问题标题】:How do I get the OnClickListener working on a custom view with a RelativeLayout?如何让 OnClickListener 在具有 RelativeLayout 的自定义视图上工作?
【发布时间】:2013-07-31 18:12:42
【问题描述】:

问题

你好,

我用RelativeLayout 构建了一个自定义视图,将其用作自定义图像按钮。 到目前为止,选择它有效(PIC2),即使我单击它(使用 GoogleTV Remote),视图也成功将其状态更改为 PIC3(感谢android:duplicateParentState="true"

但不幸的是,onClickListener 没有触发(无论我是使用远程“确定”按钮单击视图还是使用触摸板......)

我真的需要像普通按钮一样的行为。 如何做到这一点?我已经花了几个小时搜索 Google 和 StackOverflow...(顺便说一句。在为 RelativeLayout 设置 android:clickable="false" 时,OnClickListener 正在工作,但只有当我使用鼠标指针(触摸板)和之后的焦点时丢失并且不显示状态(图3))

图片

PIC1

PIC2

PIC3

代码

rounded_button.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="false">

<TextView
    android:id="@+id/caption"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:layout_marginLeft="30dp"
    android:background="@drawable/btn_rounded_corners"
    android:paddingLeft="25dp"
    android:textSize="15sp" 
    android:duplicateParentState="true"/>

<ImageView
    android:id="@+id/icon"
    style="@style/Menu_Button"
    android:layout_width="50dp"
    android:layout_height="50dp"
    android:layout_marginRight="-50dp"
    android:layout_toLeftOf="@id/caption"
    android:background="@drawable/btn_main_menu_back_shape"
    tools:ignore="ContentDescription"
    android:duplicateParentState="true" />

RoundedButton.java

public class RoundedButton extends RelativeLayout {
private String label;
private int icon;

/**
 * @param context
 */
public RoundedButton(Context context)
{
    super(context);
    initAttributes(context, null);
}

/**
 * @param context
 * @param attrs
 */
public RoundedButton(Context context, AttributeSet attrs)
{
    super(context, attrs);
    initAttributes(context, attrs);
}

/**
 * @param context
 * @param attrs
 * @param defStyle
 */
public RoundedButton(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
    initAttributes(context, attrs);
}

private void initAttributes(Context context, AttributeSet attrs)
{
    LayoutInflater.from(context).inflate(R.layout.rounded_button, this, true);

    TypedArray a = 
        context.obtainStyledAttributes(attrs, R.styleable.RoundedButton);

    final int N = a.getIndexCount();
    for (int i = 0; i < N; ++i)
    {
        int attr = a.getIndex(i);
        switch (attr)
        {
            case R.styleable.RoundedButton_text:
                setLabel(a.getString(attr));
                break;
            case R.styleable.RoundedButton_icon:
                setIcon(a.getResourceId(attr, 0));
                break;
        }
    }
    a.recycle();
}

public String getLabel()
{
    return this.label;
}

public void setLabel(final String label)
{
    this.label = label;
    ((TextView)findViewById(R.id.caption)).setText(this.label);
}

/**
 * @return the icon
 */
public int getIcon()
{
    return icon;
}

/**
 * @param icon the icon to set
 */
public void setIcon(int icon)
{
    this.icon = icon;
    ((ImageView)findViewById(R.id.icon)).setImageResource(this.icon);
}
}

activity_main.xml 的相关部分

<eu.test.custom_views.RoundedButton
    android:id="@+id/custombutton"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    custom:icon="@drawable/hand_icon_green_left"
    custom:text="Normal state" />

主要活动

public class MainActivity extends Activity implements OnClickListener {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ((RoundedButton) findViewById(R.id.custombutton)).setOnClickListener(this);
}

@Override
public void onClick(View arg0) {
    if(arg0.getId() == R.id.custombutton) { Toast.makeText(this, "Clicked", Toast.LENGTH_SHORT).show(); }
}
}

【问题讨论】:

  • 嘿@Sebastian 你是如何实现 onclick 监听器的?任何帮助都会得到帮助
  • 你不必使用触摸事件,它不会起作用。这很简单:stackoverflow.com/a/66733216/294884

标签: android google-tv


【解决方案1】:

我现在明白了.. 解决方案非常简单,花了一些时间;-)

解决方案

在 RoundedButton.java 中覆盖 dispatchKeyEvent(KeyEvent event) 并实现您自己的 OnClickListener。然后写一个公开的setOnClickListener函数……

private OnClickListener listener;

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_UP) {
        if(listener != null) listener.onClick(this);
    }
    return super.dispatchTouchEvent(event);
}


@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if(event.getAction() == KeyEvent.ACTION_UP && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER || event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
        if(listener != null) listener.onClick(this);
    }
    return super.dispatchKeyEvent(event);
}

public void setOnClickListener(OnClickListener listener) {
    this.listener = listener;
}

工作 RoundedButton.java

public class RoundedButton extends RelativeLayout
{
private OnClickListener listener;
private String label;
private int icon;

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if(event.getAction() == MotionEvent.ACTION_UP) {
        if(listener != null) listener.onClick(this);
    }
    return super.dispatchTouchEvent(event);
}


@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if(event.getAction() == KeyEvent.ACTION_UP && (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER || event.getKeyCode() == KeyEvent.KEYCODE_ENTER)) {
        if(listener != null) listener.onClick(this);
    }
    return super.dispatchKeyEvent(event);
}

public void setOnClickListener(OnClickListener listener) {
    this.listener = listener;
}

/**
 * @param context
 */
public RoundedButton(Context context)
{
    super(context);
    initAttributes(context, null);
}

/**
 * @param context
 * @param attrs
 */
public RoundedButton(Context context, AttributeSet attrs)
{
    super(context, attrs);
    initAttributes(context, attrs);
}

/**
 * @param context
 * @param attrs
 * @param defStyle
 */
public RoundedButton(Context context, AttributeSet attrs, int defStyle)
{
    super(context, attrs, defStyle);
    this.setClickable(true);
    this.setEnabled(true);
    this.setFocusable(true);
    this.setFocusableInTouchMode(true);

    initAttributes(context, attrs);
}

private void initAttributes(Context context, AttributeSet attrs)
{
    LayoutInflater.from(context).inflate(R.layout.rounded_button,  this, true);

    TypedArray a = 
        context.obtainStyledAttributes(attrs, R.styleable.RoundedButton);

    final int N = a.getIndexCount();
    for (int i = 0; i < N; ++i)
    {
        int attr = a.getIndex(i);
        switch (attr)
        {
            case R.styleable.RoundedButton_text:
                setLabel(a.getString(attr));
                break;
            case R.styleable.RoundedButton_icon:
                setIcon(a.getResourceId(attr, 0));
                break;
        }
    }
    a.recycle();
}

public String getLabel()
{
    return this.label;
}

public void setLabel(final String label)
{
    this.label = label;
    ((TextView)findViewById(R.id.caption)).setText(this.label);
}

/**
 * @return the icon
 */
public int getIcon()
{
    return icon;
}

/**
 * @param icon the icon to set
 */
public void setIcon(int icon)
{
    this.icon = icon;
    ((ImageView)findViewById(R.id.icon)).setImageResource(this.icon);
}

}

【讨论】:

  • 这是唯一对我有用的解决方案
【解决方案2】:

我在RecyclerView.Adapter 中创建了我的自定义视图(继承自RelativeLayout)的实例,并将list_item.xml 膨胀到每个新实例中,然后在onBindViewHolder() 方法中附加我的侦听器,但即使在理论上我以正确的方式做事直到我从 list_item.xml(我的自定义视图)的根布局中删除了 android:clickable="true" 属性后它才起作用

【讨论】:

    猜你喜欢
    • 2010-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    相关资源
    最近更新 更多