如何将上下文菜单添加到 Table 布局?
How can I add a Context Menu to a Table Layout?
各位程序员大家好
我正在尝试使用一个应用程序来记录我所做的所有费用。
我在表单中输入我的信息,将其添加到 SQLite 数据库并在 Table 布局中的新 activity 中显示它。一切正常,直到那里,或多或少...
这是 Activity 我显示 SQLite 数据的地方 Table
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;
}
}
现在我正尝试向该 Table布局添加上下文菜单,这样我就可以删除行,但它并没有真正发挥作用。当我尝试调用 info.id 时出现 NullPointerException。我认为这与我如何为 ContextMenu 注册视图有关。我尝试注册行、TableLayout 等。是否可以这样做,或者它只适用于 ListViews?
这是 StackTrace:
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.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.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)
我建议看一下 answer posted here、 中最重要的部分 来自它:
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;
}
});
各位程序员大家好
我正在尝试使用一个应用程序来记录我所做的所有费用。 我在表单中输入我的信息,将其添加到 SQLite 数据库并在 Table 布局中的新 activity 中显示它。一切正常,直到那里,或多或少...
这是 Activity 我显示 SQLite 数据的地方 Table
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;
}
}
现在我正尝试向该 Table布局添加上下文菜单,这样我就可以删除行,但它并没有真正发挥作用。当我尝试调用 info.id 时出现 NullPointerException。我认为这与我如何为 ContextMenu 注册视图有关。我尝试注册行、TableLayout 等。是否可以这样做,或者它只适用于 ListViews?
这是 StackTrace:
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.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.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)
我建议看一下 answer posted here、 中最重要的部分 来自它:
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;
}
});