1

由于某种原因,我的 Fragment 从未调用onCreateOptionsMenu过我的菜单,溢出菜单从未出现,并且在模拟器中按下菜单按钮也无济于事。我试过使用setHasOptionsMenu(true),但这也无济于事。有任何想法吗?

这是我的onCreate, onCreateOptionsMenu and onPrepareOptionsMenu

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setHasOptionsMenu(true);
    setMenuVisibility(true);
}

@Override
public void onPrepareOptionsMenu(Menu menu) {
    super.onPrepareOptionsMenu(menu); 
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    inflater.inflate(R.menu.main, menu);
    super.onCreateOptionsMenu(menu, inflater);
}

编辑:

完整的片段代码。

public class BackupFragment extends ExpandableListFragment {

    public static final Uri SMS_URI = Uri.parse("content://sms");
    private static final int CONTEXTMENU_IMPORT = 21;
    private static final int CONTEXTMENU_DELETEFILE = 22;
    private static final int CONTEXTMENU_DELETEDAY = 23;
    private static final int UPLOAD_DROPBOX = 24;
    private static final int UPLOAD_DRIVE = 25;
    private static final int DIALOG_LICENSEAGREEMENT = 1;
    private static final int DIALOG_ABOUT = 2;
    public static final int DIALOG_EXPORT = 4;
    public static final String STANDARD_DIRNAME = new StringBuilder(Environment.getExternalStorageDirectory().toString()).append("/backup/").toString();
    public static File DIR;
    public static final boolean CANHAVEROOT = checkRoot(); 
    public static BackupFragment INSTANCE;
    @SuppressWarnings("deprecation")
    public static final int API_LEVEL = Integer.parseInt(Build.VERSION.SDK);
    public BackupFilesListAdapter listAdapter;
    private AlertDialog deleteFileDialog;
    private AlertDialog deleteDayDialog;
    private ProgressDialog exportDialog;
    private ProgressDialog importDialog;
    private AlertDialog selectExportsDialog;
    private ExporterInfos exporterInfos;
    private View FragmentView;

    /**
     * Sets up the main content of the application (i.e. loads the list of
     * available backups and generates the context menu).
     */
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        FragmentView = inflater.inflate(R.layout.backup_fragment, container, false);
        //registerForContextMenu(FragmentView);
        return FragmentView;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        INSTANCE = this;
        super.onActivityCreated(savedInstanceState);
        Crittercism.init(getActivity().getApplicationContext(), "516574be558d6a5f8a00001f");

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity());

        String dirName = preferences.getString(Strings.PREFERENCE_STORAGELOCATION, STANDARD_DIRNAME);

        if (TextUtils.isEmpty(dirName)) {
            dirName = STANDARD_DIRNAME;
        }
        DIR = new File(dirName);

        listAdapter = new BackupFilesListAdapter(getActivity(), preferences);
        getExpandableListView().setAdapter(listAdapter);
        getExpandableListView().setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
                ExpandableListView.ExpandableListContextMenuInfo expandableInfo = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;

                menu.setHeaderTitle(((TextView) ((ExpandableListView.ExpandableListContextMenuInfo) menuInfo).targetView.findViewById(android.R.id.text1)).getText());
                if (ExpandableListView.getPackedPositionType(expandableInfo.packedPosition) == ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                    menu.add(0, CONTEXTMENU_IMPORT, Menu.NONE, R.string.button_import);
                    menu.add(0, CONTEXTMENU_DELETEFILE, Menu.NONE, R.string.contextmenu_deletefile);
                    menu.add(0, UPLOAD_DROPBOX, Menu.NONE, R.string.upload_dropbox);
                    menu.add(0, UPLOAD_DRIVE, Menu.NONE, R.string.upload_drive);
                } else {
                    menu.add(0, CONTEXTMENU_DELETEDAY, Menu.NONE, R.string.contextmenu_deletedaydata);
                }
            }
        });
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setHasOptionsMenu(true);
        setMenuVisibility(true);
    }

    @Override
    public void onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu); 
    }

    @Override
    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        inflater.inflate(R.menu.main, menu);
        super.onCreateOptionsMenu(menu, inflater);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Log.d(getClass().getSimpleName(), item.toString());
        switch (item.getItemId()) {
            case R.id.menu_about: {
                showDialog(DIALOG_ABOUT);
                break;
            }
            case CONTEXTMENU_DELETEFILE: {
                /* using "showDialog" with a Bundle is only available from api version 8 on, so we cannot directly use this. Lets impose this */

                long packedPosition = ((ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo()).packedPosition;

                if (ExpandableListView.getPackedPositionType(packedPosition) != ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                    break;
                }

                final File file = listAdapter.getChild(ExpandableListView.getPackedPositionGroup(packedPosition), ExpandableListView.getPackedPositionChild(packedPosition));

                if (deleteFileDialog == null) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

                    builder.setIcon(android.R.drawable.ic_dialog_alert);
                    builder.setTitle(android.R.string.dialog_alert_title);
                    builder.setPositiveButton(android.R.string.yes, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // just to enable the button
                        }
                    });
                    builder.setNegativeButton(android.R.string.no, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });
                    builder.setMessage(Strings.EMPTY); // just so that the string is available
                    deleteFileDialog = builder.create();
                }
                deleteFileDialog.show();
                deleteFileDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        if (!file.exists() || file.delete()) {
                            listAdapter.remove(file);
                        } else {
                            // show error
                        }
                        deleteFileDialog.dismiss();
                    }
                });
                deleteFileDialog.setMessage(String.format(getString(R.string.question_deletefile), file.toString()));
                break;
            }
            case CONTEXTMENU_IMPORT: {
                ExpandableListView.ExpandableListContextMenuInfo menuInfo = (ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo();

                long packedPosition = menuInfo.packedPosition;

                if (ExpandableListView.getPackedPositionType(packedPosition) != ExpandableListView.PACKED_POSITION_TYPE_CHILD) {
                    break;
                }
                if (importDialog == null) {
                    importDialog = new ProgressDialog(getActivity());
                }
                checkProgressDialog(importDialog);
                new ImportTask(importDialog, listAdapter.getChild(ExpandableListView.getPackedPositionGroup(packedPosition), ExpandableListView.getPackedPositionChild(packedPosition)), (Integer) menuInfo.targetView.getTag());
                break;
            }
            case CONTEXTMENU_DELETEDAY: {
                long packedPosition = ((ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo()).packedPosition;

                if (ExpandableListView.getPackedPositionType(packedPosition) != ExpandableListView.PACKED_POSITION_TYPE_GROUP) {
                    break;
                }

                final int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);

                Date date = listAdapter.getGroup(groupPosition);

                if (deleteDayDialog == null) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

                    builder.setIcon(android.R.drawable.ic_dialog_alert);
                    builder.setTitle(android.R.string.dialog_alert_title);
                    builder.setPositiveButton(android.R.string.yes, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            // just to enable the button
                        }
                    });
                    builder.setNegativeButton(android.R.string.no, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });
                    builder.setMessage(Strings.EMPTY); // just so that the string is available
                    deleteDayDialog = builder.create();
                }
                deleteDayDialog.show();
                deleteDayDialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener() {
                    public void onClick(View v) {
                        Vector<File> files = listAdapter.getChildren(groupPosition);

                        Vector<File> deletedFiles = new Vector<File>();

                        for (File file : files) {
                            if (!file.exists() || file.delete()) {
                                deletedFiles.add(file);
                            } else {
                                // show error
                            }
                        }
                        listAdapter.remove(deletedFiles);
                        deleteDayDialog.dismiss();
                    }
                });
                deleteDayDialog.setMessage(String.format(getString(R.string.question_deletefile), DateFormat.getDateInstance().format(date)));
                break;
            }
            case R.id.menu_exporteverything: {
                if (exportDialog == null) {
                    exportDialog = new ProgressDialog(getActivity());
                }
                checkProgressDialog(exportDialog);
                checkExportTaskForIncompleteData(new ExportTask(exportDialog, listAdapter, EverythingExporter.ID));
                break;
            }
            case R.id.menu_export: {
                if (selectExportsDialog == null) {
                    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

                    builder.setIcon(android.R.drawable.ic_dialog_info);
                    builder.setTitle(R.string.dialog_export);

                    exporterInfos = Exporter.getExporterInfos(getActivity());

                    builder.setNegativeButton(android.R.string.cancel, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.cancel();
                        }
                    });

                    builder.setItems(exporterInfos.names, new OnClickListener() {
                        public void onClick(DialogInterface dialog, int which) {
                            dialog.dismiss();
                            if (exportDialog == null) {
                                exportDialog = new ProgressDialog(getActivity());
                            }
                            checkProgressDialog(exportDialog);
                            checkExportTaskForIncompleteData(new ExportTask(exportDialog, listAdapter, exporterInfos.ids[which]));
                        }
                    });
                    selectExportsDialog = builder.create();
                }
                selectExportsDialog.show();
                break;
            }
            case R.id.menu_settings: {
                break;
            }           
            case UPLOAD_DROPBOX: {
                Intent i = new Intent(getActivity(), Dropbox.class);

                long packedPosition = ((ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo()).packedPosition;

                final File file = listAdapter.getChild(ExpandableListView.getPackedPositionGroup(packedPosition), ExpandableListView.getPackedPositionChild(packedPosition));
                i.putExtra("file", file.toString());
                i.putExtra("path", file.getName());

                startActivity(i);
                break;
            }
            case UPLOAD_DRIVE: {
                Intent i = new Intent(getActivity(), DriveAuth.class);

                long packedPosition = ((ExpandableListView.ExpandableListContextMenuInfo) item.getMenuInfo()).packedPosition;

                final File file = listAdapter.getChild(ExpandableListView.getPackedPositionGroup(packedPosition), ExpandableListView.getPackedPositionChild(packedPosition));
                i.putExtra("file", file.toString());
                i.putExtra("path", file.getName());

                startActivity(i);
            }

        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Checks if the exporter that is attached to the given ExportTask may
     * produce incomplete data and shows a warning if this is the case and
     * if the user wants to get notified. Note that the standard setting is
     * to show the warning.
     * The user may also cancel the warning dialog which results in the
     * export to be not performed.
     *
     * @param exportTask task whose exporter is checked w.r.t. incomplete
     *                   exports
     */
    private void checkExportTaskForIncompleteData(final ExportTask exportTask) {
        Exporter exporter = exportTask.getExporter();

        if (!PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean(Strings.PREFERENCE_HIDEDATAWARNINGS, false) && exporter.maybeIncomplete()) {
            AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

            builder.setTitle(android.R.string.dialog_alert_title);
            builder.setMessage(getString(R.string.warning_incompletedata_export, exporter.getIncompleteDataNames(getActivity())));
            builder.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                    exportTask.execute();
                }
            });
            builder.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.cancel();
                }
            });
            builder.setCancelable(true);
            builder.show();
        } else {
            exportTask.execute();
        }
    }

    /**
     * Here, the given progress dialog will be reset.
     *
     * @param dialog progress dialog to be reset
     */
    private void checkProgressDialog(ProgressDialog dialog) {
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setProgress(0);
        dialog.setMax(100);
        dialog.setMessage(Strings.EMPTY); // we just have to set some non-null value to enable the title
    }


    @Override
    public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) {
        if (importDialog == null) {
            importDialog = new ProgressDialog(getActivity());
        }
        checkProgressDialog(importDialog);
        new ImportTask(importDialog, listAdapter.getChild(groupPosition, childPosition), (Integer) v.getTag());

        return true;
    } 


    protected void showDialog(int id) {
        if (id == DIALOG_LICENSEAGREEMENT) {
            AlertDialogFragment myDialogFragment = AlertDialogFragment.newInstance();
            myDialogFragment.show(getFragmentManager(), "myDialogFragment");
        }
    } 



    /**
     * In order to perform certain backups (such as the wifi settings), we
     * need root to access the corresponding configuration files.
     *
     * @return true if <i>root</i> access can be obtained, <i>false</i>
     *         otherwise
     */
    private static boolean checkRoot() {
        try {
            Process process = Runtime.getRuntime().exec("/system/bin/ls -l /system/bin/su /system/xbin/su");

            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line = reader.readLine();

            reader.close();
            process.destroy();

            return line != null && line.length() > 9 && line.charAt(9) == 'x';
        } catch (Exception e) {
            return false;
        }
    }

}
4

2 回答 2

1

您可能在活动中夸大了内容而不是调用超级。

如果您在任何其他片段或活动中膨胀任何菜单项,您也应该调用super.onCrea ....它们。

常见菜单问题的另一个选项是,如果您使用操作栏 sherlock,您应该扩展 SherlockFragment 以使用菜单。

于 2013-04-16T13:37:49.830 回答
0

迁移到 ABS 而不是 Support 库似乎已经解决了问题,这可能是由于与我正在使用的 SlidingMenu 库发生冲突。

于 2013-04-16T15:08:11.853 回答