首页 > 解决方案 > 如何将上下文菜单添加到表格布局?

问题描述

各位程序员好

我正在尝试自己在一个应用程序上记录我所做的所有费用。我在表单中输入我的信息,将其添加到 SQLite 数据库并在 TableLayout 的新活动中显示它。一切都很好,直到那里,或多或少......

这是我展示我的 SQLite 表数据的活动

package com.ascendise.ascBudget;

import androidx.appcompat.app.AppCompatActivity;

import android.content.res.Configuration;
import android.database.Cursor;
import android.database.SQLException;
import android.icu.text.DecimalFormat;
import android.os.Bundle;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.CheckBox;
import android.widget.TableLayout;
import android.widget.TableRow;
import android.widget.TextView;

public class ShowExpensesActivity extends AppCompatActivity {
    private TableLayout tblExpenses;
    private TextView tvMessage;
    private TableOpenHandler toh = new TableOpenHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        Cursor cursor = toh.getCursor(toh.TABLE_NAME_XPNSES);
        Boolean isLandscape = this.getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_show_expenses);
        setTitle(R.string.main_button_expenses);

        //region Initialization GUI-Elements
        tblExpenses = findViewById(R.id.tblExpenses);
        tvMessage = findViewById(R.id.tvMessage);
        //endregion

        //region fill Table
        while(cursor.moveToNext()) {
            try {
                TableRow row = new TableRow(this);
                TextView tvArticle = new TextView(this);
                TextView tvCategory = new TextView(this);
                TextView tvDescription = new TextView(this);
                TextView tvDate = new TextView(this);
                CheckBox ckbxNecessity = new CheckBox(this);
                TextView tvPrice = new TextView(this);

                String sArticle = cursor.getString(toh.COLUMN_ARTICLE);
                String sCategory = cursor.getString(toh.COLUMN_CATEGORY);
                String sDescription = cursor.getString(toh.COLUMN_DESC);
                String sDate = cursor.getString(toh.COLUMN_DATE);
                String sPrice = cursor.getString(toh.COLUMN_PRICE);

                DecimalFormat df = new DecimalFormat(getString(R.string.input_decimalFormat));
                sPrice = df.format(Double.parseDouble(sPrice)).replace(',', '\'');

                tvArticle.setText(sArticle);
                tvCategory.setText(sCategory);
                tvDescription.setText(sDescription);
                tvDate.setText(sDate);
                ckbxNecessity.setClickable(false);
                tvPrice.setText(sPrice);

                if (Integer.parseInt(cursor.getString(toh.COLUMN_NT)) == (toh.XPNSES_NECESSITY)) {
                    ckbxNecessity.setChecked(true);
                } else {
                    ckbxNecessity.setChecked(false);
                }

                row.addView(tvArticle);
                row.addView(tvCategory);
                row.addView(tvDescription);
                row.addView(tvDate);
                row.addView(ckbxNecessity);
                row.addView(tvPrice);
                row.setClickable(true);
                registerForContextMenu(row);
                tblExpenses.addView(row);
            }catch(SQLException ex) {
                ex.printStackTrace();
            }catch(Exception ex) {
                ex.printStackTrace();
            }
        }
        //endregion

        //region change TableLayout @ OrientationChange
        if(isLandscape){
            tvMessage.setVisibility(View.INVISIBLE);
            tvMessage.setHeight(0);
            tblExpenses.setColumnCollapsed(2,false);
            tblExpenses.setColumnCollapsed(4, false);
        }else{
            tvMessage.setVisibility(View.VISIBLE);
            tblExpenses.setColumnCollapsed(2,true);
            tblExpenses.setColumnCollapsed(4, true);
        }
        //endregion
    }

    //closes TableHandler when Activity/App gets closed
    @Override
    public void onDestroy(){
        super.onDestroy();
        toh.close();
    }

    @Override
    public void onCreateContextMenu(ContextMenu menu, View v,
                                    ContextMenuInfo menuInfo){
        super.onCreateContextMenu(menu, v, menuInfo);
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.context_menu , menu);
        setIntent(getIntent());
    }

    @Override
    public boolean onContextItemSelected(MenuItem item){
        AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
        switch(item.getItemId()){
            case R.id.delete:
                toh.delete(info.id);
                break;
            case R.id.edit:
                break;
            default:
                break;
        }
        return true;
    }
}

现在我正在尝试向该 TableLayout 添加一个上下文菜单,这样我就可以删除行,但它并没有真正起作用。当我尝试调用 info.id 时收到 NullPointerException。我认为这与我如何为 ContextMenu 注册视图有关。我尝试注册行、TableLayout 等。甚至可以这样做还是只适用于 ListViews?

这是堆栈跟踪:

E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.ascendise.ascBudget, PID: 26615
    java.lang.NullPointerException: Attempt to read from field 'long android.widget.AdapterView$AdapterContextMenuInfo.id' on a null object reference
        at com.ascendise.ascBudget.ShowExpensesActivity.onContextItemSelected(ShowExpensesActivity.java:133)
        at android.app.Activity.onMenuItemSelected(Activity.java:3676)
        at androidx.fragment.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:436)
        at androidx.appcompat.app.AppCompatActivity.onMenuItemSelected(AppCompatActivity.java:196)
        at androidx.appcompat.view.WindowCallbackWrapper.onMenuItemSelected(WindowCallbackWrapper.java:109)
        at com.android.internal.policy.PhoneWindow$PhoneWindowMenuCallback.onMenuItemSelected(PhoneWindow.java:3851)
        at com.android.internal.view.menu.MenuBuilder.dispatchMenuItemSelected(MenuBuilder.java:761)
        at com.android.internal.view.menu.MenuItemImpl.invoke(MenuItemImpl.java:178)
        at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:908)
        at com.android.internal.view.menu.MenuBuilder.performItemAction(MenuBuilder.java:898)
        at com.android.internal.view.menu.MenuDialogHelper.onClick(MenuDialogHelper.java:166)
        at com.android.internal.app.AlertController$AlertParams$3.onItemClick(AlertController.java:1146)
        at android.widget.AdapterView.performItemClick(AdapterView.java:321)
        at android.widget.AbsListView.performItemClick(AbsListView.java:1206)
        at android.widget.AbsListView$PerformClick.run(AbsListView.java:3197)
        at android.widget.AbsListView$3.run(AbsListView.java:4145)
        at android.os.Handler.handleCallback(Handler.java:809)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:166)
        at android.app.ActivityThread.main(ActivityThread.java:7555)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)

标签: javaandroidandroid-tablelayoutandroid-contextmenu

解决方案


我建议从此处发布的答案之一中查看下面的代码,我已经从中列出了最重要的部分

row.setOnLongClickListener(new OnLongClickListener() {
    @Override
    public boolean onLongClick(View v) {
        String message = "Here is your message"
        setIntent(getIntent().putExtra("message_key", message));
        registerForContextMenu(v);
        openContextMenu(v);
        unregisterForContextMenu(v);
        return true;
    }
});



推荐阅读