I am new to android, currently in my second year in I.t..
I'm working on a grocery list app project, where I display a list of groceries for the user to select and to display them on the next screen (Screen 2).
The problem I am having, is, when I click the Show List button, it displays the indexes of the selected checkboxes instead of the text displayed... I have tried using a ListActivity to display an array in a CheckedTextView but that didn't work out either (checkboxes were not checking when selected).
I would really appreciate some help on how to display the selected text instead of the checkboxes selected indexes and would like to know where I am going wrong.
Below is my Java and XML code for the 2 screens..
Java Coding - Screen 1
package com.allmycode.lists;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.CheckBox;
import android.widget.LinearLayout;
public class MainActivity extends Activity {
static CheckBox[] checkBoxes = new CheckBox[18];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout layout =
(LinearLayout) findViewById(R.id.linearLayout);
for (int i = 0; i < 18; i++) {
checkBoxes[i] = new CheckBox(this);
layout.addView(checkBoxes[i]);
}
checkBoxes[0].setText("Baking Ingredients");
checkBoxes[1].setText("Beverages");
checkBoxes[2].setText("Canned Foods");
checkBoxes[3].setText("Cereal");
checkBoxes[4].setText("Dairy");
checkBoxes[5].setText("Detergents");
checkBoxes[6].setText("Frozen Vegetables");
checkBoxes[7].setText("Fruit");
checkBoxes[8].setText("Broad Beans");
checkBoxes[9].setText("Herbs");
checkBoxes[10].setText("Legumes");
checkBoxes[11].setText("Meat");
checkBoxes[12].setText("Pasta");
checkBoxes[13].setText("Pet Food");
checkBoxes[14].setText("Rice");
checkBoxes[15].setText("Snacks");
checkBoxes[16].setText("Toiletries");
checkBoxes[17].setText("Vegetables");
}
public void onShowListClick(View view) {
Intent intent =
new Intent(this, MyListActivity.class);
startActivity(intent);
}
}
XML Coding - Screen 1
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id="#+id/linearLayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</TextView>
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="onShowListClick"
android:text="#string/show_list" >
</Button>
Java Coding - Screen 2
package com.allmycode.lists;
import java.util.ArrayList;
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class MyListActivity extends ListActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ArrayList<Integer> listItems =
new ArrayList<Integer>();
for (int i = 0; i < 18; i++) {
if (MainActivity.checkBoxes[i].isChecked()) {
listItems.add(i);
}
}
setListAdapter(new ArrayAdapter <Integer> (this,
R.layout.my_list_layout, listItems));
}
}
XML Coding - Screen 2
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android=
"http://schemas.android.com/apk/res/android"
android:id="#+id/identView"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
</TextView>
You're only setting the indexes, so it makes sense that's what's happening:
ArrayList<Integer> listItems = new ArrayList<Integer>(); // <-- List of Integers
for (int i = 0; i < 18; i++) {
if (MainActivity.checkBoxes[i].isChecked()) {
listItems.add(i); // <-- You're adding an integer to the List
}
}
Try this instead:
ArrayList<String> listItems = new ArrayList<String>(); // <-- List of Strings
for (int i = 0; i < 18; i++) {
if (MainActivity.checkBoxes[i].isChecked()) {
listItems.add(MainActivity.checkBoxes[i].getText()); // Set it to the text of the Checkbox, not the integer index in the loop
}
}
setListAdapter(new ArrayAdapter<String> (this, R.layout.my_list_layout, listItems));
The answer from Guardanis is technically correct if you were working with a regular Java class. The Android Activity class is NOT a regular Java class however.
Never try to access fields or methods in one Activity from any other app component. In some cases it might work but that approach breaks the Activity model and if you continue along that line, i.e., assuming an Activity is just a regular Java class, at some point your app will crash and burn.
The correct way to do what you are doing is to work out which checkboxes are checked using code in your MainActivity BEFORE you start MyListActivity. You'd then need to pass that information to MyListActivity either as Intent extras or by saving the data in SharedPreferences or using some other way of sharing the data.
Related
I'm new to Android and have been learning about Android app development for about a month just through a book, and right now, I'm working on my own project, which is a basic app that manages user tasks and schedule. There is this one problem I am having. I am trying to add a new task to a RecyclerView list that contains the list of main tasks, but I keep getting errors. Here is what I have (I don't want to show everything because it is a project):
The RecyclerView list (main_task_window.xml):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/MainTaskList"
android:layout_width="match_parent"
android:layout_height="449dp"
android:layout_alignParentStart="true"
android:layout_alignParentBottom="true"
android:layout_marginStart="0dp"
android:layout_marginTop="1dp"
android:layout_marginBottom="61dp" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/AddaMainTask"
android:onClick="addnewtask"
android:layout_width="54dp"
android:layout_height="51dp"
android:layout_alignParentEnd="true"
android:layout_alignParentBottom="true"
android:layout_marginEnd="13dp"
android:layout_marginBottom="10dp"
android:clickable="true"
app:srcCompat="#android:drawable/ic_input_add" />
</RelativeLayout>
The window that allows users to add new main tasks as well as additional notes (add_new_main_task_window.xml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/maintasks"
android:layout_width="match_parent"
android:layout_height="62dp"
android:hint="Main Task"/>
<EditText
android:id="#+id/notes"
android:layout_width="match_parent"
android:layout_height="62dp"
android:hint="Additional notes"/>
<Button
android:id="#+id/addButton"
android:onClick="sendButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Add to main task" />
</LinearLayout>
Now here are the following Java files:
1. MainTasks.java (contains the get and set methods for the main task and additional notes)
package com.ricstudios.daymanager;
public class MainTasks
{
private String mt, an; //'mt' stands for "main tasks". 'an' stands for "additional notes"
//MainTasks class constructor
public MainTasks(String mt, String an)
{
//mt and an in the parameters is equal to the mt and an variables above
this.mt = mt;
this.an = an;
}
public String getMainTasks() //this get method obtains the main task string input)
{
return mt;
}
public void setMainTasks(String MainTasks) //this set methods stores the main task string input)
{
this.mt = MainTasks;
}
public String getAdditionalNotes() //this get method obtains the main task string input
{
return an;
}
public void setAdditionalNotes(String AddNotes) //this set method stores the main task string
{
this.an = AddNotes;
}
}
MainTaskAdapter.java (contains the adapter to render the data)
package com.ricstudios.daymanager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import java.util.List;
public class MainTaskAdapter extends RecyclerView.Adapter<MainTaskAdapter.ViewHolder>
{
private List<MainTasks> maintasklist; //will contain the main task and additional notes string inputs
public class ViewHolder extends RecyclerView.ViewHolder
{
public EditText maintask, addnotes;
//provides a reference to the views for each data item
public ViewHolder(View view)
{
super(view);
maintask = (EditText)view.findViewById(R.id.maintasks);
addnotes = (EditText)view.findViewById(R.id.notes);
}
}
//MainTaskAdapter class constructor
public MainTaskAdapter(List<MainTasks> maintasklist)
{
this.maintasklist = maintasklist;
}
//create new view (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
{
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.add_new_main_task_window, parent, false);
return new ViewHolder(itemView);
}
//replaces the contents of the main task view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position)
{
MainTasks obj = maintasklist.get(position); //MainTasks class obj called 'obj', which allows access to the MainTasks class
//obtains the main task and additional notes from the MainTask class
holder.maintask.setText(obj.getMainTasks());
holder.addnotes.setText(obj.getAdditionalNotes());
}
//returns the size of the main task list (invoked by the layout manager)
#Override
public int getItemCount()
{
return maintasklist.size();
}
}
AddNewMainTask.java (adds the tasks and additional notes to the RecyclerView)
package com.ricstudios.daymanager;
import android.support.v7.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import android.widget.EditText;
import android.widget.Button;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
/*This class handles the window for adding new main tasks to the main task list (this window is the add_new_main_task_window.xml layout)*/
public class AddNewMainTask extends AppCompatActivity
{
private Button addbutton; //Button element from the add_new_main_task_window.xml layout
private EditText maintask, addnotes; //EditText elements from the add_new_main_task_window.xml layout
private List<MainTasks> maintasklist = new ArrayList<>();
private RecyclerView ListofMainTasks; //RecyclerView list element from the add_new_main_task_window.xml layout (containing the Main Task list)
private MainTaskAdapter TAdapter; //MainTaskAdapter class object 'TAdapter', allows access to the MainTaskAdapter class
/*sendButton method from the Button element in the add_new_main_task_window.xml and adds the main task and additional notes to the RecyclerView main task list*/
public void sendButton(View view)
{
maintask = (EditText)view.findViewById(R.id.maintasks);
addnotes = (EditText)view.findViewById(R.id.notes);
ListofMainTasks = (RecyclerView)findViewById(R.id.MainTaskList);
TAdapter = new MainTaskAdapter(maintasklist);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
ListofMainTasks.setLayoutManager(mLayoutManager);
ListofMainTasks.setItemAnimator(new DefaultItemAnimator());
ListofMainTasks.setAdapter(TAdapter);
/*Passes the EditText element values into the MainTask.java parameters*/
MainTasks mnt = new MainTasks(maintask.getText().toString(), addnotes.getText().toString());
maintasklist.add(mnt);
}
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.add_new_main_task_window); //displays the window that allows users to add new main tasks (which is the add_new_main_task_window.xml layout)
addbutton = (Button)findViewById(R.id.addButton);
/*When user clicks button, the values the user puts in the EditText fields will be added to the RecyclerView list of the main_task_window.xml layout*/
addbutton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
sendButton(v);
}
});
}
}
Whenever I press the "Add to Main Task" button, the app suddenly stop. Please help. Oh, and about the floatingactionbutton in the main_task_window.xml, don't worry about that. That just sends the user to the add_new_main_task_window.xml
Update: 3/5/19
I'm getting this error from the logcat:
03-05 15:22:49.298 10335-10335/com.project.daymanager E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.project.daymanager, PID: 10335
java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.widget.RecyclerView.setLayoutManager(android.support.v7.widget.RecyclerView$LayoutManager)' on a null object reference
at com.project.daymanager.AddNewMainTask.sendButton(AddNewMainTask.java:39)
at com.project.daymanager.AddNewMainTask$1.onClick(AddNewMainTask.java:63)
at android.view.View.performClick(View.java:5702)
at android.widget.TextView.performClick(TextView.java:10887)
at android.view.View$PerformClick.run(View.java:22541)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Replace
view.findViewById();
with
findViewById();
In the MainTasks.java Don't use a constructor
public MainTasks(String mt, String an)
Just keep the set And get methods and do
MainTasks mt = new MainTasks();
mt.setMainTasks("Title");
mt.setAdditionalNotes("Note");
list.add(mt);
If it still not working, please post the error log so we can know whats the error.
Update: 3/5/19
You are trying to access the recyclerView of the MainTaskActivity in
ListofMainTasks = (RecyclerView)findViewById(R.id.MainTaskList);
from out side the activity (From another Activity) and that's not possible this way,
you can set the RecyclerView in the MainTaskActivity to static and use it in AddNewMainTask Activity by calling it
MainTaskActivity.myRecyclerView.
Problem is in this line:
ListofMainTasks = (RecyclerView)findViewById(R.id.MainTaskList);
program is unable to find recycler view and its null. and you can't set layout manager to a null object. I've reviewed your code and thing you did wrong is that in you onCreate method you are setting layout setContentView(R.layout.add_new_main_task_window); and you're trying to find recylerview which is not in this layout.
Your recycler view is in main_task_window.xml. use setContentView(R.layout.main_task_window.xml); and your activity will find recyclerview easily.
Note: if you want button/controls also which are in this layout add_new_main_task_window.xml then please move them in layout with recyclerview.
What I am trying to do here is to display a list of strings using ArrayList<String> and ArrayAdapter<String> when a user clicks a button. I want to declare all the members i.e. adapter, ArrayList and the list layout as global because I want to add more buttons later with the same feature of displaying a list of strings.
This code has no error but it's not working. I put the Toast in the onClick to make sure the onClick is working. I can see the toast but not the listView I want to see.
class file
R.id.button_news is the button id. R.layout.activity_primary_content is the layout that I'm using in this class PrimaryContent
R.layout.list_view_secondary is the layout where the listView R.id.list_view is located.
R.layout.list_view_secondary layout and the PrimaryContent class are not related but I want to use the listView which is in the list_view_secondary layout to display from the PrimaryContent.
In this line of code
arrayAdapter = new ArrayAdapter<>(view.getContext(),android.R.layout.simple_list_item_1,list); I tried by put the context view.getContext() and getBaseContext() both of them are not working.
import android.content.Context;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;
import java.util.ArrayList;
public class PrimaryContent extends AppCompatActivity {
private final String LOG_TAG = PrimaryContent.class.getSimpleName();
public ListView listView;
public ArrayList<String> arrayList;
public ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_primary_content);
final LayoutInflater factory = getLayoutInflater();
final View rootView = factory.inflate(R.layout.list_view_secondary, null);
listView = rootView.findViewById(R.id.list_view);
arrayList = new ArrayList<>();
for (int i=0; i<20; i++) {
arrayList.add("World News");
}
Button news = findViewById(R.id.button_news);
news.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(getBaseContext(),"Damn",Toast.LENGTH_SHORT).show();
for (String x: arrayList) {
Log.v(LOG_TAG,x);
System.out.println();
}
arrayAdapter = new ArrayAdapter<>(view.getContext(),android.R.layout.simple_list_item_1,arrayList);
listView.setAdapter(arrayAdapter);
}
});
}
}
R.layout.list_view_secondary
<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/list_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:drawSelectorOnTop="true"
android:orientation="vertical" />
You forgot to add the inflated layout to your parent layout, for example:
LinearLayout parentLayout = (LinearLayout) findViewById(R.id.parent_layout);
parentLayout.addView(rootView);
I am querying some raws from the database in Android studio. When I have the result table as a cursor, I want to show that cursor in an activity where columns are written at the top and rows are seen one under the other like a normal table. So, this activity's column names will change according to the result query's columns.
Any idea how to implement this, or is there a template I can use? I am new to Android so it might be an easy question for some of you, sorry for that.
So I recently have as well the same question. Then I found a really good tutorial with custom list items.
First, make sure that you save your records from the database into an object.
So first you have to create a row view. So create a simple XML file insert for example the following code and save it as myobject_list_item in your res/layout folder.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/item"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
android:id="#+id/column1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_toStartOf="#+id/column2"
android:padding="10dp"
android:paddingLeft="5dp"
android:text="Column1"
android:textAppearance="#android:style/TextAppearance.Material.Large"
android:textSize="20sp" />
<TextView
android:id="#+id/column2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/gewichtung"
android:layout_alignParentEnd="true"
android:layout_alignParentTop="true"
android:padding="10dp"
android:text="Column2"
android:textAppearance="#android:style/TextAppearance.Material.Large"
android:textSize="20sp" />
</RelativeLayout>
After that you have to create a custom list adapter. So create a new Java file with the name MyObject_ListAdapter and insert the following code:
package net.example.app;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.RelativeLayout;
import android.widget.TextView;
import net.example.app.R;
import java.util.ArrayList;
public class MyObject_ListAdapter extends ArrayAdapter<MyObject> {
// Source:
// http://hmkcode.com/android-custom-listview-items-row/
private ArrayList<MyObject> objects;
private Context context;
public MyObject_ListAdapter(Context context, ArrayList<MyObject> objects) {
super(context, R.layout.myobject_list_item, objects);
this.objects = objects;
this.context = context;
}
public View getView(int position, View convertView, ViewGroup parent) {
// 1. Create inflater
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
// 2. Get rowView from inflater
View rowView = inflater.inflate(R.layout.fach_list_item, parent, false);
// 3. Get the two text view from the rowView
TextView column1 = (TextView) rowView.findViewById(R.id.column1);
TextView column2 = (TextView) rowView.findViewById(R.id.column2);
RelativeLayout item = (RelativeLayout) rowView.findViewById(R.id.item);
// 4. Set the text for textView
column1.setText(objects.get(position).getName());
column2.setText(objects.get(position).getSecondName());
// 5. return rowView
return rowView;
}
}
Add in your activity now an simple ListView and add for this an id like lv.
Then in your Java Activity you can insert the following code:
package net.example.app;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import net.example.app.MyObject;
import net.example.app.MyObject_ListAdapter;
import java.util.ArrayList;
public class MyActivity extends AppCompatActivity {
private ArrayAdapter arrayAdapter;
private ArrayList<MyObject> myObjects = new ArrayList<>();
private SQLiteDatabase db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myactivity);
db = openOrCreateDatabase("database.db", MODE_PRIVATE, null);
ListView lv = (ListView) findViewById(R.id.lv);
arrayAdapter = new MyObject_ListAdapter(this, myObjects); //Define the custom list adapter with the activity and arraylist
lv.setAdapter(arrayAdapter); //Connect your listview with the adapter
displayData();
}
private void displayData() {
Cursor c = db.rawQuery("SELECT * FROM my_table", null);
while (c.moveToNext()) { //Loop through all the records
//Now on the variable 'c' there is one record.
int column_a_name = c.getColumnIndex("my_column1"); //Get the index of the column from your table.
String column_a_value = c.getString(column_a_name); //Get the value from the column from the current record.
int column_b_name = c.getColumnIndex("my_column2");
String column_b_value = c.getString(column_b_name);
//Now you can do with the value what you want.
myObjects.add(new MyObject(column_a_value, column_b_value));
}
arrayAdapter.notifyDataSetChanged(); //Notify, that you have changed some data in the array list.
}
}
I hope this tutorial may help you.
When you get a Cursor from a SQL execution, then you can use the following script:
Cursor c = db.rawQuery("SELECT * FROM my_table", null);
while (c.moveToNext()) { //Loop through all the records
//Now on the variable 'c' there is one record.
int column_a_name = c.getColumnIndex("my_column"); //Get the index of the column from your table.
String column_a_value = c.getString(column_a_name); //Get the value from the column from the current record.
//Now you can do with the value what you want.
System.out.println(column_a_value);
}
I hope this might be helpful for you.
Android has different layouts that could be of use for what you state.
You can use TableLayout of GridLayout. At this post you can find some discussion about which one choose: Grid Layout Vs. Table Layout
From Android docs, you can check some examples like: https://developer.android.com/guide/topics/ui/layout/grid.html
and https://developer.android.com/guide/topics/ui/layout/gridview.html
Some additional recommendation:
Use AsyncTask for interact with the database, don't do that from the UI thread.
I choose callback methods so, when the data access is completed, you inform the calling activity who is in charge of showing the data on the screen (using the layout of your choice).
Do not create big long classes doing everything. use one class for the activity, another for the adapter, another for the async task.
Hope this helps you.
On my MainActivity.java, I have written code for creating a list of Leap Year till 2015 (inclusive) from 1800 (inclusive). However, I am stuck at the part on where a user clicks 'Generate' button and List of Leap Year is displayed in ListView.
I believe the real problem is with my populate() method because that's only part I am not so sure of. Because I haven't dealt with ArrayAdapter or ArrayList much so far.
NOTE: I don't get any compiling or run time error, I am missing some logical part. The app launches succesfully, but Generate Button doesn't do anything visibly.
Refer to my code Below:
MainActivity.java
package net.androidbootcamp.gregorianspeeddating;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
Button btnGen, btnMan;
ListView listView;
Integer randomNum;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
listView = (ListView) findViewById(R.id.yearsListView);
//Button Generate that creates a ListView of Leap Year on MainActivity
btnGen = (Button) findViewById(R.id.btnGen);
btnGen.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Random r = new Random();
randomNum = r.nextInt(2016 - 1800) + 1800;
if (isLeapYear(randomNum)) {
populate();
}
}
});
// Button Manipulate that takes user to another activity
btnMan = (Button) findViewById(R.id.btnMan);
btnMan.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(MainActivity.this, Manipulate.class));
}
});
}
// Returns true if given Integer is a Leap Year.
public boolean isLeapYear(Integer year) {
boolean b = (year % 4 == 0) && (year % 100 != 0) || (year % 400 == 0);
if (!b) {
return false;
}
return true;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
// Method To Populate ListView with random Leap Year
public void populate() {
ArrayAdapter<Integer> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, randomNum);
listView.setAdapter(adapter);
}
}
content_main.xml which contains Button 'Generate' and 'ListView' --> This is displayed in activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:context="net.androidbootcamp.gregorianspeeddating.MainActivity"
tools:showIn="#layout/activity_main">
<ListView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="#+id/yearsListView"
android:layout_weight="1"
android:dividerHeight="13dp"
android:divider="#android:color/transparent"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Generate"
android:id="#+id/btnGen"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_marginLeft="28dp"
android:layout_marginStart="28dp"
android:layout_marginBottom="60dp" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Manipulate"
android:id="#+id/btnMan"
android:layout_marginRight="28dp"
android:layout_marginEnd="33dp"
android:layout_alignTop="#+id/btnGen"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true" />
</RelativeLayout>
In order to display a list of random leap years, you need to give your listview a list of years rather than a single year. In the onClick method of your Button you randomly generate one number between 1800 and 2015 rather than generating a list of random numbers.
What you have to do is:
Instead of having Integer randomNum;, use List<Integer> randomNums;
Use a variable int count = 20; // use a variable count to keep track of the number of leap years to generate
In the onClick method of the button, use
Random rand = new Random();
randomNums = new ArrayList<Integer>();
while(randomNums.size != count){
randomNums.add(rand.nextInt(2016 - 1800) + 1800);
}
populate()
This while loop can go on and on until you find the required count of random numbers.
Finally in the populate method use the array randomNums
ArrayAdapter<Integer> adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, randomNums);
All the best :)
I haven't run your code yet, but I can see one problem in your onClick handler. In this condition:
if (isLeapYear(randomNum)) {
populate();
}
you are really only calling populate if the random year that was generated is a leap year. From your code it looks like you are simply generating one random number and then creating a list with 0 or 1 entries (0 if it's not a leap year and 1 if it is). So the chances of you having any items in that list is only 1 in 4.
It would help if you post your desired outcome. For example: are you trying to list ALL years starting in 1800 and ending in 2015 that are leap years in order? In that case, why do you need to generate a random number?
I'm new to android developing, so i apologise if this is a simple/noob-ish question, and for any incorrect terminology.
but what i need to know is how can i include a list alongside of other UI elements (such as TextView, ImageView elements etc)
upto now, all i have been able to achieve is a list activity all on its own, which to do this i have been using the ListActivity class type.
My list activity:
import android.app.ListActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
public class ListViewExample extends ListActivity
{
String[] exampleList = {
"Item 1",
"Item 2",
"Item 3"
//etc etc
};
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
setListAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, exampleList));
}
}
Which is started within my Main class/activity:
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
public class NewtestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
startActivity(new Intent( this, ListViewExample.class));
}
}
but with the function of "startActivity()", this seems to just switch to that activity, and not "include" it to the current, which of-corse means that any elements within "R.layout.main" (defined above the calling of "startActivity()) are not shown.
Is there anyway to include this activity within my main activity?
or is there a better way of making a list?
(my goal will eventually be to make the list array dynamic, just thought id say in case that affected on any suggested solution).
thanks for any help (:
Using the startActivity to start your ListViewExample starts a whole new activity (with a whole new view) and puts it on top of the stack. When you click the back button, then your main activity will be displayed. Please see this link to learn more about the activity lifecycle.
It sounds like what you want to do is define some other UI elements alongside your listview. I dont know if you can do this on the SIDE, but I know you can include buttons/textviews on top or bottom of a listview. See this post as a good example of how to put a button below a listview.
EDIT: As an example (taken from the second link), you would do something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:id="#+id/testbutton"
android:text="#string/hello" android:layout_alignParentBottom="true" />
<ListView android:layout_width="fill_parent"
android:layout_height="fill_parent" android:id="#+id/list"
android:layout_alignParentTop="true" android:layout_above="#id/testbutton" />
</RelativeLayout>
Now you could also put that button on bottom if you wanted, or include a textbox on the top and a button on bottom.
Yes as Espiandev said, you would want your main activity to extend Activity. Then in your XML you would have the above. The way you would get your listview to bind to would be
ListView lv = (ListView)findViewById(R.id.list);
Then you could bind to it:
lv.setAdapter(...)
An alternative to the other answer, which is probably more scalable, is to simply make ListViewExample extend a basic Activity. Then, in the onCreate() method, retrieve the ListView by using findViewById() and then use setAdapter() on this. For example, if your ListView was given the id listview1:
public class ListViewExample extends Activity {
String[] exampleList = {
"Item 1",
"Item 2",
"Item 3"
//etc etc
};
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listview);
// Get an instance of your listview in code
ListView listview = (ListView) findViewById(R.id.listview1);
// Set the listview's adapter
listview.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, exampleList));
}
}
This will give you the flexibility to have a layout with more than just a listview in it