自定义操作视图无法点击。

25

我正在尝试将自定义的ActionView添加到我的ActionBar中。

我想添加一个常见的刷新按钮(ImageButton,在FrameLayout中使用ProgressBar),但是如果我使用了ActionViewonOptionsItemSelected()从未被调用。

以下是代码:

在我的Activity中:

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.messages_actionbar, menu);
mRefreshView = (RefreshView) menu.findItem(R.id.messages_refresh).getActionView();

return super.onCreateOptionsMenu(menu);
}

messages_actionbar的来源:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@+id/messages_refresh"
        android:title="title"
        android:icon="@drawable/icon"
        android:showAsAction="always"
        android:actionViewClass="com.blabla.RefreshView"/>
</menu>

RefreshView的代码:

public class RefreshView extends FrameLayout {

    private ImageView mButton;
    private ProgressBar mProgressBar;
    private boolean mLoading;

    public RefreshView(Context context) {
        super(context, null);
        initView(context);
    }

    public RefreshView(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
        initView(context);
    }

    public RefreshView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(context);
    }

    private void initView(Context context) {
        LayoutInflater inflator = LayoutInflater.from(context);
        View v = inflator.inflate(R.layout.actionbar_refresh, this);
        mProgressBar = (ProgressBar) v.findViewById(R.id.action_refresh_progress);
        mButton = (ImageView) v.findViewById(R.id.action_refresh_button);
    }

    public void setLoading(boolean loading) {
        if (loading != mLoading) {
            mProgressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
            mButton.setVisibility(loading ? View.GONE : View.VISIBLE);
            mLoading = loading;
        }
    }
}

actionbar_refresh的源代码:

<?xml version="1.0" encoding="utf-8" ?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/action_refresh_button"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:scaleType="center"
        android:background="@drawable/icon" />

    <ProgressBar
        android:id="@+id/action_refresh_progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:visibility="gone"
        android:indeterminate="true" />
</FrameLayout>

另一方面,如果我在RefreshView类内部为其中的ImageView设置了一个clickListener,那么它将被调用。

有人已经这样做过了吗?


2
我正在尝试添加通用的刷新按钮(ImageButton、FrameLayout 中的 ProgressBar),但如果我使用 ActionView,那么 onOptionsItemSelected() 永远不会被调用。你为什么认为应该调用它呢?它不再是菜单选项 - 它是你自定义的 View,所以我不希望调用 onOptionsItemSelected()。 - CommonsWare
1
@CommonsWare:为什么不呢?视图是现有菜单项的“ActionView”。menu.findItem(R.id.messages_refresh).getActionView();返回正确的视图。如果您所说的是正确的,那么Gmail应用程序是如何做到的呢?您认为他们设置了clickListener,然后自定义视图以某种方式通知了Activity吗? - Macarse
那将是我的猜测。想一想:假设我有一个包含17个按钮的操作视图。它们都会触发onOptionsItemSelected()吗?如果是这样,你如何区分它们? - CommonsWare
3个回答

8

onOptionsItemSelected() 只有在操作项位于溢出菜单中时才应该调用,您也应该处理它。 (您已将其强制为“始终”在操作栏上,因此 onOptionsItemSelected() 将不会被调用)。

在膨胀后的 onCreateOptionsMenu() 中,必须为菜单项设置一个 OnMenuItemClickListener


我撤回上面的一部分。我进行了一些额外的测试。对于操作视图,只有操作项(在操作栏或溢出菜单中)才会调用onOptionsItemSelected()。这解释了你所看到的情况。但是当操作视图放置在溢出菜单中时,如果定义了onMenuItemClick(),则会为其调用onOptionsItemSelected()。 - CEO

3

这个方法是可行的,但我实现它的方式与你设置的方式非常相似,因为我需要更多地控制实际视图。你应该在你的视图上实现一个onClickListener,然后实现一个回调给基本活动或片段。如果你只需要一个简单的刷新旋转器,我建议你采用你的方法,我只是想说,它可以通过一些小的改变来使你原来的代码工作。 - Maurycy
1
我从你的博客文章中进行了一些修改,现在我已经将其上传到GitHub - Enrique Diaz

1
我已经找到了适合我的工作解决方案,想要与你分享。它基于(@Macarse)的第一种方法,但做了一些重要的改变。
重要提示:根据需要调整initView方法。
  1. onClickListener设置给ImageView(mButton

  2. loading设置为true,并通知Activity(MyActivity)有点击事件发生

    private void initView(final Context context) {
        final LayoutInflater inflator = LayoutInflater.from(context);
    
        final View actionView = inflator.inflate(
                R.layout.action_refresh_progress, this);
        mProgressBar = (ProgressBar) actionView
                .findViewById(R.id.action_refresh_progress);
    
        mButton = (ImageView) actionView
                .findViewById(R.id.action_refresh_button);
    
        mButton.setOnClickListener(new OnClickListener() {
    
            @Override
            public void onClick(final View view) {
                setLoading(true);
                ((MyActivity) context).handleRefreshButtonClick();
            }
        });
    }
    
  3. 根据点击事件在Activity(MyActivity)中作出相应的反应

    public void handleRefreshButtonClick() {
        // 开始刷新...
    }
    

我希望我的方法能够节省您寻找可行解决方案的时间!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接