How to dynamically add rows from a table (sqlite) to layout? (Android) - java

I am trying to take all the rows from my db and add it to the current layout, also, making each row clickable in the layout to take the user to a new screen with the id...
Here is my current code, but stuck on that part... I understand that I can put an onClickListener, but then does it have to be a button?
For a visual representation refer to a notepad app on any device where each note title appears and clicking on it takes you to that note.
public class MainActivity extends Activity implements OnClickListener {
private Button add_new_dictionary;
// Database helper
private DatabaseHelper db;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// db setup
db = new DatabaseHelper(getApplicationContext());
// get all dictionaries
List<db_dictionary> allDictionaries = db.getAllDictioniaries();
for (db_dictionary dictionary_found : allDictionaries) {
// create new view for each dictionary name include id and make it
// dynamic and include onclick to take to dictionary_view screen
Button dictionary_button = new Button(this);
}
add_new_dictionary = (Button) findViewById(R.id.add_new_dictionary);
}
#Override
public void onClick(View v) {
if (v == add_new_dictionary) {
Intent add_new_dictionary_intent = new Intent(MainActivity.this,
add_new_dictionary.class);
startActivity(add_new_dictionary_intent);
}
}
}
To re-iterate the question: How do I go about dynamically taking rows from my db and adding it to my layout dynamically based on how many results are returned from the query? (However, the rows should be able to point to a new screen with the dictionary id)

All views in android can implement the OnClickListener interface. So no, it doesn't HAVE to be a button.
As you've decided to use the activity to handle this then you need to tell your code to pass the event to your implementation wihin your activity.
// create new view for each dictionary name include id and make it
// dynamic and include onclick to take to dictionary_view screen
Button dictionary_button = new Button(this);
dictionary_button.setOnClickListener(this);
A trick I use to store information is the setTag method which would allow you to retrieve the correct reference during your onClick:
dictionary_button.setTag(some_record_id);
Then retrieve it later:
#Override
public void onClick(View v) {
if (v == add_new_dictionary) {
Intent add_new_dictionary_intent = new Intent(MainActivity.this,
add_new_dictionary.class);
startActivity(add_new_dictionary_intent);
}
else (
Object tag = v.getTag();
//now launch the detail activity using the data from the tag
}
}
You should really look into ListAdapters and cursors to do this properly, but this method should get you going for now

If you need to pick data from a db and show it as a list (getting click events) you should probably look into CursorAdapter and ListView
http://developer.android.com/reference/android/widget/CursorAdapter.html
http://developer.android.com/reference/android/widget/ListView.html
You can fins many examples on the web on how to use a cursoradapter and the listview

Related

onSave- / onRestoreInstanceState not working

The situation is that I want to create an app, which should be able to create a new TextView in a LinearLayout everytime a button is clicked. A text from and EditText ist assigned to said TextView. I managed to pull this off. However I've been struggling on how to save all of the created TextViews, once the app is closed and started up again. I tried using OnSaveInstanceState and OnRestoreInstance state to save an Array, to which I save every text that is displayed on a TextView. After restored I would check the size of the arraylist and create for a TextView for every value in the arraylist, so that all is restored. However, it doesn't work. I know, that the names are saved to the arraylist, however, nothing is restored, when I restart the app. Here's my Code:
public class MainActivity extends AppCompatActivity{
private ArrayList<String> SubjectArray = new ArrayList<String>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button savebtn = findViewById(R.id.MAINsave);
EditText newname = findViewById(R.id.newname);
CheckBox promo = findViewById(R.id.MAINpromo);
LinearLayout linearlayout = findViewById(R.id.MAINln);
savebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
newsub();
}
});
}
private void newsub(){
EditText newname = findViewById(R.id.newname);
CheckBox promo = findViewById(R.id.MAINpromo);
LinearLayout MAINln = findViewById(R.id.MAINln);
SubjectArray.add(newname.getText().toString());
Toast.makeText(MainActivity.this, "Added To Array", Toast.LENGTH_SHORT).show();
RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 200);
Params.setMargins(0, 10, 0, 10);
TextView newsubject = new TextView(MainActivity.this);
newsubject.setText(newname.getText().toString());
newsubject.setGravity(View.TEXT_ALIGNMENT_CENTER);
newsubject.setBackgroundColor(GRAY);
newsubject.setLayoutParams(Params);
MAINln.addView(newsubject);
}
#Override
protected void onRestoreInstanceState(#NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
SubjectArray = savedInstanceState.getStringArrayList("KEY_SUBJECTARRAY");
LinearLayout MAINln = findViewById(R.id.MAINln);
int subjectcount = SubjectArray.size();
for (int i = 0; i <= subjectcount; i++) {
RelativeLayout.LayoutParams Params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 200);
Params.setMargins(0, 10, 0, 10);
TextView restoredsubject = new TextView(MainActivity.this);
restoredsubject.setText(SubjectArray.get(i));
restoredsubject.setGravity(View.TEXT_ALIGNMENT_CENTER);
restoredsubject.setBackgroundColor(GRAY);
restoredsubject.setLayoutParams(Params);
MAINln.addView(restoredsubject);
}
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putStringArrayList("KEY_SUBJECTARRAY", SubjectArray);
}
}
you can manage a local database table and every time you are adding the new TextView just insert the Text of that TextView in the table . When you start your application first check the data of that table, if available then get the data in a list .
After getting list
Apply a loop on list size
Add a new textview inside body of loop
Set the current indexed text in Added TextView inside the loop.
you can clear table also when you need.
When you say "restart the app" you mean, a fresh start?
The savedInstanceState is not made for this. You save the state for moments when the instance of your Activity gets recreated.
As an example, when the user is turning the phone to landscape formatting. Then a onConfigurationChanged event happens (depends on how you set up your activity in the manifest) and onCreate gets called with the Bundle you saved in onSaveInstanceState.
To persist your state over app sessions, best approach is either saving it in the SharedPreferences (and loading them in onCreate of your MainActivity oder Application class) or to persist them in a database table.
The onRestoreInstanceState not made this purpose. It has a different purpose like, if your activity was previously destroyed and you going to recreate the activity again, at this you could be able to retrieve the saved data. For more details click here.
In this case, recommend using preferences or lightWeight persistence libraries like Room. So you could retrieve the details any point the app until clear the data of the app.

android - listview losing the rows of data when hitting back button

Please give me a hand with an issue I am having with a ListView and its related data in my android development project.
I have an activity called OrderForm that gets started by an Intent from the activity UserProfile as such:
In UserProfile
Intent intent = new Intent(this, OrderForm.class);
startActivity(intent);
Then in OrderForm there is an EditText and an add button to add String items to an ArrayList, and the UI gets populated accordingly.
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
I realize I can use Room for persistence and even SharedPreferences, but
I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
Thanks in advance.
Here is part of the code from OrderForm
public class OrderForm extends AppCompatActivity {
ArrayList<String> list;
ListView itemList;
ArrayAdapter<String> arrayAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_order_form);
itemList = findViewById(R.id.itemList);
itemText = findViewById(R.id.item);
linearLayout = findViewById(R.id.no_items_container);
orderContainer = findViewById(R.id.orderContainer);
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(this,
R.layout.list_item,R.id.rowItem, list)
{
#Override
public View getView(int position,
View convertView,
ViewGroup parent) {
// some custom stuff here
}
}
public void addItem(View view)
{
String item = itemText.getText().toString().trim().toLowerCase();
if(!item.isEmpty() && list.indexOf(item) == -1) {
arrayAdapter.add(item);
}
}
You need to understand how Activity lifecycles work.
https://developer.android.com/guide/components/activities/activity-lifecycle.html
Your issue is that when pressing the back button, your OrderForm Activity is destroyed and effectively your arraylist/list view is destroyed. To avoid this problem, you'll have to store the values somewhere for example SharedPreferences, create a text file holding your strings and store it, or return the arraylist back to the UserProfile class where you'll store/handle them (to do that use startActivityForResult() instead of startActivity())
When I click the back button (back to UserProfile) and go via the Intent to OrderForm again, the UI does not show the list items, why is that?
In your onCreate() method, you have this:
list = new ArrayList<>();
arrayAdapter = new ArrayAdapter<String>(..., list)...
Unless you persist your data in some way, list is always going to be empty when your activity starts up.
I realize I can use Room for persistence and even SharedPreferences, but I wanted to see if there is cleaner, more efficient method, otherwise the less code the better.
Exactly what you need to store will help define the best way to store it. For a simple list of strings, probably SharedPreferences is the simplest solution.
Also, maybe I'm not understanding them correctly, but I tried onSaveInstanceState and onRestoreInstanceState and they don't work for me.
These methods are used to store data when an activity is destroyed and then recreated, which commonly happens when the user rotates the device (but can also happen for various other reasons). When you exit your activity (by pressing back to UserProfile), these methods aren't triggered.

Dynamically Add and Save buttons in Android studio

Currently i managed to create the buttons dynamically on a view
Here is the my code to create the buttons;
public void Add_on(View v) {
AlertDialog.Builder mbuilder = new AlertDialog.Builder(Mb.this);
View mview = getLayoutInflater().inflate(R.layout.activity_mb1, null);
EditText number = (EditText) mview.findViewById(R.id.etnum);
Button Create = (Button) mview.findViewById(R.id.etcreate);
Button Cancel = (Button) mview.findViewById(R.id.etcancel);
Create.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
if (!number.getText().toString().isEmpty())
{
Toast.makeText(Mb.this, "Number can be NULL",Toast.LENGTH_SHORT).show();
LinearLayout yenilayout = new LinearLayout(Mb.this);
int n =1;
for(int i=0; i<n; i++)
{
Button yeniButton = new Button(Mb.this);
yenilayout.addView(yeniButton);
yeniButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(Mb.this, "Button is working",Toast.LENGTH_SHORT).show();
}
});
}
altlayout.addView(yenilayout);
} else {
Toast.makeText(Mb.this, "Number cannot be NULL",Toast.LENGTH_SHORT).show();
}
}
});
But whenever i recall the activity, the buttons are no longer exist. So May i know can i place the button there permanently?
Thank you for suggestions
You can use Bundle to save an activity's state and recreate it in the onCreate() method. This works for a particular instance of Activity, so can be used to save data concerning selection, or user input etc., but not data that you need to be persistent across application launches.
To use the Bundle, override the onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) methods in the Activity class. You can use methods from Bundle to save whatever data you like in a map, and get it back in onRestoreInstanceState(Bundle), which is called in onStart().
The default implementations already handle most UI stuff though, and I would have thought this would keep track of your buttons for you, so it may be that your question is actually about associating some persistent data with your application. (this also means that if you do override the above methods, you should make sure to call the super methods in the first line of your implementation).
If you need persistent data across application launches, then the quickest and easiest way would be to use SharedPreferences, see this answer for an example.

opening the same dialog from a list in android

I have a listActivity with many items.
For each item, I want to open the same popup while sending an item id\position\other
info object unique to that item.
But basically all the time I open the exact same popup.
Its buttons will send the extra unique data to the server.
I have read few tutorials, and saw a dialog is usually opened like this:
final Dialog dialog = new Dialog(context);
dialog.setContentView(R.layout.custom);
dialog.setTitle("Title...");
// set the custom dialog components - text, image and button
TextView text = (TextView) dialog.findViewById(R.id.text);
text.setText("Android custom dialog example!");
ImageView image = (ImageView) dialog.findViewById(R.id.image);
image.setImageResource(R.drawable.ic_launcher);
Button dialogButton = (Button) dialog.findViewById(R.id.dialogButtonOK);
// if button is clicked, close the custom dialog
dialogButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
dialog.dismiss();
}
});
dialog.show();
}
I think it's more readable to create a different file to the dialog.
like this:
public class SocialActionsDialog extends Dialog {
public SocialActionsDialog(Context context) {
super(context);
mContext = context;
}
Context mContext;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.social_actions);
setTitle("Title...");
}
but then I get a syntax error on the OnCreate.
Is it common and good practice to create new file? and if so- how to do it properly?
is it more efficient somehow - just showing the same dialog instead of initializing a new one each time? or is both ways the same?
For the syntax error, make sure you are importing the R class from your app and not the Android SDK class R resources.
For an experienced programmer your instinct is to move the dialog to a separate file, especially if it contains a lot of code. And that can be the right decision at times.
However, it is often convenient to have the dialog as an embedded class or to just create it inline (as in your example) because then it is within the scope of your activity and can access your state variables and protected methods on the Activity itself.
So you end up passing all this information to the dialog if you have it in a separate file, and at some point it just isn't worth it because the code becomes more complex and less maintainable.

TextView setText from another class

My problem is that i've a tabhost with two tabs.
The first is a listview and the second only have two textviews.
What i want is when i click on an item in the listview on tab one, the array position id (int) should be sent to tab/class two, where there is an array who fetches a text by the position id that was sent.
The switching of tabs is done, but i fail everytime i try to send the position-id.
This is how i send it:
TAB ONE:
//This function is called when i click a listitem
public void setDetails(String Text, long arr_id){
Detail detail = new Detail();
detail.setDetail(); // right now i don't send the parameters because it wont even work with or without it.
}
TAB TWO:
TextView descr;
TextView title;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detail);
descr = (TextView)findViewById(R.id.desc);
title = (TextView)findViewById(R.id.title);
}
public void setDetailText(String Text){
descr.setText(Text);
}
public void setDetailTitle(String Text){
title.setText(Text);
}
public void setDetail(){
this.setDetailTitle("example text");
this.setDetailText("example text2");
}
I want to set the text on tab two BEFORE it switch to tab two.
This works if i use SetDetail() and setDetailTitle() in the same tab/class, but not in another.
I've googled my ass off, please help me
i do this in my code using getParent() or getActivity() methods in my TabActivity and inner Activitys, cause if we use a TabActivity (wich subclass the ActivityGroup class) we can obtain the 'TextActivity' using ActivityManager and obtain the activity instance, so, here we can call the setDetail() method, and this will execute before the Activity is showed,
in your ListActivity do something like this
((MyTextActivity)((MyTabActivity)getParent()).getLocalActivityManager().getActivity(ACTIVITY_ID)).setDetail();
this works only if in you start the childs activity within your TabActivity with:
intent = new Intent(ACTIVITY_ID).setClass(this, MyMapActivity.class);
getLocalActivityManager().startActivity(ACTIVITY_ID, intent);

Categories