无法单击自定义操作视图
Posted
技术标签:
【中文标题】无法单击自定义操作视图【英文标题】:Custom Action View can't be clicked 【发布时间】:2011-07-23 16:47:30 【问题描述】:我正在尝试将自定义 ActionView
添加到我的 ActionBar
。
我正在尝试添加通用刷新按钮。 (ImageButton
,ProgressBar
在 FrameLayout
内)但如果我使用 ActionView
,则永远不会调用 onOptionsItemSelected()
。
代码如下:
在我的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_
android:layout_>
<ImageView
android:id="@+id/action_refresh_button"
android:layout_
android:layout_
android:scaleType="center"
android:background="@drawable/icon" />
<ProgressBar
android:id="@+id/action_refresh_progress"
android:layout_
android:layout_
android:layout_gravity="center"
android:visibility="gone"
android:indeterminate="true" />
</FrameLayout>
另一方面,如果我在RefreshView
类中将clickListener
设置为ImageView
,它就会被调用。
有人已经这样做了吗?
【问题讨论】:
“我正在尝试添加通用刷新按钮。(ImageButton,FrameLayout 内的 ProgressBar)但如果我使用 ActionView,则永远不会调用 onOptionsItemSelected()。” - 是什么让你认为它应该被调用?它不再是一个菜单选项——它是你的自定义View
——所以我不希望onOptionsItemSelected()
被调用。
@CommonsWare:为什么不呢?该视图是现有菜单项的ActionView
。 menu.findItem(R.id.messages_refresh).getActionView();
返回正确的视图。如果您说的是正确的,Gmail 应用程序是如何做到的?你认为他们设置了clickListener
并且自定义视图会以某种方式通知Activity
?
这是我的猜测。想一想:假设我有一个 17 个按钮的动作视图。他们都会触发onOptionsItemSelected()
吗?如果是这样,您将如何区分它们?
【参考方案1】:
onOptionsItemSelected()
仅在操作项位于溢出菜单中时才应调用,您也应处理该菜单。 (您将其强制“始终”显示在操作栏上,因此不会调用 onOptionsItemSelected()
)。
在onCreateOptionsMenu()
充气后,您必须为菜单项设置OnMenuItemClickListener
。
【讨论】:
我参与上面的后面。我做了一些额外的测试。 onOptionsItemSelected() 不会为操作视图调用,仅用于操作项(在操作栏或溢出菜单中)。这解释了你所看到的。但是当动作视图被放置在溢出菜单中时,会为其调用 onOptionsItemSelected(),如果定义了则调用 onMenuItemClick()。【参考方案2】:我最终使用了来自 http://code.google.com/p/styled-action-bar/ 的 src 代码。
【讨论】:
这可行,但是我以与您设置它的方式非常相似的方式实现了这一点,因为我需要对实际视图进行更多控制。您应该刚刚在视图上实现了 onClickListener,然后为要实现的基本活动或片段实现了回调。同样,如果您只需要一个简单的刷新微调器,我会建议您使用的方法,我只想说它可以与您的原始代码一起工作,只需稍作改动。 我已经从您的blog post 进行了调整,现在我已经上传到Github【参考方案3】:我找到了一个可行的解决方案,我想与您分享。它基于 (@Macarse) 的第一种方法,但有一些重要的变化。
重要提示:相应地调整 initView 方法
为 ImageView 设置一个 onClickListener (mButton)
将 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();
);
React根据 Activity 中的点击 (MyActivity)
public void handleRefreshButtonClick()
// Start refreshing...
我希望我的方法可以为您节省一些时间来寻找可行的解决方案!
【讨论】:
以上是关于无法单击自定义操作视图的主要内容,如果未能解决你的问题,请参考以下文章