上下文操作栏怪异的行为的菜单项 [英] Contextual action bar weird behavior for menu item

查看:276
本文介绍了上下文操作栏怪异的行为的菜单项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一些怪异的行为在上下文动作吧。

第一:

一个菜单项时,才会显示每一秒时间我点击了溢出按钮:

二/三:

有没有一种方法,该图标不使用这么大的空间?

当我更改添加属性安卓showAsAction =总是来的所有项目,实际上有足够的空间来显示所有的图标 - 的的我的共享图标无法点击了:

清理项目的没有帮助。

我采用Android 4.2.2我的测试设备(银河S3)上。

我甚至想完全一个新ROM我 XXX GS3(的的CyanogenMod 10.1 现在,之前的 SlimBean ,还取消了导航栏的底部) - 没有帮助

我也试了一下在的Nexus 4 。还有更多的空间,所以分享按钮和删除按钮是可见的。 Share按钮的不是的点击,当我开始行动模式,但是当我打开设备为横向模式下,它的工作原理,当我打开它为纵向它仍然有效。因此basicially上的Nexus 4,共享按钮不旋转的前工作。


清单:

 <使用-SDK安卓的minSdkVersion =14机器人:targetSdkVersion =17/>
 

编译反对的minSdkVersion = 17 没什么区别。

我开始行动模式从这样一个片段:

  mActionMode = activity.startActionMode(mMultipleCallback);
 

ActionMode.Callback 我填充菜单:

  @覆盖
公共布尔onCreateActionMode(ActionMode模式,菜单菜单){
    MenuInflater充气= mode.getMenuInflater();
    inflater.inflate(R.menu.management_cab,菜单);
    菜单项项= menu.findItem(R.id.managementCABShare);
    mShareActionProvider =(ShareActionProvider)item.getActionProvider();
    //...其他的东西
    返回true;
}
 

这里是XML:

 < XML版本=1.0编码=UTF-8&GT?;
<菜单的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>
    <项目
        机器人:标题=@字符串/ checkAll
        机器人:ID =@ + ID / managementCABCheckAll
        机器人:图标=@机器人:可绘制/ checkbox_on_background>
    < /项目>
    <项目
        机器人:标题=@字符串/启用
        机器人:ID =@ + ID / managementCABEnable
        机器人:图标=@可绘制/ sphere_green>
    < /项目>
    <项目
        机器人:标题=@字符串/禁用
        机器人:ID =@ + ID / managementCABDisable
        机器人:图标=@可绘制/ sphere_red>
    < /项目>
    <项目
        机器人:标题=@字符串/删除
        机器人:ID =@ + ID / managementCABDelete
        机器人:图标=@机器人:可绘制/ ic_menu_close_clear_cancel>
    < /项目>
    <项目
        机器人:标题=@字符串/股
        机器人:ID =@ + ID / managementCABShare
        机器人:actionProviderClass =android.widget.ShareActionProvider
        机器人:图标=@机器人:可绘制/ ic_menu_share>
    < /项目>
    <项目
        机器人:标题=@字符串/导出
        机器人:ID =@ + ID / managementCABExport
        机器人:图标=@可绘制/资源管理器>
    < /项目>
< /菜单>
 

为了完整起见全回调

 保护ActionMode.Callback mMultipleCallback =新ActionMode.Callback(){

    私人ShareActionProvider mShareActionProvider;

    @覆盖
    公共布尔onCreateActionMode(ActionMode模式,菜单菜单){
        MenuInflater充气= mode.getMenuInflater();
        inflater.inflate(R.menu.management_cab,菜单);
        菜单项项= menu.findItem(R.id.managementCABShare);
        mShareActionProvider =(ShareActionProvider)item.getActionProvider();
        hideUnwantedCABItems(菜单);
        返回true;
    }

    @覆盖
    公共布尔onActionItemClicked(ActionMode模式,菜单项项){
        名单<整数GT; checkedPositions = getAllCheckedPositions();
        开关(item.getItemId()){
        案例R.id.managementCABCheckAll:
            changeCheckedOfAllItems(真正的);
            返回true;
        案例R.id.managementCABEnable:
            changeEnabled(checkedPositions,真正的);
            返回true;
        案例R.id.managementCABDisable:
            changeEnabled(checkedPositions,假);
            返回true;
        案例R.id.managementCABDelete:
            如果(deleteAlert == NULL)
                createDeleteDialog(checkedPositions);
            initDeleteDialog(checkedPositions);
            返回true;
        案例R.id.managementCABShare:
            意图shareIntent =新意图();
            shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
            shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM,exportItemsAndGetUris(checkedPositions));
            shareIntent.setType(应用程序/ XML);
            setShareIntent(shareIntent);
            返回true;
        案例R.id.managementCABExport:
            字符串消息;
            如果(StorageController.copyUriListToExportFolder(exportItemsAndGetUris(checkedPositions)))
                消息= getActivity()的getString(R.string.export_success)。
            其他
                消息= getActivity()的getString(R.string.export_fail)。

            Toast.makeText(getActivity(),消息+:\ N+ StorageController.getExternalExportApplicationFolder(),Toast.LENGTH_LONG).show();
            返回true;
        默认:
            返回false;
        }
    }

    @覆盖
    公共无效onDestroyActionMode(ActionMode模式){
        mActionMode = NULL;
        changeCheckedOfAllItems(假);
    }

    @覆盖
    在prepareActionMode公共布尔(ActionMode模式,菜单菜单){
        返回false;
    }

    私人无效setShareIntent(意向shareIntent){
        如果(mShareActionProvider!= NULL){
            mShareActionProvider.setShareIntent(shareIntent);
        }
    }
};
 

解决方案

好了,解决了无法点击共享图标。这是怎样的一个误解,从我的API。

我想你可以把一个 SharedActionProvider-项目就像在你的菜单的XML文件中的每个其他项目。但实际上你不能。 onActionItemClicked 竟然没有触发该图标时,它的表现为一个动作(这就是为什么当您添加它不是可点击 showAsAction始终= )。够搞怪,当图标不显示的点击事件被触发,但在溢出菜单中看到。 这可能是在上下文操作栏中实际的错误!

现在,我终于想通了,你应该如何触发 SharedActionProvider-项目

您必须把意图 onCreateActionMode 办法(!):

 公共布尔onCreateActionMode(ActionMode模式,菜单菜单){
    MenuInflater充气= mode.getMenuInflater();
    inflater.inflate(R.menu.management_cab,菜单);
    菜单项项= menu.findItem(R.id.managementCABShare);
    initSharedActionProvider(项目); //看看这个方法在未来的code片段
    返回false;
}
 

现在你可能会说:你这个白痴,这是显而易见的,它甚至更好,因为你以前那样设置的意图一直存在,而不是作为 onActionItemClicked 办法

很抱歉,但我不同​​意:它并没有真正意义的在这里设置。其原因是:对我来说,与你检查每增加一个项目的意图变化。它会为你检查每个项目一个以出口为XML文件,我真的不希望有一个图标,点击每次创建一个XML文件。这是没有意义的,我想要创建的所有的XML文件,只有当用户真正想要导出的项目。

所以基本上我做了一个解决此。在开始的时候,我做了意图并添加一个空的名单,其中,乌里> 。这个列表保存为我的类成员变量,因此,如果我添加项目,该项目也将在意图。然后,当用户点击分享项目,该列表中填充所有选定的项目。要做到这一点我推翻了 OnShareTargetSelectedListener 。当用户点击一个具体份额目标该方法被触发(如电子邮件,Dropbox的,等等)。

现在,这里的整个code为(该方法只从被调用一次 onCreateActionMode ):

 私人无效initSharedActionProvider(菜单项项){
    mShareActionProvider =(ShareActionProvider)item.getActionProvider();
    mShareActionProvider.setOnShareTargetSelectedListener(新OnShareTargetSelectedListener(){
        @覆盖
        公共布尔onShareTargetSelected(ShareActionProvider源,意向意图){

            //这里是exportedFiles列表填充
            exportItemsAndSetList(getAllCheckedPositions());
            返回true;
        }
    });

    意图shareIntent =新意图();
    shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);

    // exportedFiles是一个成员变量,我填充选定的项目,与exportItemsAndSetList方法
    shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM,exportedFiles);
    shareIntent.setType(应用程序/ XML);
    mShareActionProvider.setShareIntent(shareIntent);
}
 

我希望你明白我所做的存在。如果不是,随便问。

通过这一切之上,我的问题之一是解决(即共享图标时,显示为图标无法点击) - 但其他两个保持开放(图标shouln't使用这么大的空间和第一个问题)。


问题2种解决:

好像Android的需要这是在更高的分辨率文件夹(华电国际,xhdpi)真的是在一个更高的分辨率的图标 - 我的启用/禁用图标具有32×32像素只有大小(我只是把他们的所有文件夹因此)和Android取得了很大的混乱不知何故,所以只有三个图标都适合在操作栏。我只是删除了所有的图标,但原有的在MDPI 32x32像素。现在的Andr​​oid upscales的32x32像素的图标,可以显示五个项目中的动作条。这是一种奇怪的。


问题1种解决:

看起来这是直接关系到问题2,只要我解决了问题2,删除图标直接放在行动上吧。

另外有一些测试,我看到的文字总是在那里,如果我加入 showAsAction =从不来删除图标。我真的觉得有一些东西需要与问题2(图标真的不好的东西在那里)。


我的问题几乎都解决了。

我觉得我得到了一个(新)现实的bug 现在:最近使用的共享动作是浮在溢图标。当点击那里,溢出菜单仍然打开,但它看起来pretty的低劣的:

我是怎么解决这个问题?

嗯,我做与此****乱搞,所以我刚添加的 showAsAction =从不来共享图标。 (是的,我看到了<一个href="http://stackoverflow.com/questions/10706564/how-do-you-turn-off-share-history-when-using-shareactionprovider">this,但我得到一个异常,如果我这样做,也是它的正常生命周期的另一个变化......)

随意评论,如果你知道的比我以前更好的解决方案:>

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:

Clean Project does not help.

I use Android 4.2.2 on my test device (Galaxy S3).

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.

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.


Manifest:

<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="17" />

Compiling against minSdkVersion=17 makes no difference.

I start the Action Mode from a fragment like this:

mActionMode = activity.startActionMode(mMultipleCallback);

In the ActionMode.Callback I populate the menu:

@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 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);
        }
    }
};

解决方案

Okay, the solution to the unclickable share icon. This was kind of a misunderstanding from me to the 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!

Now I finally figured out how you should trigger a SharedActionProvider-Item:

You have to (!) put a Intent in the onCreateActionMode method:

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 onActionItemClickedMethod as you did before".

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.

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):

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:

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.


Problem 1 kind of solved:

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.

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).


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:

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...)

Feel free to comment if you a know better solution than I used :>

这篇关于上下文操作栏怪异的行为的菜单项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆