I have some weird behavior in the contextual action bar.
我在上下文动作栏里有一些奇怪的行为。
Firstly:
首先:
One menu item is only shown every second time I click on the overflow button:
每次我点击溢出按钮时,只显示一个菜单项:
Secondly / thirdly:
第二/第三:
Is there a way that the icons do not use so much space?
有没有一种方法可以让图标不占用太多空间?
When I change add property android:showAsAction="always"
to all items, there is actually enough space to show all icons - but my share icon is not clickable anymore:
当我更改添加属性android:showAsAction="always"时,实际上有足够的空间显示所有的图标——但我的分享图标不再可点击:
Clean Project does not help.
清洁项目没有帮助。
I use Android 4.2.2 on my test device (Galaxy S3).
我在我的测试设备(Galaxy S3)上使用Android 4.2.2。
I even tried to completely flash a new ROM on my XXX GS3 (CyanogenMod 10.1 now, before SlimBean, also removed the navigationbar at at the bottom) - did not help.
我甚至尝试在我的XXX GS3上完全刷新一个新的ROM (CyanogenMod 10.1,在SlimBean之前,也删除了底部的navigationbar)——但没有任何帮助。
I also tried it on a Nexus 4. There is more space, so the share button and the delete button are visible. The share button is not clickable when I start action mode, but when I turn the device to landscape mode it works, and when I turn it back to portrait it still works. So basicially on the Nexus 4, the share button does not work before rotating.
我还在Nexus 4上试用过。有更多的空间,所以共享按钮和删除按钮是可见的。当我启动动作模式时,分享按钮不是可点击的,但是当我将设备转到横屏模式时,它就可以工作,当我将它转回竖屏模式时,它仍然可以工作。因此,在Nexus 4上,共享按钮在旋转之前不会工作。
Manifest:
清单:
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />
Compiling against minSdkVersion=17
makes no difference.
根据minSdkVersion=17编译没有区别。
I start the Action Mode from a fragment like this:
我从这样的片段开始动作模式:
mActionMode = activity.startActionMode(mMultipleCallback);
In the ActionMode.Callback
I populate the menu:
ActionMode。回调I填充菜单:
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.management_cab, menu);
MenuItem item = menu.findItem(R.id.managementCABShare);
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
//...other stuff
return true;
}
And here is the XML:
这是XML:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:title="@string/checkAll"
android:id="@+id/managementCABCheckAll"
android:icon="@android:drawable/checkbox_on_background">
</item>
<item
android:title="@string/enable"
android:id="@+id/managementCABEnable"
android:icon="@drawable/sphere_green">
</item>
<item
android:title="@string/disable"
android:id="@+id/managementCABDisable"
android:icon="@drawable/sphere_red">
</item>
<item
android:title="@string/delete"
android:id="@+id/managementCABDelete"
android:icon="@android:drawable/ic_menu_close_clear_cancel">
</item>
<item
android:title="@string/share"
android:id="@+id/managementCABShare"
android:actionProviderClass="android.widget.ShareActionProvider"
android:icon="@android:drawable/ic_menu_share">
</item>
<item
android:title="@string/export"
android:id="@+id/managementCABExport"
android:icon="@drawable/explorer">
</item>
</menu>
For the sake of completeness the whole callback
:
为了完整起见,整个回调:
protected ActionMode.Callback mMultipleCallback = new ActionMode.Callback() {
private ShareActionProvider mShareActionProvider;
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.management_cab, menu);
MenuItem item = menu.findItem(R.id.managementCABShare);
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
hideUnwantedCABItems(menu);
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
List<Integer> checkedPositions = getAllCheckedPositions();
switch (item.getItemId()) {
case R.id.managementCABCheckAll:
changeCheckedOfAllItems(true);
return true;
case R.id.managementCABEnable:
changeEnabled(checkedPositions, true);
return true;
case R.id.managementCABDisable:
changeEnabled(checkedPositions, false);
return true;
case R.id.managementCABDelete:
if (deleteAlert == null)
createDeleteDialog(checkedPositions);
initDeleteDialog(checkedPositions);
return true;
case R.id.managementCABShare:
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, exportItemsAndGetUris(checkedPositions));
shareIntent.setType("application/xml");
setShareIntent(shareIntent);
return true;
case R.id.managementCABExport:
String message;
if (StorageController.copyUriListToExportFolder(exportItemsAndGetUris(checkedPositions)))
message = getActivity().getString(R.string.export_success);
else
message = getActivity().getString(R.string.export_fail);
Toast.makeText(getActivity(), message + ":\n" + StorageController.getExternalExportApplicationFolder(), Toast.LENGTH_LONG).show();
return true;
default:
return false;
}
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
changeCheckedOfAllItems(false);
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
private void setShareIntent(Intent shareIntent) {
if (mShareActionProvider != null) {
mShareActionProvider.setShareIntent(shareIntent);
}
}
};
1 个解决方案
#1
9
Okay, the solution to the unclickable share icon. This was kind of a misunderstanding from me to the API.
好的,不可点击分享图标的解决方案。这是我对API的一种误解。
I thought you could treat a SharedActionProvider-Item
like every other item in your menu XML file. But actually you can't. onActionItemClicked
is not even triggered for this icon when it's shown as an action (this is why it's not clickable when you add showAsAction=always
). Funny enough, the click event is triggered when the icon is not shown, but it is visible in the overflow menu. This may be an actual bug in the contextual action bar!
我认为您可以将SharedActionProvider-Item与您的菜单XML文件中的其他条目一样对待。但实际上你不能。当这个图标显示为动作时,onactionitemclick甚至没有被触发(这就是为什么当你添加showAsAction=always时它不能被点击)。有趣的是,单击事件在图标未显示时被触发,但在溢出菜单中是可见的。这可能是上下文动作栏中的实际错误!
Now I finally figured out how you should trigger a SharedActionProvider-Item
:
现在我终于明白了如何触发SharedActionProvider-Item:
You have to (!) put a Intent
in the onCreateActionMode
method:
你必须在onCreateActionMode方法中加入意图:
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.management_cab, menu);
MenuItem item = menu.findItem(R.id.managementCABShare);
initSharedActionProvider(item); //Check out this method in the next code fragment
return false;
}
Now you may say: "You idiot, this was obvious, and it's even better to set the intent always there instead as in the onActionItemClicked
Method as you did before".
现在你可能会说:“你这个白痴,这是显而易见的,最好将意图始终设置在那里,而不是像以前那样在onActionItemClickedMethod中那样。”
Sorry, but I disagree: It does not really make sense to set it here. The reason is: For me the intent changes with every additional item you check. It creates an export-XML file for each item you check, and I really don't want to create an XML file each time an icon is clicked. This makes no sense, and I want all XML files to be created only when a user really wants to export the items.
对不起,但我不同意:在这里设置它并没有什么意义。原因是:对我来说,意图随着你检查的每一项而改变。它为您选中的每个项目创建一个导出XML文件,我真的不希望每次单击图标时都创建一个XML文件。这毫无意义,我希望所有XML文件只在用户真正想要导出项时创建。
So basically I made a workaround for this. At the beginning, I make an Intent
and add an empty List<Uri>
. This list is saved as a member variable in my class, so if I add items to it, the items will also be in the intent. Then when the user clicks the share item, the list is populated with all selected items. To accomplish this I overrode the OnShareTargetSelectedListener
. This method is triggered when a user clicks on a concrete share target (like email, dropbox, etc.).
所以基本上我做了一个变通。在开始时,我创建了一个意图并添加了一个空列表
Now here's the whole code for that (the method is only called once from onCreateActionMode
):
这里是整个代码(该方法仅从onCreateActionMode调用一次):
private void initSharedActionProvider(MenuItem item) {
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
mShareActionProvider.setOnShareTargetSelectedListener(new OnShareTargetSelectedListener() {
@Override
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
//Here is the exportedFiles list populated
exportItemsAndSetList(getAllCheckedPositions());
return true;
}
});
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
//exportedFiles is a member Variable which I populate with the selected items, with the exportItemsAndSetList method
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, exportedFiles);
shareIntent.setType("application/xml");
mShareActionProvider.setShareIntent(shareIntent);
}
I hope you understand what I did there. If not, feel free to ask.
我希望你能理解我在那里做了什么。如果没有,请尽管问。
With all this above, one of my problems is solved (that the share icon is not clickable when shown as an icon) - but the other two remain open (icons shouln't use so much space and the first problem).
有了以上这些,我的一个问题就解决了(当显示为图标时,共享图标不能点击)——但是另外两个仍然是打开的(图标不应该占用太多空间,第一个问题)。
Problem 2 kind of solved:
问题2解决了
Seems like Android needs the icons which are in the higher resolution folders (hdpi, xhdpi) really to be in a higher resolution - my enable / disable icon had only a size of 32x32 pixels (and I just put them in all folders) and therefore Android made a big mess somehow, so only three icons did fit on the action bar. I just removed all icons, but the original ones of 32x32 pixels in mdpi. Now Android upscales the 32x32 pixels icons and can display five items in the actionbar. It is kind of strange.
似乎是Android需要更高分辨率的文件夹的图标(hdpi xhdpi)真的是高分辨率——我的启用/禁用图标只有一个大小为32 x32像素(我只是把它们放在所有文件夹),因此Android大混乱,所以只有三个图标在操作栏。我刚刚删除了所有的图标,但是原始的是mdpi中的32x32像素。现在,Android升级了32x32像素的图标,可以在actionbar中显示5个项目。这有点奇怪。
Problem 1 kind of solved:
问题1解决了:
Looks like this was directly related to problem 2, as soon as I solved problem 2, the delete icon was placed directly on the action bar.
看起来这与问题2直接相关,一旦我解决了问题2,删除图标就会直接放在操作栏上。
Also with some testing I saw that the text was always there if I added showAsAction=never
to the delete icon. I really think it had something to do with problem 2 (the icons really did bad stuff there).
另外,通过一些测试,我发现如果我向删除图标添加showAsAction=never,文本始终存在。我真的认为这和问题2有关(图标确实在那里做了坏事)。
My problems are almost solved.
我的问题差不多解决了。
I think I got a (new) real bug now: the most recently used share action is floating over the overflow icon. When clicking there, the overflow menu still opens, but it looks pretty shitty:
我想我现在有了一个(新的)真正的bug:最近使用的共享操作在溢出图标上浮动。当点击这里时,溢出菜单仍然打开,但是看起来很糟糕:
How did I fix this?
我怎么修复的?
Well I'm done with messing around with this ****, so I just added the showAsAction=never
to the share icon. (And yes I saw this, but I get an exception if I do this, also it's another change of the normal lifecycle...)
我已经做完了这个****,所以我只是添加了showAsAction=从没有到共享图标。(是的,我看到了这个,但如果我这样做,我就会有一个例外,这也是正常生命周期的另一个变化……)
Feel free to comment if you a know better solution than I used :>
如果您知道比我使用的更好的解决方案,请随时发表意见:>
#1
9
Okay, the solution to the unclickable share icon. This was kind of a misunderstanding from me to the API.
好的,不可点击分享图标的解决方案。这是我对API的一种误解。
I thought you could treat a SharedActionProvider-Item
like every other item in your menu XML file. But actually you can't. onActionItemClicked
is not even triggered for this icon when it's shown as an action (this is why it's not clickable when you add showAsAction=always
). Funny enough, the click event is triggered when the icon is not shown, but it is visible in the overflow menu. This may be an actual bug in the contextual action bar!
我认为您可以将SharedActionProvider-Item与您的菜单XML文件中的其他条目一样对待。但实际上你不能。当这个图标显示为动作时,onactionitemclick甚至没有被触发(这就是为什么当你添加showAsAction=always时它不能被点击)。有趣的是,单击事件在图标未显示时被触发,但在溢出菜单中是可见的。这可能是上下文动作栏中的实际错误!
Now I finally figured out how you should trigger a SharedActionProvider-Item
:
现在我终于明白了如何触发SharedActionProvider-Item:
You have to (!) put a Intent
in the onCreateActionMode
method:
你必须在onCreateActionMode方法中加入意图:
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.management_cab, menu);
MenuItem item = menu.findItem(R.id.managementCABShare);
initSharedActionProvider(item); //Check out this method in the next code fragment
return false;
}
Now you may say: "You idiot, this was obvious, and it's even better to set the intent always there instead as in the onActionItemClicked
Method as you did before".
现在你可能会说:“你这个白痴,这是显而易见的,最好将意图始终设置在那里,而不是像以前那样在onActionItemClickedMethod中那样。”
Sorry, but I disagree: It does not really make sense to set it here. The reason is: For me the intent changes with every additional item you check. It creates an export-XML file for each item you check, and I really don't want to create an XML file each time an icon is clicked. This makes no sense, and I want all XML files to be created only when a user really wants to export the items.
对不起,但我不同意:在这里设置它并没有什么意义。原因是:对我来说,意图随着你检查的每一项而改变。它为您选中的每个项目创建一个导出XML文件,我真的不希望每次单击图标时都创建一个XML文件。这毫无意义,我希望所有XML文件只在用户真正想要导出项时创建。
So basically I made a workaround for this. At the beginning, I make an Intent
and add an empty List<Uri>
. This list is saved as a member variable in my class, so if I add items to it, the items will also be in the intent. Then when the user clicks the share item, the list is populated with all selected items. To accomplish this I overrode the OnShareTargetSelectedListener
. This method is triggered when a user clicks on a concrete share target (like email, dropbox, etc.).
所以基本上我做了一个变通。在开始时,我创建了一个意图并添加了一个空列表
Now here's the whole code for that (the method is only called once from onCreateActionMode
):
这里是整个代码(该方法仅从onCreateActionMode调用一次):
private void initSharedActionProvider(MenuItem item) {
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
mShareActionProvider.setOnShareTargetSelectedListener(new OnShareTargetSelectedListener() {
@Override
public boolean onShareTargetSelected(ShareActionProvider source, Intent intent) {
//Here is the exportedFiles list populated
exportItemsAndSetList(getAllCheckedPositions());
return true;
}
});
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
//exportedFiles is a member Variable which I populate with the selected items, with the exportItemsAndSetList method
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, exportedFiles);
shareIntent.setType("application/xml");
mShareActionProvider.setShareIntent(shareIntent);
}
I hope you understand what I did there. If not, feel free to ask.
我希望你能理解我在那里做了什么。如果没有,请尽管问。
With all this above, one of my problems is solved (that the share icon is not clickable when shown as an icon) - but the other two remain open (icons shouln't use so much space and the first problem).
有了以上这些,我的一个问题就解决了(当显示为图标时,共享图标不能点击)——但是另外两个仍然是打开的(图标不应该占用太多空间,第一个问题)。
Problem 2 kind of solved:
问题2解决了
Seems like Android needs the icons which are in the higher resolution folders (hdpi, xhdpi) really to be in a higher resolution - my enable / disable icon had only a size of 32x32 pixels (and I just put them in all folders) and therefore Android made a big mess somehow, so only three icons did fit on the action bar. I just removed all icons, but the original ones of 32x32 pixels in mdpi. Now Android upscales the 32x32 pixels icons and can display five items in the actionbar. It is kind of strange.
似乎是Android需要更高分辨率的文件夹的图标(hdpi xhdpi)真的是高分辨率——我的启用/禁用图标只有一个大小为32 x32像素(我只是把它们放在所有文件夹),因此Android大混乱,所以只有三个图标在操作栏。我刚刚删除了所有的图标,但是原始的是mdpi中的32x32像素。现在,Android升级了32x32像素的图标,可以在actionbar中显示5个项目。这有点奇怪。
Problem 1 kind of solved:
问题1解决了:
Looks like this was directly related to problem 2, as soon as I solved problem 2, the delete icon was placed directly on the action bar.
看起来这与问题2直接相关,一旦我解决了问题2,删除图标就会直接放在操作栏上。
Also with some testing I saw that the text was always there if I added showAsAction=never
to the delete icon. I really think it had something to do with problem 2 (the icons really did bad stuff there).
另外,通过一些测试,我发现如果我向删除图标添加showAsAction=never,文本始终存在。我真的认为这和问题2有关(图标确实在那里做了坏事)。
My problems are almost solved.
我的问题差不多解决了。
I think I got a (new) real bug now: the most recently used share action is floating over the overflow icon. When clicking there, the overflow menu still opens, but it looks pretty shitty:
我想我现在有了一个(新的)真正的bug:最近使用的共享操作在溢出图标上浮动。当点击这里时,溢出菜单仍然打开,但是看起来很糟糕:
How did I fix this?
我怎么修复的?
Well I'm done with messing around with this ****, so I just added the showAsAction=never
to the share icon. (And yes I saw this, but I get an exception if I do this, also it's another change of the normal lifecycle...)
我已经做完了这个****,所以我只是添加了showAsAction=从没有到共享图标。(是的,我看到了这个,但如果我这样做,我就会有一个例外,这也是正常生命周期的另一个变化……)
Feel free to comment if you a know better solution than I used :>
如果您知道比我使用的更好的解决方案,请随时发表意见:>