23

我需要一个 getOnClickListener() 用于 Android 中的视图。这样我可以为我的视图分配一个临时的 OnClickListener。我想像这样使用它:

private View.OnClickListener oldListener;

public void assignTempListener(View view) {
    oldListener = view.getOnClickListener(); // doesn't exist

    view.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // some code

            v.setOnClickListener(oldListener);
        }
    });
}

问题是这个函数不存在。我也不能从 View 继承来创建这个方法,因为所有类型的 View 都可以传递给 assignTempListener。还有其他方法可以使用它吗?

编辑:在我的代码中犯了一个小错误。

4

5 回答 5

27

您可以使用... REFLECTION来做到这一点。*击鼓*

这条路线充满了危险。

我不推荐它,因为类的内部结构可以随时更改,但如果确实无法避免,您可以按照以下方式在 Android 4.2.2 之前执行此操作:

/**
 * Returns the current View.OnClickListener for the given View
 * @param view the View whose click listener to retrieve
 * @return the View.OnClickListener attached to the view; null if it could not be retrieved
 */
public View.OnClickListener getOnClickListener(View view) {
    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
        return getOnClickListenerV14(view);
    } else {
        return getOnClickListenerV(view);
    }
}

//Used for APIs lower than ICS (API 14)
private View.OnClickListener getOnClickListenerV(View view) {
    View.OnClickListener retrievedListener = null;
    String viewStr = "android.view.View";
    Field field;

    try {
        field = Class.forName(viewStr).getDeclaredField("mOnClickListener");
        retrievedListener = (View.OnClickListener) field.get(view);
    } catch (NoSuchFieldException ex) {
        Log.e("Reflection", "No Such Field.");
    } catch (IllegalAccessException ex) {
        Log.e("Reflection", "Illegal Access.");
    } catch (ClassNotFoundException ex) {
        Log.e("Reflection", "Class Not Found.");
    }

    return retrievedListener;
}

//Used for new ListenerInfo class structure used beginning with API 14 (ICS)
private View.OnClickListener getOnClickListenerV14(View view) {
    View.OnClickListener retrievedListener = null;
    String viewStr = "android.view.View";
    String lInfoStr = "android.view.View$ListenerInfo";

    try {
        Field listenerField = Class.forName(viewStr).getDeclaredField("mListenerInfo");
        Object listenerInfo = null;

        if (listenerField != null) {
            listenerField.setAccessible(true);
            listenerInfo = listenerField.get(view);
        }

        Field clickListenerField = Class.forName(lInfoStr).getDeclaredField("mOnClickListener");

        if (clickListenerField != null && listenerInfo != null) {
            retrievedListener = (View.OnClickListener) clickListenerField.get(listenerInfo);
        }
    } catch (NoSuchFieldException ex) {
        Log.e("Reflection", "No Such Field.");
    } catch (IllegalAccessException ex) {
        Log.e("Reflection", "Illegal Access.");
    } catch (ClassNotFoundException ex) {
        Log.e("Reflection", "Class Not Found.");
    }

    return retrievedListener;
}
于 2013-02-21T02:51:12.640 回答
7

您可以覆盖该类并为您的视图声明一个 onClicklistener 并为 onClickListener 字段编写 setter 和 getter:

public class SAutoBgButton extends ImageButton {

  public View.OnClickListener mOnClickListener;

  @Override
  public void setOnClickListener(OnClickListener l) {
    super.setOnClickListener(l);
    mOnClickListener = l;
  }
  public OnClickListener getmOnClickListener() {
    return mOnClickListener;
  }
}
于 2015-11-09T09:00:59.917 回答
2

答案很简单

OnClickListener ocl = new OnClickListener { 
    @Override
    public void onClick(View view) {
        clickableView.performClick();
    }
}

onclicklistener 的全部功能除了一件事 - 你不能将任何视图作为参数传递给它,clickableView它将是处理程序,但在大多数情况下它就足够了

于 2018-06-21T10:29:16.893 回答
1

采用

 oldListener = new view.OnClickListener() {

        @Override
        public void onClick(View v) {
            // some code

          v.setOnClickListener(oldListener);
        }
    });

代替

oldListener = view.getOnClickListener(); // doesn't exist

getOnClickListener不是当前 API 中ViewButton的任何方法,请参阅文档了解更多详细信息

http://developer.android.com/reference/android/view/View.OnClickListener.html

于 2012-06-25T09:54:48.247 回答
0

尼特!

给出的答案中的 oldListener 在每种情况下都被重新定义,并且它的旧状态或定义丢失,无论它的名称是否假装。

遵循此技术: 获取 Android View 对象 的当前 onClickListener 将在抽象类的 onClick 方法中设置“旧”侦听器,并且任何临时侦听器将使用 setOnClickListener 以及对 super 的调用,以便在以下情况下(重新)设置旧侦听器或酌情

临时侦听器设置代码不需要知道“旧”侦听器是什么,但是仍然需要某种形式的协调,以便该侦听器的作者或那些侦听器使它们抽象化并使用 onClick 方法设置点击侦听器,简而言之,遵循协议。

在特殊情况下,您可能希望绕过 onclicklistener View 成员的 protected 或 private 限定符:http: //grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.1_r2/android/ view/View.java#View.0mOnClickListener 然后做一点http://www.jguru.com/faq/view.jsp?EID=321191 这会让你成为听众。

您甚至可能想编写自己的 getOnClickListener 或任何使用自省方法的 getter,如果它确实有效的话:)

:)

于 2013-02-21T00:34:49.673 回答