将多个项目添加到列表视图,每个项目从按钮单击的另一个意图接收
Posted
技术标签:
【中文标题】将多个项目添加到列表视图,每个项目从按钮单击的另一个意图接收【英文标题】:Adding multiple items to a listview with each item received from another intent on a button click 【发布时间】:2020-08-19 05:32:11 【问题描述】:我正在创建一个生日提醒应用程序,该应用程序从主要活动开始,使用意图进入一个新活动,人们在那里选择生日,然后将选定的出生日期、月份和年份返回到主要活动。 然后在主活动中,我创建了一个新按钮,该按钮检索生日选择器活动发送的所有信息,并尝试在每次按下按钮时将其显示在列表活动中。
我面临的问题是,如果一旦我运行应用程序,生日就会被记录并显示在列表视图中,但是如果我添加另一个生日并尝试在列表视图中显示它,之前的记录会被删除,我只剩下目前的记录了。
我真正想知道的是如何在我的 listView 中添加项目,以便同时显示我以前的所有生日。
提供的代码文件如下: activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:orientation="vertical"
android:weightSum="10"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_
android:layout_
android:layout_weight="1"
android:background="#97B252D5">
<TextView
android:id="@+id/editText"
android:layout_
android:layout_
android:ems="10"
android:fontFamily="sans-serif-black"
android:text="Remindro"
android:textAllCaps="true"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="36sp"
android:textStyle="bold|italic"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.067"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/newEntry"
android:layout_
android:layout_
android:background="#C1E6E60F"
android:fontFamily="sans-serif-black"
android:onClick="addNewEntry"
android:text="+ADD"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.88"
app:layout_constraintStart_toEndOf="@+id/editText"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.48" />
</androidx.constraintlayout.widget.ConstraintLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_
android:layout_
android:layout_weight="9"
android:background="#A071D4ED">
<ListView
android:id="@+id/list"
android:layout_
android:layout_
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/viewRecord"
app:layout_constraintVertical_bias="0.0" />
<Button
android:id="@+id/viewRecord"
android:layout_
android:layout_
android:layout_marginTop="16dp"
android:background="#9650EC31"
android:onClick="viewRecord"
android:text="View Record"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/_dynamic"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
代码文件:MainActivity.java
package com.example.remindro;
import android.app.ListActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.appcompat.app.AppCompatActivity;
import java.util.ArrayList;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity
private static final String TAG = "";
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
Calendar calendar = Calendar.getInstance();
int thisYear = calendar.get(Calendar.YEAR);
int thisMonth = calendar.get(Calendar.MONTH) + 1;
int thisDay = calendar.get(Calendar.DAY_OF_MONTH);
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
listItems);
ListView records = (ListView) findViewById(R.id.list);
records.setAdapter(adapter);
public void addNewEntry(View v)
Intent adding = new Intent();
adding.setClass(this,addinglist.class);
startActivity(adding);
finish();
public void viewRecord(View v)
Intent receiver = getIntent();
int day = receiver.getIntExtra("day",0);
int month = receiver.getIntExtra("month",0);
int year = receiver.getIntExtra("year",0);
String name = receiver.getStringExtra("nameofperson");
String choice = receiver.getStringExtra("radio");
String mss = name + " has his " + choice + " on " + day + "/" + month + "/" + year;
//Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();
int age = thisYear - year;
calendar.set(thisYear,thisMonth,thisDay);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(thisYear,month,day);
long milliseconds1 = calendar.getTimeInMillis();
long milliseconds2 = calendar1.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
// Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();
String finalMsg = mss + " " + msg2;
listItems.add(finalMsg);
adapter.notifyDataSetChanged();
activity_addinglist.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_
android:layout_
android:background="#8AEC9F18"
tools:context=".addinglist">
<NumberPicker
android:id="@+id/day"
android:layout_
android:layout_
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<NumberPicker
android:id="@+id/month"
android:layout_
android:layout_
android:layout_marginStart="60dp"
android:layout_marginLeft="60dp"
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/day"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<NumberPicker
android:id="@+id/year"
android:layout_
android:layout_
android:layout_marginStart="56dp"
android:layout_marginLeft="56dp"
android:background="#B5EA1241"
android:scaleX="1.3"
android:scaleY="1.3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toEndOf="@+id/month"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.298">
</NumberPicker>
<Button
android:id="@+id/submit"
android:layout_
android:layout_
android:layout_marginBottom="156dp"
android:background="#9A7CEF46"
android:onClick="addingEvent"
android:text="ADD Event"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<RadioGroup
android:id="@+id/typer"
android:layout_
android:layout_
app:layout_constraintBottom_toTopOf="@+id/submit"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.407"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/month"
app:layout_constraintVertical_bias="0.666">
<RadioButton
android:id="@+id/birthday"
android:layout_
android:layout_
android:text="Birthday"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
<RadioButton
android:id="@+id/anniversary"
android:layout_
android:layout_
android:text="Anniversary"
android:textAppearance="@style/TextAppearance.AppCompat.Large" />
</RadioGroup>
<EditText
android:id="@+id/name"
android:layout_
android:layout_
android:textAppearance="@style/TextAppearance.AppCompat.Large"
android:hint="Enter the Name of the Person"
app:layout_constraintBottom_toTopOf="@+id/month"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.045"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.475" />
<EditText
android:id="@+id/resultshower"
android:layout_
android:layout_
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.045"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/submit"
app:layout_constraintVertical_bias="0.518" />
</androidx.constraintlayout.widget.ConstraintLayout>
并添加list.java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.Switch;
public class addinglist extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addinglist);
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
day.setMinValue(1);
day.setMaxValue(31);
month.setMinValue(1);
month.setMaxValue(12);
year.setMinValue(1950);
year.setMaxValue(2020);
public void addingEvent(View v)
String name;
EditText nameEntered = (EditText) findViewById(R.id.name);
name = nameEntered.getText().toString();
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
int day1 = day.getValue();
int month1 = month.getValue();
int year1 = year.getValue();
RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
int selectedId = typer.getCheckedRadioButtonId();
RadioButton checked = (RadioButton) findViewById(selectedId);
String typee = checked.getText().toString();
EditText resultbox = (EditText) findViewById(R.id.resultshower);
String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
resultbox.setText(Finalmsg);
Intent newintent = new Intent();
newintent.putExtra("nameofperson",name);
newintent.putExtra("day",day1);
newintent.putExtra("month",month1);
newintent.putExtra("year",year1);
newintent.putExtra("radio",typee);
newintent.setClass(this,MainActivity.class);
startActivity(newintent);
提前感谢您抽出时间来解决此问题。
【问题讨论】:
【参考方案1】:要从活动中获取结果,您应该使用 startActivityForResult()
和 onActivityResult()
API,而不是 startActivity()
。
您可以从 tutorialspoint 给出的这个简单示例中学习它:https://www.tutorialspoint.com/how-to-manage-startactivityforresult-on-android
但最新的 Android 开发者文档建议我们为此使用新的Activity Result API。
要学习,可以参考谷歌的文档:https://developer.android.com/training/basics/intents/result
Wajahat Karim 写的这篇文章:https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/
我正在尝试使用这个新的 Activity Result API 为您提供答案。
首先,您必须添加 AndroidX Activity
和 Fragment
库作为依赖项。
app/build.gradle
apply plugin: 'com.android.application'
android
compileSdkVersion 29
buildToolsVersion "29.0.2"
defaultConfig
applicationId "com.lakindu.birthdayreminder"
minSdkVersion 14
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
buildTypes
release
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
dependencies
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
// Reference 1 : https://developer.android.com/training/basics/intents/result
// Reference 2 : https://wajahatkarim.com/2020/05/activity-results-api-onactivityresult/
implementation 'androidx.activity:activity:1.2.0-alpha04'
implementation 'androidx.fragment:fragment:1.3.0-alpha04'
我将把一个 Parcelable
对象从添加列表活动发送到 MainActivity 作为结果。
这是 Parcelable Event
类的实现。
Event.java
import android.os.Parcel;
import android.os.Parcelable;
public class Event implements Parcelable
// Name of the person
private String nameOfPerson;
// Day of month
// byte (8 bit) as the type, because day can only have a value from 1 to 31
private byte day;
// Month of year
// byte (8 bit) as the type, because month can only have a value from 1 to 12
private byte month;
// Year
// Short (16 bit) as the type, because year can only have a realistic A.D. year
private short year;
// Type of event
private String eventType;
// Constructor (auto-generated using Android Studio)
public Event(String nameOfPerson, byte day, byte month, short year, String eventType)
this.nameOfPerson = nameOfPerson;
this.day = day;
this.month = month;
this.year = year;
this.eventType = eventType;
// Getters for each private member field (auto-generated using Android Studio)
public String getNameOfPerson()
return nameOfPerson;
public byte getDay()
return day;
public byte getMonth()
return month;
public short getYear()
return year;
public String getEventType()
return eventType;
// Parcelable implementation (auto-generated using Android Studio)
protected Event(Parcel in)
nameOfPerson = in.readString();
day = in.readByte();
month = in.readByte();
year = (short) in.readInt();
eventType = in.readString();
public static final Creator<Event> CREATOR = new Creator<Event>()
@Override
public Event createFromParcel(Parcel in)
return new Event(in);
@Override
public Event[] newArray(int size)
return new Event[size];
;
@Override
public int describeContents()
return 0;
@Override
public void writeToParcel(Parcel dest, int flags)
dest.writeString(nameOfPerson);
dest.writeByte(day);
dest.writeByte(month);
dest.writeInt((int) year);
dest.writeString(eventType);
然后我们必须创建一个类来封装来自 MainActivity 的添加列表活动的输入(在此示例中没有),以及从添加列表活动返回的输出到 MainActivity(Event Parcelable 对象)。
这个类是一个ActivityResultContract,它就像我们给Android系统的一个契约,用来打开一个特定的Activity,并为我们得到一个结果。
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import androidx.activity.result.contract.ActivityResultContract;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
public class GetEvent extends ActivityResultContract<Void, Event>
@NonNull
@Override
public Intent createIntent(@NonNull Context context, Void input)
// Create Intent that should be used to start addinglist activity for result
Intent intent = new Intent(context, addinglist.class);
// If you need to send any inputs to addinglist activity,
// you can put them in intent as extras.
// Eg: intent.putExtra("input", input)
// But for now we don't have to send any inputs to addinglist activity.
return intent;
@Override
public Event parseResult(int resultCode, @Nullable Intent intent)
// Action is cancelled? Return null
if(Activity.RESULT_OK != resultCode) return null;
// No intent to get output? Return null
if(null == intent) return null;
// Successfully got result from addinglist activity
return intent.getExtras().getParcelable("output");
这是我们从 MainActivity 启动添加列表活动并获取结果的方式。
MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import androidx.activity.ComponentActivity;
import androidx.activity.result.ActivityResultCallback;
import androidx.activity.result.ActivityResultLauncher;
import java.util.ArrayList;
import java.util.Calendar;
public class MainActivity extends ComponentActivity
private static final String TAG = "";
ArrayList<String> listItems = new ArrayList<String>();
ArrayAdapter<String> adapter;
Calendar calendar = Calendar.getInstance();
int thisYear = calendar.get(Calendar.YEAR);
int thisMonth = calendar.get(Calendar.MONTH) + 1;
int thisDay = calendar.get(Calendar.DAY_OF_MONTH);
// Holds the latest event received from addinglist activity
private Event mLatestEvent = null;
// Register a callback to be called on an event received from addinglist activity
private ActivityResultLauncher<Void> mGetEvent = registerForActivityResult(
// Instance that encapsulates input and output when starting addinglist activity for result
new GetEvent(),
// Callback to be called when event is received
new ActivityResultCallback<Event>()
@Override
public void onActivityResult(Event result)
// Save as latest event received
mLatestEvent = result;
);
private static final Void NO_INPUT = null;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
adapter=new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
listItems);
ListView records = (ListView) findViewById(R.id.list);
records.setAdapter(adapter);
public void addNewEntry(View v)
// Launch addinglist activity to get an event
mGetEvent.launch(NO_INPUT);
public void viewRecord(View v)
// No latest event? Then nothing to add to list, just return.
if(null == mLatestEvent) return;
// Prepare string that is being added to the list.
// Using a StringBuilder as there are multiple number of immutable strings to be appended.
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(mLatestEvent.getNameOfPerson())
.append(" has his ")
.append(mLatestEvent.getEventType())
.append(" on ")
.append(mLatestEvent.getDay())
.append("/")
.append(mLatestEvent.getMonth())
.append("/")
.append(mLatestEvent.getYear());
String mss = stringBuilder.toString();
//Toast.makeText(getApplicationContext(),mss,Toast.LENGTH_LONG).show();
int age = thisYear - mLatestEvent.getYear();
calendar.set(thisYear,thisMonth,thisDay);
Calendar calendar1 = Calendar.getInstance();
calendar1.set(thisYear, mLatestEvent.getMonth(), mLatestEvent.getDay());
long milliseconds1 = calendar.getTimeInMillis();
long milliseconds2 = calendar1.getTimeInMillis();
long diff = milliseconds2 - milliseconds1;
int noOfDays = (int) (diff / (24 * 60 * 60 * 1000));
String msg2 = "Turning " + age + " in " + noOfDays + "days!!";
// Toast.makeText(getApplicationContext(),msg2,Toast.LENGTH_LONG).show();
String finalMsg = mss + " " + msg2;
listItems.add(finalMsg);
adapter.notifyDataSetChanged();
请注意,MainActivity 现在是ComponentActivity
。不是 AppCompatActivity。
这里是如何将添加列表活动的结果发送到 MainActivity。
addinglist.java
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.NumberPicker;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import androidx.appcompat.app.AppCompatActivity;
public class addinglist extends AppCompatActivity
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_addinglist);
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
day.setMinValue(1);
day.setMaxValue(31);
month.setMinValue(1);
month.setMaxValue(12);
year.setMinValue(1950);
year.setMaxValue(2020);
public void addingEvent(View v)
String name;
EditText nameEntered = (EditText) findViewById(R.id.name);
name = nameEntered.getText().toString();
NumberPicker day = (NumberPicker) findViewById(R.id.day);
NumberPicker month = (NumberPicker) findViewById((R.id.month));
NumberPicker year = (NumberPicker) findViewById(R.id.year);
byte day1 = (byte) day.getValue();
byte month1 = (byte) month.getValue();
short year1 = (short) year.getValue();
RadioGroup typer = (RadioGroup) findViewById(R.id.typer);
int selectedId = typer.getCheckedRadioButtonId();
RadioButton checked = (RadioButton) findViewById(selectedId);
String typee = checked.getText().toString();
EditText resultbox = (EditText) findViewById(R.id.resultshower);
String Finalmsg = name + " has his " + typee + " on " + day1 + "/" + month1 + "/" + year1;
resultbox.setText(Finalmsg);
// Prepare the result to output
Intent newintent = new Intent();
newintent.putExtra(
"output",
new Event(name, day1, month1, year1, typee)
);
// Set the result
setResult(Activity.RESULT_OK, newintent);
// Finish the addinglist activity.
// Then result will be sent to the MainActivity.
finish();
这是正在运行的应用程序。
【讨论】:
据我所知,类之间的数据传输将以可打包对象的形式创建的自定义对象的形式进行。 ActivityResultsContract 就像从 main 获取输入到添加列表并将输出从添加列表提供到 main 的媒介。但我仍然没有得到的是你如何在列表视图上添加多个结果,一次对象只有一个数据!以及多个数据条目的存储位置和方式,因为它们需要存储才能在列表视图中显示。 感谢您的耐心等待,如果我有什么问题,请纠正我。 代码解释部分 1 - 当 '+ADD' 按钮被按下时,addNewEntry(View)
正在被调用,并且 MainActivity 发起调用以启动添加列表活动以获取事件结果。但是 MainActivity 不会被破坏。它只是进入后台,并且添加列表活动出现在其顶部以获取用户的输入。在用户设置输入并按下“添加事件”按钮后,addinglist 活动创建事件,将其设置为结果,然后自行关闭。
代码解释第二部分 - 当 MainActivity 通过注册的回调接收到 Event 时,它被保存到 MainActivity 的Event mLatestEvent
成员字段中。当按下“查看记录”按钮时调用viewRecord(View)
方法时,它会获取mLatestEvent
,使用该事件准备一个字符串,并将其添加到列表视图中。 只要 MainActivity 没有被破坏,我们就会在列表视图中看到所有以前添加的字符串。 如果它以某种方式被破坏(可能是由于 Android 系统在内存不足的情况下),您将丢失所有数据在列表视图中。
所以一旦你收到一个事件,你应该把它保存在数据库中。阅读 Room
数据库以将数据保存到数据库中,并阅读 LiveData
以使用数据库中保存的数据更新您的列表视图。以上是关于将多个项目添加到列表视图,每个项目从按钮单击的另一个意图接收的主要内容,如果未能解决你的问题,请参考以下文章
将 NEXT 按钮添加到 iPad UISplitViewControl