【问题标题】:Contextual action bar weird behavior for menu item菜单项的上下文操作栏奇怪行为
【发布时间】:2014-11-02 18:33:05
【问题描述】:

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

首先:

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

第二次/第三次:

有没有办法让图标不占用太多空间?

当我将添加属性 android:showAsAction="always" 更改为所有项目时,实际上有足够的空间来显示所有图标 - 但是我的共享图标不再可点击:

清理项目没有帮助。

我在我的测试设备 (Galaxy S3) 上使用 Android 4.2.2。

我什至尝试在我的XXX GS3 上完全刷新一个新 ROM(CyanogenMod 10.1,在 SlimBean 之前,还删除了底部的导航栏) - 没有帮助。

我也在Nexus 4 上尝试过。有更多的空间,所以分享按钮和删除按钮是可见的。当我开始操作模式时,共享按钮不可点击,但是当我将设备切换到横向模式时它可以工作,当我将它转回纵向时它仍然可以工作。所以基本上在 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);
        }
    }
};

【问题讨论】:

  • 您在设备上使用 v14,还是针对 v14 SDK 进行编译?
  • wtf 为什么投反对票??无论如何,我在我的设备上使用 4.2.2 - 检查编辑以进行澄清
  • 那不是我,如果您针对 v14 进行编译,我会首先尝试针对最新的 SDK 进行编译。
  • 针对 minSdkVersion=17 编译没有区别。 (不适用于第一个问题,也不适用于第二个问题)
  • 如果只留下inflating menu,没有其他东西(比如ShareActionProvider等),行为会改变吗?

标签: android contextual-action-bar


【解决方案1】:

好的,无法点击的共享图标的解决方案。这是我对 API 的一种误解。

我认为您可以将SharedActionProvider-Item 视为菜单 XML 文件中的所有其他项目。但实际上你不能。 onActionItemClicked 在显示为操作时甚至不会触发此图标(这就是为什么添加 showAsAction=always 时它不可点击的原因)。有趣的是,当图标未显示时触发点击事件,但在溢出菜单中可见。 这可能是上下文操作栏中的实际错误!

现在我终于知道应该如何触发SharedActionProvider-Item

您必须 (!) 在 onCreateActionMode 方法中添加一个 Intent

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

现在你可能会说:“你这个白痴,这很明显,最好将意图始终设置在那里,而不是像以前那样在 onActionItemClickedMethod 中设置”。

对不起,我不同意:在这里设置它没有任何意义。原因是:对我来说,您检查的每一个附加项目都会改变意图。它为您检查的每个项目创建一个导出 XML 文件,我真的不想在每次单击图标时创建一个 XML 文件。这是没有意义的,我希望只有在用户真正想要导出项目时才创建所有 XML 文件。

所以基本上我为此做了一个解决方法。一开始,我创建了一个Intent 并添加了一个空的List&lt;Uri&gt;。这个列表作为成员变量保存在我的类中,所以如果我向它添加项目,这些项目也将在意图中。然后,当用户单击共享项目时,列表将填充所有选定的项目。为了做到这一点,我覆盖了OnShareTargetSelectedListener。当用户点击具体的共享目标(如电子邮件、保管箱等)时会触发此方法。

现在这是完整的代码(该方法仅从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);
}

我希望你明白我在那里做了什么。如果没有,请随时询问。

通过以上所有这些,我的一个问题得到了解决(共享图标在显示为图标时不可点击)-但其他两个保持打开状态(图标不应占用太多空间和第一个问题)。


问题2解决了:

似乎 Android 需要更高分辨率文件夹(hdpi、xhdpi)中的图标才能真正具有更高的分辨率 - 我的启用/禁用图标只有 32x32 像素的大小(我只是将它们放在所有文件夹中),因此 Android 不知何故弄得一团糟,所以操作栏上只有三个图标。我刚刚删除了所有图标,但 mdpi 中的原始图标为 32x32 像素。现在 Android 升级了 32x32 像素的图标,并且可以在操作栏中显示五个项目。有点奇怪。


问题 1 已解决:

看来这和问题2有直接关系,我一解决问题2,删除图标就直接放在了操作栏上。

此外,通过一些测试,我发现如果我将showAsAction=never 添加到删除图标,文本始终存在。我真的认为这与问题 2 有关(图标确实在那里做了坏事)。


我的问题几乎解决了。

我想我现在遇到了一个(新)真正的错误:最近使用的分享操作漂浮在溢出图标上。点击那里时,溢出菜单仍然打开,但看起来很糟糕:

我是如何解决这个问题的?

好吧,我已经不再搞砸这个****了,所以我只是将showAsAction=never添加到了共享图标中。 (是的,我看到了this,但如果我这样做,我会得到一个例外,这也是正常生命周期的另一个变化......)

如果您知道比我使用的更好的解决方案,请随时发表评论:>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多