Start a particular intent using ArrayList - java

I want to start an explicit intent , Here is the code
public class TabView extends ListActivity {
List<String> list1strings = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.tview);
ListView listview1 = (ListView) findViewById(R.id.list1);
TabHost th = (TabHost) findViewById(android.R.id.tabhost);
th.setup();
list1strings.add("Programming Language");
list1strings.add("Database");
list1strings.add("Java Technologies");
list1strings.add("Web Technologies");
list1strings.add("Application/Web Server");
list1strings.add("operating Systems");
list1strings.add("PHP framework");
list1strings.add("PHP CMS");
listview1.setAdapter(new ArrayAdapter<String>(TabView.this,
android.R.layout.simple_list_item_1, list1strings));
th.addTab(th.newTabSpec("Tab1").setIndicator("Training")
.setContent(R.id.tab1));
TabSpec specs = th.newTabSpec("Tab2");
specs.setContent(R.id.tab2);
specs.setIndicator("Workshops");
th.addTab(specs);
specs = th.newTabSpec("Tab 3");
specs.setContent(R.id.tab3);
specs.setIndicator("Reach Us");
th.addTab(specs);
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
super.onListItemClick(l, v, position, id);
String getpos = list1strings.get(position);
try {
Class<?> ourclass = Class.forName("in.brainwave.industrialtraining." + getpos);
Intent ourIntent = new Intent(TabView.this, ourclass);
startActivity(ourIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
"list1string" here have data and I want to start an intent when an item on ListView is clicked , but the problem is that class name cannot have space and "String getpos = list1strings.get(position);" returns the string from ArrayList which contains space , Is there any way so that I can start an Intent when any item is clicked.
Please guide me .

You can just initialize a second array/list with the classes of each item, so when you select item N you get the class at the same position. For example:
ArrayList<String> listItems = new ArrayList<String>();
ArrayList<Class> classes = new ArrayList<Class>();
listItems.add("Programming");
classes.add(YourProgrammingActivity.class);
// (...)
listItems.add("PHP CMS");
classes.add(YourPHPCMSActivity.class);
And then to start the right activity in the listener:
Class activityToStart = classes.get(position);
Intent ourIntent = new Intent(TabView.this, activityToStart);
startActivity(ourIntent);
As you can guess, each class you put in that list should be an activity (and be declared in AndroidManifest), otherwise your app will crash.
Also if this is a fixed list, replacing ArrayList with arrays is much less verbose:
String[SIZE] listItems = {"Programming", /* (...) */, "PHP CMS"};
Class[SIZE] classes = {YourProgrammingActivity.class, /* (...) */, YourPHPCMSActivity.class };
(...)
Class activityToStart = classes[position];

From an Object Oriented Perspective you can encapsulate this information in one class and do a for loop to do it in an automatic manner. Let me show you (and remember there are multiple possible options, in doing this).
Keep in mind that this is more or less pseudocode that looks exactly to Java but I programed from memory, so there could be errors and typos!
First of all let met tell you that there are some things that are done in a "bad" way. For example this piece of code will never work:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
String getpos = list1strings.get(position);
try {
Class<?> ourclass = Class.forName("in.brainwave.industrialtraining." + getpos);
Intent ourIntent = new Intent(TabView.this, ourclass);
startActivity(ourIntent);
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
Because you are storing Strings which are titles! Not even Java class names. The best way is to create a class that encapsulate the information you need. This class keeps all information you need to provide to the different components.
public class TabEntry {
// In here you save the real class to be invoked in the listener
private Class mEntryClass;
// You store the title of the tab
private String mTabTitle;
// In here you store the content tab id like R.id.tab3
private int mContentId;
// Add more fields as necessary
...
public TabEntry(Class clazz, String tabTitle, int contentId) {
this.mClass = clazz;
this.mTabTitle = tabTitle;
}
public Class getEntryClass() {
return this.mEntryClass;
}
public String getTabTitle() {
return this.mTabTitle;
}
// Add more getters as needed
}
So right now, you have created a class that encapsulates the information you need to create your tabs. Now in the code of the TabActivity:
public class TabView extends ListActivity {
List<TabEntry> mListTabEntries = new ArrayList<TabEntry>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tview);
ListView listview1 = (ListView) findViewById(R.id.list1);
TabHost th = (TabHost) findViewById(android.R.id.tabhost);
th.setup();
// Initalize your list with your tabs entries, this should be done outside this method
// to don't clutter your code
mListTabEntries.add(new TabEntry(Activity1.class, "Title", R.id.text1));
mListTabEntries.add(new TabEntry(Activity2.class, "Title2", R.id.text2));
listview1.setAdapter(new ArrayAdapter<String>(TabView.this,
android.R.layout.simple_list_item_1, getTabsStrings(mListTabEntries)));
// Create a for loop to iterate each entry in your list, so you dont have to do it
// manually
for (TabEntry entry : mListTabEntries) {
th.addTab(th.newTabSpec(entry.getTabTitle())
.setIndicator(entry.getIndictor())
.setContent(entry.getContent());
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
TabEntry entry = list1strings.get(position);
Intent ourIntent = new Intent(TabView.this, entry.getTabClass());
startActivity(ourIntent);
}
private String[] getTabsStrings(List<TabEntry> mEntries) {
String[] titlesString = new String[mEntries.size()];
for(int i = 0; i < mEntries.length(); i++) {
titlesString[i] = mEntries.get(i);
}
return titlesString;
}
}
At this point this code should work (but IMHO it not the prettiest one). So we can do better (if you want learn more about code, you can read Clean Code or Effective Java, both books are great to improve your skills with programming).
If you want to learn more about how we can make this code more pretty and succinct let me know! :)

Related

Permanently save intent from other activity (with two values) to listview

I'm trying to save two values from an activity (where the user can put in two different values, one String value and one integer value) in the listview from another activity. In the first activity, it shows a list with a course and the amount of points for that course in one listview, like this:
Course: English
Points: 4
Now, the problem is, everytime I want to put in another value using the add_course_actitivty, it overwrites the previous value. I've looked at different solutions, like with sharedpreferences (Add items to listview from other activity), but this uses only one value and if I try to work with sharedpreferences, it overwrites the other value in the sharedpreferences, but I want users to add multiple courses and corresponding points. Also on restart, it deletes the values in the listview (I read to prevent this you need to store it in sharedpreferences, but this doesn't work the way I need it to be)
KeuzeActivity.class (shows the listview):
public class KeuzeActivity extends AppCompatActivity {
private FloatingActionButton fab_add;
private String student_naam;
private ListView keuze_list;
boolean wantDelete;
private ArrayAdapter adapter;
private String vak;
private int ec;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_keuze);
// setting title
student_naam = getIntent().getStringExtra("student");
setTitle("Keuzevakken en projecten van " + student_naam);
//initialzing elements
fab_add = (FloatingActionButton)findViewById(R.id.fab_add);
keuze_list = (ListView) findViewById(R.id.keuze_list);
//initializing list
final ArrayList<Course> courseItems = new ArrayList<Course>();
adapter = new ArrayAdapter<Course>(this, android.R.layout.simple_list_item_1, courseItems);
keuze_list.setAdapter(adapter);
// checks if intent has required values, put it in listview
if (getIntent().hasExtra("vak") && getIntent().hasExtra("ec")) {
vak = getIntent().getStringExtra("vak");
ec = getIntent().getIntExtra("ec", ec);
courseItems.add(new Course(vak, ec));
adapter.notifyDataSetChanged();
}
// make fab go to other activity
fab_add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(KeuzeActivity.this, add_course_activity.class));
}
});
// long press deletes item
keuze_list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
#Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showDeleteDialog();
if (wantDelete) {
courseItems.remove(position);
adapter.notifyDataSetChanged();
}
return true;
}
});
}
private void showDeleteDialog() {
AlertDialog.Builder infobuilder = new AlertDialog.Builder(this);
infobuilder.setCancelable(false);
infobuilder.setTitle("Vak/project verwijderen");
infobuilder.setMessage("Weet je zeker dat je het vak of project wilt verwijderen?");
final TextView text = new TextView(this);
// action when pressed OK
infobuilder.setPositiveButton("Ja", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
wantDelete = true;
dialog.cancel();
}
});
infobuilder.setNegativeButton("Nee", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
wantDelete = false;
dialog.cancel();
}
});
infobuilder.show();
}
}
add_course_activity.class (let's users input course and points)
public class add_course_activity extends AppCompatActivity {
private EditText course_edit;
private EditText ec_edit;
private Button save_btn;
private String student_name;
private int ec;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_course);
setTitle("Voeg vak of project toe");
final Context context = getApplicationContext();
// initializing elements
course_edit = (EditText) findViewById(R.id.edit_vak);
ec_edit = (EditText) findViewById(R.id.edit_ec);
save_btn = (Button) findViewById(R.id.save_button);
// action on savebutton
save_btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (course_edit.getText().toString().trim().length() > 0 && ec_edit.getText().toString().trim().length() > 0 ) {
ec = Integer.parseInt(ec_edit.getText().toString());
Intent goBack = new Intent(add_course_activity.this, KeuzeActivity.class);
goBack.putExtra("vak", course_edit.getText().toString());
goBack.putExtra("ec", ec);
goBack.putExtra("student", PreferenceManager.getDefaultSharedPreferences(context).getString("student_name", student_name));
startActivity(goBack);
}
else {
Toast.makeText(context, "Voer juiste informatie in!", Toast.LENGTH_SHORT).show();
}
}
});
}
}
Course.java class (getters and setters + with toString method)
public class Course {
private String vak;
private int ec;
public Course(String vak, int ec) {
this.vak = vak;
this.ec = ec;
}
public String getVak() {
return vak;
}
public void setVak(String vak) {
this.vak = vak;
}
public int getEc() {
return ec;
}
public void setEc(int ec) {
this.ec = ec;
}
#Override
public String toString() {
return ("Vak: " + vak + "\n" + "Punten: " + ec);
}
}
Note that my code isn't clean or done, but to get further I need to fix this problem.
You have several way to do it. As other replies have suggested you can use an SQLLite database and add data to a course table and retrieve data from it.
If you find Db approach to complicated/heavy
You could also use SharedPreferences what you need to do is figure a way to store a string that represent a list of course. It is not the best way to approach it but it will work.
Lets say you choose to serialize your Course object with "vac-ec"
Then you just store a serialized list of course. Example "vac1-ec1,vac2-ec2"
When you need to add a course you juste grab the previous string split it to list, append the new course to the list and re-serialize the list to a string to encode it.
Other solution could be to use Realm.
You should used SQLiteDatabase and create a table with valid attributes and insert your new values into them
Okay, now things are clearer. As answered by #Dwijraj, when storing what potentially will be a large set of data, for maximum control it is best to use SQLite.
You can read more about the different Saving Data methods here:
https://developer.android.com/training/basics/data-storage/index.html
SharedPreferences are best used to store small amounts of information, like storing the settings of an application. [Mute] for example. Or a highscore in case of a game.
A Database is a better option when it comes to storing large pieces of data that you will potentially manipulate.
Your data structure can be something like this, Courses table containing Unique_ID , Course Name, Course Level, Course summary.
A table for English for example which will contain
Exams, Scores, Duration.
There are a lot of things you can do.
Try by storing the records in SQLite, and get it when you want to show.
By this, You can have a track of all added items. And you can show the items you want.

Android - How to make an Activity for each item in a ListView and pass Java Object to next screen

I have a ListView of contacts and each contact is a Java object with a bunch of information associated with it. Some of that info is shown in the ListView, but the rest is meant for the DetailView. I'm trying to write a method that will take me to a DetailView for any contact I click on, but I also need to take the object with me. I store all of the contacts in an ArrayList in my MainActivity.java
My questions: Do I need to take the contact object with me or is there actually some way to access my ArrayList in another Activity?
If I can/have to take it with me, how would I do so, since the putExtra() methods don't take objects as arguments.
The beginning of my MainActivity looks like this:
public class MainActivity extends Activity implements AdapterView.OnItemClickListener {
ListView list;
I have a very basic onClickListener right now but don't know what to put into it:
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(MainActivity.this, DetailView.class);
intent.putExtra("contact", i);
startActivity(intent);
}
I feel like my initial definition of the MainActivity class doesn't correspond to the onItemClick method or something, which is why it doesn't execute and take me to another screen.
Intent intent = new Intent(ActivityA.this, DetailView.class);
intent.putExtra("extra_name","extra");
startActivity(intent);
Then in the other Activity :
/*onCreate*/
Object extra = getIntent().getExtra().get("extra_name");
I would recommend to pass an ID of some sort pointing to the description, passing complex data structure with intents is not recommended
Simply, use Intent.putExtra() to pass the information and getIntent().getExtras() to receive the information.
// call a new intent
myIntent = new Intent(ActivityA.this, ActivityB.class);
// put an extra (like this following string)
String userid = "User A";
myIntent.putExtra("TAG_CONTACT_ID", userid);
startActivity(myIntent);
// receive the info in your onCreate method in ActivityB
Bundle extras = getIntent().getExtras();
if(extras != null) {
String newUserID = extras.getString("TAG_CONTACT_ID");
}
See this short example for more information.
If you want to pass an Integer, you can do it as the following: myIntent.putExtra("value", i); and take it with: int myValue = extras.getInt("value");.
Hope this help.
Try something like this:
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Contact c = (Contact)contacts.get(position);
Intent i = new Intent();
i.putExtras("contact", c);
i.setClass(this, Activity2.class);
startActivity(i);
}
Create java object with parcelable
Check the below code to create parcelable object in Android.
public class ObjFeedImages implements Parcelable {
public int image_id;
public boolean like_status = false;
public String image_url = null;
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeStringArray(new String[] {
String.valueOf(image_id),
String.valueOf(like_status),
image_url, });
}
public ObjFeedImages(Parcel in) {
String[] data = new String[3];
int i = 0;
in.readStringArray(data);
image_id = Integer.parseInt(data[i++]);//
like_status = Boolean.parseBoolean(data[i++]);
image_url = data[i++];
}
public static final Parcelable.Creator<ObjFeedImages> CREATOR = new Parcelable.Creator<ObjFeedImages>() {
#Override
public ObjFeedImages createFromParcel(Parcel source) {
try {
return new ObjFeedImages(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
#Override
public ObjFeedImages[] newArray(int size) {
try {
return new ObjFeedImages[size];
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
};
}
After creating some list of such object say
ObjFeedImages object = new ObjFeedImages();
object.image_id = 1;
object.like_status = true;
object.image_url="http://some image url";
Intent intent = new Intent(/*Your Intent Info*/);
intent.putExtras("key_name",object);
startActivity(intent);
Here is the complete description.
To retrive object in other activity you have to write below code.
ObjFeedImages objectOnOtherActivity = (ObjFeedImages)getIntent().getParcelableExtra("key_name");
So ready to enjoy code.
Happy coding....

How to make listView say one thing, but pass through different data

So this question is a little hard to explain, but basically what i want is to have an array list for a listview, but change the title on the listview. So that when the user sees the listview it says one thing, but passes through different information.
Here's my code:
//the string names
String names[] = { "item1", "item2"};
i have 2 classes called item1.java and item2.java
when one listitem is clicked it sets a class equal to the activity name and opens it like this:
protected void onListItemClick(ListView lv, View v, int position, long id){
super.onListItemClick(lv, v, position, id);
String openClass = names[position];
try{
Class selected = Class.forName("com.example.example." + openClass);
Intent selectedIntent = new Intent(this, selected);
startActivity(selectedIntent);
}catch (ClassNotFoundException e){
e.printStackTrace();
}
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
finish();
}
But in the listview i don't want it to say "item1" and "item2"....is there any way to make like an alias or something?
Sorry if my question is hard to understand i tried my best to explain what i need help with let me know if you have any questions about my question(: thanks for the help
You do this the same way you make any custom adapter, such as one that should display images instead of or in addition to some text.
For example, if your adapter is an ArrayAdapter, you create a subclass, override getView(), and do what you want in there to format your rows the way that you want.
You can override toString() to do this. See following example
public static class Alias {
String originalValue;
public Alias(String s) {
this.originalValue = s;
}
#Override
public String toString() {
return "What are you want to show";
}
}
String names[] = {"item1", "item2"};
Alias array[] = new Alias[names.length];
Alias array[0] = new Alias(names[0]);
Alias array[1] = new Alias(names[1]);
ArrayAdapter<Alias> adapter = new ArrayAdapter<Alias>(this, resId, array);
This will show "What are you want to show" in every listview whatever the value is.

Android - saving checked items of a ListView on app shutdown

I am making an application for the Android platform in Eclipse, and I need help with something. :)
What I want for one part to do is create an arraylist from items that are checked in another ListView. I figured out how to make that and here is the code:
public class MusicList extends Activity {
private ListView lvCheckBox;
private String[] arr = { "Depeche Mode", "The Prodigy", "Rammstein",
"Manilla Road", "Led Zeppelin", "AC/DC", "Massive Attack",
"Skrillex", "Deadmau5" };
ArrayList<String> arrList;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.musiclist);
lvCheckBox = (ListView) findViewById(R.id.lvCheckBox);
lvCheckBox.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
lvCheckBox.setAdapter(new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_checked, arr));
arrList = new ArrayList<String>();
lvCheckBox.setOnItemClickListener(new OnItemClickListener(){
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// TODO Auto-generated method stub
if(arrList.contains(lvCheckBox.getItemAtPosition(arg2).toString()))
{
arrList.remove(lvCheckBox.getItemAtPosition(arg2).toString());
}
else
{
arrList.add(lvCheckBox.getItemAtPosition(arg2).toString());
}
Collections.sort(arrList);
String strText = "";
for(int i=0 ; i<arrList.size(); i++)
strText += arrList.get(i) + ",";
Toast.makeText(MusicList.this, "Item Clicked: "+ strText, Toast.LENGTH_SHORT).show();
}
});
}
}
BUT!
Now I need to save that arraylist (like some "user settings" (actually the music which the user likes)) even when the app closes completely and when I come back to the list screen previously checked items need to be checked again (bear in mind I will be adding a lot more musicians to the starting list!!). So, anyone knows how to do that? :)
That's all, thanks in advance, and also I am new here so sorry if I messed something up :(
Android has a SharedPreferences class that will allow you to save information to the App's "cache".
So, you'd be able to save and retrieve the list information.
http://developer.android.com/reference/android/content/SharedPreferences.html

Android - call method instead of class - sdk

I have my main application class as follows and what I would like to know is how to change one line to call a method either from same class or another class, whilst the others still call activities. Here is the code:
public class InfoActivity extends GDListActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTitle(R.string.info_activity_title);
ItemAdapter adapter = new ItemAdapter(this);
adapter.add(createTextItem(R.string.info_about, AboutActivity.class));
adapter.add(createTextItem(R.string.info_terms, TermsActivity.class));
adapter.add(createTextItem(R.string.info_privacy, PrivacyActivity.class));
setListAdapter(adapter);
}
private TextItem createTextItem(int stringId, Class<?> klass) {
final TextItem textItem = new TextItem(getString(stringId));
textItem.setTag(klass);
return textItem;
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
final TextItem textItem = (TextItem) l.getAdapter().getItem(position);
Intent intent = new Intent(InfoActivity.this, (Class<?>) textItem.getTag());
startActivity(intent);
}
}
The line in question:
adapter.add(createTextItem(R.string.info_about, AboutActivity.class));
I would like to call a method which as an example does this:
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] { AboutActivity.this.getString(R.string.feedback_email) } );
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT, AboutActivity.this.getString(R.string.feedback_subject));
emailIntent.setType("plain/text");
startActivity(emailIntent);
Right now I have this in the onCreate method of AboutActivity, but there naturally is no reason to have this functionality (sending email) within an activity. Instead it can just be ran as is. So, how could I do this?
Thanks!
The other two lines:
adapter.add(createTextItem(R.string.info_terms, TermsActivity.class));
adapter.add(createTextItem(R.string.info_privacy, PrivacyActivity.class));
they can remain the same in terms of functionality. This question is an addendum from this one (which I asked earlier and got answered):
Android - call method instead of class - sdk
How ever you choose to go about this, the trick is to actually move the decision making about what to do when a particular item is clicked down into the onListItemClick method. Here's a simple approach. First, change your createTextItem method to this:
private TextItem createTextItem(int stringId) {
final TextItem textItem = new TextItem(getString(stringId));
return textItem;
}
Then, change your onListItemClick to this:
protected void onListItemClick(ListView l, View v, int position, long id) {
final TextItem textItem = (TextItem) l.getAdapter().getItem(position);
String textItemContents = textItem.getString(); //I don't know if this is actually correct. I don't know what the TextItem class is. But I think you get the idea.
Intent intent = getIntentForString(textItemContents);
startActivity(Intent);
}
Your getIntentForString() method would then look something like this (note we can't use a switch because support for using switch statements with strings has only just recently been added to java):
private Intent getIntentForString(String textViewContents){
if(textViewContents.equals(getString(R.string.info_about))){
Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL, new String[] {
AboutActivity.this.getString(R.string.feedback_email) } );
emailIntent.putExtra(android.content.Intent.EXTRA_SUBJECT,
AboutActivity.this.getString(R.string.feedback_subject));
emailIntent.setType("plain/text");
return emailIntent;
}
else if(textViewContents.equals(getString(R.string.info_terms)){
return new Intent(InfoActivity.this, TermsActivity.class);
}
else if(textViewContents.equals(getString(R.string.info_privacy)){
return new Intent(InfoActivity.this, Privacy.class);
}
else{
return null;
}
}
Note this approach has a downfall though. If yous start adding a bunch of different items to your ListView you're going to need to grow and grow your getIntentForString() method. For right now though, this should suffice. If you find yourself adding more options to your ListView though they'll be a more complicated approach that we'll need to take.

Categories