I have two activity screens: Create and View. Create is where the user creates their shopping list. View is where they view their list (and can still add items).
I've tried reading about saving the instance state of activities but I'm still confused as to **how I can make it so when the user chooses items from the dropdowns in the create screen, those are copied, into the view screen. So basically both screens look the same - i.e the dropdowns with the selected items are in the view screen as well. (So like, the exact view instance from the create screen is copied into the view screen)
Below is my create.java code. (view.java has exactly the same code just with .view in places instead of .create, and some extra code.)
public class create extends AppCompatActivity { private LinearLayout mLinearLayout; private ArrayList<SearchableSpinner> mSpinners; //TODO add the below list of buttons and checkboxes // private List<AppCompatButton> mButtons = new ArrayList<>(); private List<CheckBox> mCheckboxes = new ArrayList<>(); private List<View> mViews = new ArrayList<>(); Button buttonGo; Spinner spinner; //Button buttontest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_create); getSupportActionBar().setDisplayHomeAsUpEnabled(true); GlobalClass globalClass = (GlobalClass) this.getApplicationContext(); ArrayList<String> items = new ArrayList<>(); items.add(String.valueOf(mSpinners)); // add you selected item globalClass.setItems(items); mSpinners = new ArrayList<>(); mLinearLayout = findViewById(R.id.my_linearLayout); FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.fab); floatingActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getBaseContext(), "Item added!", Toast.LENGTH_SHORT).show(); RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); // Handle the click. // Handle ze click. //final Spinner spinner = makeSpinner(); //mLinearLayout.addView(spinner); //final Spinner spinner = makeSpinner(); spinner.setId(1); mLinearLayout.addView(spinner,params1); LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) spinner.getLayoutParams(); layoutParams.setMargins(5, 100, 10, 0); //top 70 Resources resources = getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); layoutParams.height = (int) (70 * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)); //80 layoutParams.width = (int) (240 * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)); //240 spinner.setLayoutParams(layoutParams); //TODO adds a new view that is suppose to replicate the button so when it is pressed, blah happens. //TODO i.e move the button code to the onclick View then delete button cause its useless. //Add a new view final View newView = makeView(); mLinearLayout.addView(newView); //TODO create new layout params here mViews.add(newView); //Add a new button // final AppCompatButton newButton = makeButton(); // mLinearLayout.addView(newButton); // Add another button // //TODO add button to the list // mButtons.add(newButton); final int listSize = mViews.size(); //code for deleting the said item. newView.setOnClickListener(new View.OnClickListener() { //start @Override public void onClick(View view) { //when the 'new button' is pressed, alert shows if you are sure you want to delete the item or not. final View.OnClickListener context = this; AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(create.this); // set title alertDialogBuilder.setTitle("Delete Item"); // set dialog message alertDialogBuilder .setMessage("Are you sure you want to delete this item?") .setCancelable(false) .setPositiveButton("Yes", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // if this button is clicked, close // current activity if (listSize > 0) { // mButtons.get(listSize - 1).setVisibility(View.GONE); mCheckboxes.get(listSize - 1).setVisibility(View.GONE); mSpinners.get(listSize - 1).setVisibility(View.GONE); mViews.get(listSize - 1).setVisibility(View.GONE); Toast.makeText(getBaseContext(), "Item removed.", Toast.LENGTH_SHORT).show(); } } }) .setNegativeButton("No", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // if this button is clicked, just close // the dialog box and do nothing dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } }); //Add a new checkbox //final CheckBox newCheckbox = makeCheckbox(); //mLinearLayout.addView(newCheckbox); //TODO add checkbox to your list final CheckBox newCheckbox = makeCheckbox(); newCheckbox.setId(2); params2.addRule(RelativeLayout.RIGHT_OF, spinner.getId()); mLinearLayout.addView(newCheckbox,params2); mCheckboxes.add(newCheckbox); } }); buttonGo.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(spinner!=null){ Intent i= new Intent(create.this, viewscreen.class); //Create the bundle Bundle bundle = new Bundle(); //Add your data to bundle bundle.putString("dropdown", String.valueOf(spinner.getOnItemSelectedListener())); //Add the bundle to the intent i.putExtras(bundle); startActivity(i); } }; }); } //DUPLICATING ITEMS WHEN FAB IS PRESSED// private CheckBox makeCheckbox() { //Create new Checkbox CheckBox checkbox = new CheckBox(this); // Setup layout LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); checkbox.setLayoutParams(layoutParams); return checkbox; } private View makeView() { //create new View View view = new View(this); view.setBackgroundColor(Color.parseColor("#ffffff")); LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 100); new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, 50); //LinearLayout.LayoutParams.MATCH_PARENT, // LinearLayout.LayoutParams.WRAP_CONTENT); view.setClickable(true); //setting if clickable - made it work. view.setLayoutParams(layoutParams); //setup layout return view; } private Spinner makeSpinner() { //opens csv InputStream inputStream = getResources().openRawResource(R.raw.shopitems); CSVFile csvFile = new CSVFile(inputStream); List<String> itemList = csvFile.read(); //Create new spinner // SearchableSpinner spinner = (SearchableSpinner) new Spinner(this, Spinner.MODE_DROPDOWN); SearchableSpinner spinner = new SearchableSpinner(this); // Setup layout LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); spinner.setLayoutParams(layoutParams); MyListAdapter adapter = new MyListAdapter(this, R.layout.listrow, R.id.txtid, itemList); spinner.setAdapter(adapter); //Add it to your list of spinners so you can retrieve their data when you click the getSpinner button mSpinners.add(spinner); return spinner; } private class CSVFile { InputStream inputStream; public CSVFile(InputStream inputStream) { this.inputStream = inputStream; } public List<String> read() { List<String> resultList = new ArrayList<String>(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); try { String line; while ((line = reader.readLine()) != null) { String[] row = line.split(","); resultList.add(row[1]); } } catch (IOException e) { Log.e("Main", e.getMessage()); } finally { try { inputStream.close(); } catch (IOException e) { Log.e("Main", e.getMessage()); } } return resultList; } } }
UPDATED CODE from Angus' help:
//Create the bundle Intent i= new Intent(this, view.class); Bundle bundle = new Bundle(); //Add your data to bundle bundle.putString("dropdown", spinner.getOnItemSelectedListener(); //Add the bundle to the intent i.putExtras(bundle); startActivity(i);
Error log:
In the error log it just says a ) expected on the line bundle.putString("dropdown", spinner.getOnItemSelectedListener();
But in the actual code when I hover on the red underline of this line: Intent i= new Intent(this, view.class);
it says:Cannot resolve constructor
Second activity code (view)
public class viewscreen extends AppCompatActivity { private LinearLayout mLinearLayout; private ArrayList<SearchableSpinner> mSpinners; //TODO add the below list of buttons and checkboxes private List<AppCompatButton> mButtons = new ArrayList<>(); private List<CheckBox> mCheckboxes = new ArrayList<>(); //Button buttontest; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view); getSupportActionBar().setDisplayHomeAsUpEnabled(true); mSpinners = new ArrayList<>(); mLinearLayout = findViewById(R.id.my_linearLayout); GlobalClass globalClass = (GlobalClass) this.getApplicationContext(); ArrayList<String> items = globalClass.getItems(); //mLinearLayout.addView(makeSpinner()); // First spinner //code for the add button to add more items FloatingActionButton floatingActionButton = (FloatingActionButton) findViewById(R.id.fab); floatingActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getBaseContext(), "Item added!" , Toast.LENGTH_SHORT ).show(); // Handle ze click. final Spinner spinner = makeSpinner(); mLinearLayout.addView(spinner); //Add another spinner LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)spinner.getLayoutParams(); layoutParams.setMargins( 5, 100, 10, 0); //top 70 Resources resources = getResources(); DisplayMetrics metrics = resources.getDisplayMetrics(); layoutParams.height = (int) (70 * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)); //80 layoutParams.width = (int) (240 * ((float)metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT)); //240 spinner.setLayoutParams(layoutParams); //Add a new button final AppCompatButton newButton = makeButton(); mLinearLayout.addView(newButton); // Add another button //TODO add button to the list mButtons.add(newButton); final int listSize = mButtons.size(); //code for deleting the said item. newButton.setOnClickListener(new View.OnClickListener() { //start @Override public void onClick(View view) { //when the 'new button' is pressed, alert shows if you are sure you want to delete the item or not. final View.OnClickListener context = this; AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(viewscreen.this); // set title alertDialogBuilder.setTitle("Delete Item"); // set dialog message alertDialogBuilder .setMessage("Are you sure you want to delete this item?") .setCancelable(false) .setPositiveButton("Yes",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog,int id) { // if this button is clicked, close // current activity // when list size = 0. show message all done if(listSize >0) { mButtons.get(listSize - 1).setVisibility(View.GONE); mCheckboxes.get(listSize - 1).setVisibility(View.GONE); mSpinners.get(listSize - 1).setVisibility(View.GONE); Toast.makeText(getBaseContext(), "Item removed." , Toast.LENGTH_SHORT ).show(); } } }) .setNegativeButton("No",new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog,int id) { // if this button is clicked, just close // the dialog box and do nothing dialog.cancel(); } }); // create alert dialog AlertDialog alertDialog = alertDialogBuilder.create(); // show it alertDialog.show(); } } ); //Add a new checkbox final CheckBox newCheckbox = makeCheckbox(); mLinearLayout.addView(newCheckbox); //TODO add checkbox to your list mCheckboxes.add(newCheckbox); //code for checkbox on click is suppose to be in view screen. newCheckbox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { // makes the set disappear when checkbox is ticked. newCheckbox.setVisibility(View.VISIBLE); newButton.setVisibility(View.VISIBLE); spinner.setVisibility(View.VISIBLE); newCheckbox.animate().alpha(0.0f).setDuration(1000).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); newCheckbox.setVisibility(View.GONE); } }); newButton.animate().alpha(0.0f).setDuration(1000).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); newButton.setVisibility(View.GONE); } }); spinner.animate().alpha(0.0f).setDuration(1000).setListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); spinner.setVisibility(View.GONE); } }); } }); //end of checkbox on click code. Bundle bundle = getIntent().getExtras(); //Extract the data… String dropdown_value= bundle.getString("dropdown"); } }); } //DUPLICATING ITEMS WHEN + IS PRESSED private CheckBox makeCheckbox() { //Create new Checkbox CheckBox checkbox = new CheckBox(this); // Setup layout LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); checkbox.setLayoutParams(layoutParams); return checkbox; } private AppCompatButton makeButton() { //creates new buttons I need //Create new Button AppCompatButton button = new AppCompatButton(this); // code for deleting the buttons i need // //buttontest.setOnClickListener(new View.OnClickListener() { // @Override // public void onClick(View v) { // Setup layout LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); button.setBackgroundColor(Color.parseColor("#ffffff")); return button; } private Spinner makeSpinner() { //opens csv InputStream inputStream = getResources().openRawResource(R.raw.shopitems); CSVFile csvFile = new CSVFile(inputStream); List<String> itemList = csvFile.read(); //Create new spinner // SearchableSpinner spinner = (SearchableSpinner) new Spinner(this, Spinner.MODE_DROPDOWN); SearchableSpinner spinner = new SearchableSpinner(this); // Setup layout LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); spinner.setLayoutParams(layoutParams); MyListAdapter adapter = new MyListAdapter(this, R.layout.listrow, R.id.txtid, itemList); spinner.setAdapter(adapter); //Add it to your list of spinners so you can retrieve their data when you click the getSpinner button mSpinners.add(spinner); return spinner; } //csv file code private class CSVFile { InputStream inputStream; public CSVFile(InputStream inputStream) { this.inputStream = inputStream; } public List<String> read() { List<String> resultList = new ArrayList<String>(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); try { String line; while ((line = reader.readLine()) != null) { String[] row = line.split(","); resultList.add(row[1]); } } catch (IOException e) { Log.e("Main", e.getMessage()); } finally { try { inputStream.close(); } catch (IOException e) { Log.e("Main", e.getMessage()); } } return resultList; } } }
ERROR LOG UPDATE:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.app.supermarketaislefinder/com.app.supermarketaislefinder.create}: java.lang.NullPointerException at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2092) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2117) at android.app.ActivityThread.access$700(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1218) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1007) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:774) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException at com.app.supermarketaislefinder.create.onCreate(create.java:232) at android.app.Activity.performCreate(Activity.java:5047) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1094) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2056) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2117) at android.app.ActivityThread.access$700(ActivityThread.java:134) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1218) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:4867) at java.lang.reflect.Method.invokeNative(Native Method)
8 Answers
Answers 1
In the first activity, put your dropdown selected value into bundle
before start another activity(intent)
Intent i= new Intent(this, YourSecondClass.class); //Create the bundle Bundle bundle = new Bundle(); //Add your data to bundle bundle.putString("dropdown", dropdown_value); //Add the bundle to the intent i.putExtras(bundle); startActivity(i);
In the new(second) activity, get your dropdown value from bundle.
Bundle bundle = getIntent().getExtras(); //Extract the data… String dropdown_value= bundle.getString("dropdown");
Answers 2
public class create extends AppCompatActivity {
private LinearLayout mLinearLayout; private ArrayList<SearchableSpinner> mSpinners; //TODO add the below list of buttons and checkboxes // private List<AppCompatButton> mButtons = new ArrayList<>(); private List<CheckBox> mCheckboxes = new ArrayList<>(); private List<View> mViews = new ArrayList<>(); Button buttonGo; Spinner spinner; ...... floatingActionButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(getBaseContext(), "Item added!", Toast.LENGTH_SHORT).show(); RelativeLayout.LayoutParams params1 = new RelativeLayout.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); RelativeLayout.LayoutParams params2 = new RelativeLayout.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); // Handle the click. // Handle ze click. //final Spinner spinner = makeSpinner(); //mLinearLayout.addView(spinner); spinner = makeSpinner(); }
Answers 3
I think what you want to do is pass the user selected items from the create screen to the view screen.
You can use a global class to store the values of the selected items. And use it like a normal java class.
public class GlobalClass extends Application { ArrayList<String> items = new ArrayList<>(); public ArrayList<String> getItems() { return items; } public void setItems(ArrayList<String> items) { this.items = items; } }
Define this in the application tag of the manifest file
<application android:name=".GlobalClass"
and use it like this in the onCreate
function of both activities
globalClass = (GlobalClass) this.getApplicationContext();
then you can use getters and setters to access your selected item list. in create activity,
ArrayList<String> items = new ArrayList<>(); items.add(item); // add you selected item globalClass.setItems(items);
in view activity,
ArrayList<String> items = globalClass.getItems();
Answers 4
buttonGo.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(spinner!=null){ Intent i= new Intent(create.this, viewscreen.class); //Create the bundle Bundle bundle = new Bundle(); //Add your data to bundle bundle.putString("dropdown", dropdown_value); //Add the bundle to the intent i.putExtras(bundle); startActivity(i); } });
Answers 5
I don't know why you are stuck in this problem still. When you know to pass values in Activities. If I think about your problem, I get various solutions in my mind.
Solution 1: Use @Angus solution, I checked your code when you followed his answer.
Basically you have to pass an value to next activity, like position/ spinner selected value.
bundle.putString("selectedPos", spinner.getSelectedItemPosition());
or
bundle.putString("selectedItem", ((String) spinner.getSelectedItem()));
Solution 2: You have SharedPreference to store these values in first activity, then get saved values in second activity.
Solution 3: I don't suggest to use Application class to store variables, but yes!, that's a solution. Like this answer. I don't use Application class to store values, because we need to clear the fields after use manually, to recover RAM uses.
Solution 4: As you said both of your Activities are almost same, then why don't you just use one Activity and manage Views accordingly.
Edit
If I am getting right, then you can pass the generated Spinners items list and selected items to next Activity. You can pass Parcelable List
for ease.
First Activity passes the Spinner model list.
ArrayList<ModelSpinner> list = new ArrayList<>(); list.add(new ModelSpinner(itemsList, (String) spinner.getSelectedItem())); startActivity(new Intent(this, MainActivity.class).putParcelableArrayListExtra("key", list));
Second activity gets the list and make according views
ArrayList<ModelSpinner> list = getIntent().getParcelableArrayListExtra("key"); for (ModelSpinner spinner : list) { // render spinners Spinner spinner = makeSpinner(spinner.getItems(),spinner.getSelectedValue()); // todo create method makeSpinner(List<String> list, String selectedItem), add this spinner to your activity. }
ModelSpinner.class
public class ModelSpinner implements Parcelable { private ArrayList<String> items; private String selectedValue; // getter setter @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeStringList(this.items); dest.writeString(this.selectedValue); } public ModelSpinner() { } protected ModelSpinner(Parcel in) { this.items = in.createStringArrayList(); this.selectedValue = in.readString(); } public static final Parcelable.Creator<ModelSpinner> CREATOR = new Parcelable.Creator<ModelSpinner>() { @Override public ModelSpinner createFromParcel(Parcel source) { return new ModelSpinner(source); } @Override public ModelSpinner[] newArray(int size) { return new ModelSpinner[size]; } }; }
Answers 6
The best solution for this scenario will be using ViewModel and LiveData from architectural components library which will simply provide you consistency in data in both the Activities. A single ViewModel for both Activities and shared LiveDatas for both Activities which will be helpful when you update any LiveData from any Activity it will get reflected in all the Activities which is observing the defined LiveData in the ViewModel.
Answers 7
You are calling the context as "This" but is calling it from within a method that overwrites a method in the interface, but the method is not in this class and therefore does not know what "This" is, to solve it do this, in you Create Class:
public class Create extends AppCompatActivity { private Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_view); getSupportActionBar().setDisplayHomeAsUpEnabled(true); context = this; buttonGo.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { if(spinner!=null){ Intent i= new Intent(context, View.class); startActivity(i); } }; } }
You can pass data with the intent,or can pass data using a static variable in the Create class.
Create Class:
public class Create extends AppCompatActivity { public static String optionSelected; //other code.... spinner.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { Create.optionSelected = parent.getItemAtPosition(position).toString(); } }); //other code.... }
In your View Class to call optionSelected:
public class View extends AppCompatActivity { String dropdown_value= Create.optionSelected; // rest of code }
Answers 8
I had a similar requirement. I solved it with a different logic.
- Create a class for reference.
- Store data in this class, then stringify using Gson and pass it to second activity.
- Get back from stringified json to class object using Gson.
- OnCreate, update the UI according to the object content u received in Step 3.
This will make the flow in control and development friendly. Hope this serves your requirement well.
Storing the view and transferring is not a better idea since this can lead to development complexity later.
Incase of multiple data for n number of spinners, you can use ArrayList of product objects and create spinner view dynamically.