菜单项语境动作条怪异的行为(Contextual action bar weird behavior

2019-09-01 01:45发布

我在上下文操作栏中的一些怪异的行为。

首先:

一个菜单项时,才会显示每次我第二次点击按钮溢出:

其次/第三:

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

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

清理项目没有帮助。

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

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

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


表现:

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

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

我开始从这样的片段操作模式:

mActionMode = activity.startActionMode(mMultipleCallback);

ActionMode.Callback我填充菜单:

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

这里是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>

为了完整整的缘故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);
        }
    }
};

Answer 1:

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



文章来源: Contextual action bar weird behavior for menu item