Android上下文菜单呈现两次

时间:2016-07-19 11:33:13

标签: android

我在应用程序中遇到的问题是在 API级别9 下运行 API级别11 (对于更高级别,它可以)。 我有一个继承 ListActivity 的活动,当用户长按一下时,对于此列表中的每个项目,都会显示一个上下文菜单。 问题是当运行API级别9/11时,上下文菜单会出现两次。 仍然无法弄清楚原因。 这是场景(代码):

的活动:

public class ActivityBoxList extends ToyshopActivity {

    public static final String SELECTED_BOX_ID = "selected_box_id";
    public static final String SELECTED_DATE_PERIOD = "selected_date_period";
    public static final int FILE_SELECT_CODE = 0;

    private BoxService boxService;
    private LinearLayout layoutBoxSubHeader;
    private LinearLayout layoutBoxLabelsSubHeader;
    private EntryService entryService;
    private ImageButton btnMainMenu, btnAddMonthIncome;
    private TextView txtSelectedDatePeriodMonth, txtSelectedDatePeriodYear, txtMonthIncomeSum, txtMonthOutgoSum, txtMonthBalance;
    private static BoxRepository boxRepository;
    private int selectedBoxIndex;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.box_list_view);

        context = this;
        boxService = BoxService.getInstance();
        entryService = EntryService.getInstance();
        initLayout();

        receiveSelectedDatePeriodBroadcast();
        registerForContextMenu(getListView());

        final BoxAdapter adapter = new BoxAdapter(this, getData());
        setListAdapter(adapter);

        registerForContextMenu(this.btnMainMenu);

        increaseAccessCounter();
    }

protected void onRestoreInstanceState(android.os.Bundle state) {
        selectedDatePeriod = (DatePeriod)state.get(ActivityBoxList.SELECTED_DATE_PERIOD);
    }

    @Override
    protected void onNewIntent(android.content.Intent intent) {
        selectedDatePeriod = (DatePeriod)intent.getSerializableExtra(ActivityBoxList.SELECTED_DATE_PERIOD);
        refreshListData(null);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void refreshListData(Long domainId) {
        Collection<Box> boxes = getData();
        setLayoutVisibility();
        BoxAdapter adapter = new BoxAdapter(context, boxes);
        setListAdapter(adapter);
        adapter.notifyDataSetChanged();
    }

this.btnMainMenu.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                openContextMenu(view);
            }
        });

        this.btnAddMonthIncome.setOnClickListener(new View.OnClickListener() {

            Dialog dialogAddIncome = new DialogAddMonthIncome(context);

            @Override
            public void onClick(View view) {
                if (DatePeriod.isSelectedPeriodActual(selectedDatePeriod)) {
                    dialogAddIncome.show();
                }
                else {
                    ToastOnMiddle.makeText(context, context.getString(R.string.txt_operation_not_permitted_not_actual_period), Integer.parseInt(context.getString(R.string.app_toast_time_long))).show();
                }
            }
        });
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        context = this;
    }


 private View.OnClickListener openIncomeListOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            openIncomeListActivity();
        }
    };

    @Override
    public void onCreateContextMenu(android.view.ContextMenu menu, android.view.View v, android.view.ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        if(v.getId() == getListView().getId()) {
            inflater.inflate(R.menu.context_menu_box, menu);
        } else if (v.getId() == R.id.btn_main_menu) {
            inflater.inflate(R.menu.main_menu, menu);
        }
    }

    @Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        Box box = ((Box)getListView().getItemAtPosition(selectedBoxIndex));
        if(!isFinishing()) {
            if (item.getItemId() == R.id.box_edit) {
                Dialog dialogEditBox = new DialogEditBox(context, box);
                dialogEditBox.show();
            } else if (item.getItemId() == R.id.box_delete) {
                new AlertDialogDelete(context, context.getString(R.string.txt_delete_box_confirm), new OnClickListenerDeleteBoxConfirm(context, box), null).show();
            } else if (item.getItemId() == R.id.main_menu_add_box) {
                Dialog dialogAddBox = new DialogAddBox(context);
                dialogAddBox.show();
            } else if (item.getItemId() == R.id.main_menu_delete_month_income) {
                openIncomeListActivity();
            } else if (item.getItemId() == R.id.main_menu_select_period) {
                Dialog dialogSelectPeriod = new DialogSelectPeriod(context, getSelectedDatePeriod());
                dialogSelectPeriod.show();
            } else if (item.getItemId() == R.id.main_menu_backup_data) {
                Dialog dialogDataBackup = new DialogDataBackup(context);
                dialogDataBackup.show();
            } else if (item.getItemId() == R.id.main_menu_help) {
                openHelpActivity();
            }
        }
        return true;
    }


}

适配器:

    public class BoxAdapter extends BaseAdapter {

    Collection<Box> boxes = new ArrayList<Box>(0);
    LayoutInflater inflater;
    Context context;

    public BoxAdapter(Context context, Collection<Box> boxes){
        this.boxes = boxes;
        this.context = context;
        this.inflater = LayoutInflater.from(this.context);
    }

    @Override
    public int getCount() {
        return boxes.size();
    }

    @Override
    public Object getItem(int i) {
        return ((ArrayList<Box>) boxes).get(i);
    }

    @Override
    public long getItemId(int i) {
        return i > 0 ? ((ArrayList<Box>) boxes).get(i).getId() : 0;
    }

    @Override
    public View getView(final int i, View view, ViewGroup viewGroup) {
        View v = view;
        final ViewHolderBoxItem viewHolder;
        if (view == null) {
            final LayoutInflater li = (LayoutInflater) this.context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            v = li.inflate(R.layout.box_list_view_item, null);
            viewHolder = new ViewHolderBoxItem(v);
            v.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolderBoxItem) v.getTag();
        }

        final Box box = ((ArrayList<Box>) boxes).get(i);
        viewHolder.boxItemDescription.setText(box.getDescription());
        viewHolder.boxItemValue.setText(box.getFormattedOutgoSum(this.context));
        viewHolder.boxImage.setImageResource(resolveImageFor(box));
        viewHolder.boxOutgoesBar.setBarSize(box.getBarSize());
        viewHolder.boxOutgoesBar.setDomain(box);
        viewHolder.layout.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                startActivityEntryList(box, ((ActivityBoxList)context).getSelectedDatePeriod());
            }
        });
        viewHolder.layout.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                ((ActivityBoxList)context).setSelectedBoxIndex(i+1);
                ((ActivityBoxList)context).openContextMenu(((ActivityBoxList)context).getListView());
                return false;
            }
        });

        return v;
    }
}

如您所见,长按侦听器附加在适配器中(仅一次):

viewHolder.layout.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                ((ActivityBoxList)context).setSelectedBoxIndex(i+1);
                ((ActivityBoxList)context).openContextMenu(((ActivityBoxList)context).getListView());
                return false;
            }
        });

我也只注册一次上下文菜单(onCreate):

registerForContextMenu(getListView());

我无法弄清楚为什么当我长按一下时,上下文菜单会出现两次。 欢迎任何帮助!

1 个答案:

答案 0 :(得分:1)

我对解决方案不满意但...... 要修复它,我必须在膨胀之前关闭菜单(menu.close()):

@Override
public void onCreateContextMenu(android.view.ContextMenu menu, android.view.View v, android.view.ContextMenu.ContextMenuInfo menuInfo) {
    menu.close(); //This fixes issue (duplicated menu) in Android APIs under version 15.
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getMenuInflater();
    if(v.getId() == getListView().getId()) {
        inflater.inflate(R.menu.context_menu_box, menu);
    } else if (v.getId() == R.id.btn_main_menu) {
        inflater.inflate(R.menu.main_menu, menu);
    }
}

如果有人弄清楚这是什么原因并发布更好的答案,我会很高兴的!