How to switch activity with item specific data sent - java

I've had a look around, and it might be because I'm not sure what I'm looking for, but I can't find out how to do something I presume should be quite easy with android.
I have an array of data to display on the screen. This data is a class that holds a database key, name and image.
I'm currently displaying this data as an ImageView and a TextView. I loop through the array and add a new row to a TableLayout containing the image and text.
I'd like both the image and text to be clickable, changing to a new activity.
This new activity needs to know the database key of the row clicked in order to display the correct data.
Here's what I have so far:
private void fillSuggestionTable(TableLayout tabSuggestions, Suggestion[] arrToAdd)
{
for(int i = 0; i < arrToAdd.length; i++)
{
/* Create a new row to be added. */
TableRow trSuggestion = new TableRow(this);
trSuggestion.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
/* Create objects for the row-content. */
ImageView imgDisplayPicture = new ImageView(this);
ImageHandler.loadBitmap(arrToAdd[i].strImageURL, imgDisplayPicture);
imgDisplayPicture.setLayoutParams(new LayoutParams(50,50));
TextView txtArtistName = new TextView(this);
txtArtistName.setText(arrToAdd[i].strName);
txtArtistName.setTextColor(Color.parseColor("#000000"));
/* Add data to row. */
trSuggestion.addView(imgDisplayPicture);
trSuggestion.addView(txtArtistName);
/* Add row to TableLayout. */
tabSuggestions.addView(trSuggestion, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
}

Is there a reason you're using a TableView? it seems like what you want to accomplish would be much easier with a ListView & custom CursorAdapter, where the adapter can handle translating from the database to the ListView row. At that point starting a new activity that knows the database ID is trivial:
mListView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick (AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(MyActivity.this, MyOtherActivity.class);
i.putExtra("database_id", id);
startActivity(i);
}
});
And in MyOtherActivity:
private int dbId;
protected void onCreate(Bundle savedInstanceState) {
//do stuff
dbId = getIntent().getIntExtra("database_id", -1); // the -1 is the default if the extra can't be found
}

To pass extra data to another Activity, you need to add extra information with the Intent.putExtra(name, value) methods.
For example, to send the Intent:
Intent i = new Intent([pass info about next Activity here]);
i.putExtra("databaseKey", databaseKey);
startActivity(i);
To get the data out again:
public void onCreate(Bundle savedInstance)
{
// Do all initial setup here
Bundle extras = getIntent().getExtras();
if (extras != null && extras.containsKey("databaseKey"))
{
int databaseKey = extras.getInt("databaseKey");
// Load database info
}
else
{
// No data was passed, do something else
}
}
EDIT: To find out when the table's row is clicked, you'll need to implement View.OnClickListener and set the onClickListener for the TableRows you use.
For example:
/* Create a new row to be added. */
TableRow trSuggestion = new TableRow(this);
trSuggestion.setOnClickListener([listener]);
The only problem you'll have is relating a View's ID to the related database row ID. A HashMap should help.

This is a pretty simple procedure. This blog explains it in simple terms.

Related

How to dynamically add items to GridView Android Studio (Java)

Hello I want to have an Add function that allows me to input items to my GridView
For Background: I have a standard GridView and an XML activity (which contains 2 TextView) that I want to convert to my GridView. I also have a custom ArrayAdapter class and custom Word object (takes 2 Strings variables) that helps me do this.
My problem: I want to have an Add button that takes me to another XML-Layout/class and IDEALLY it input a single item and so when the user goes back to MainActivity the GridView would be updated along with the previous information that I currently hard-coded atm. This previous sentence doesn't work currently
Custom ArrayAdapter and 'WordFolder' is my custom String object that has 2 getters
//constructor - it takes the context and the list of words
WordAdapter(Context context, ArrayList<WordFolder> word){
super(context, 0, word);
}
#Override
public View getView(int position, View convertView, ViewGroup parent){
View listItemView = convertView;
if(listItemView == null){
listItemView = LayoutInflater.from(getContext()).inflate(R.layout.folder_view, parent, false);
}
//Getting the current word
WordFolder currentWord = getItem(position);
//making the 2 text view to match our word_folder.xml
TextView title = (TextView) listItemView.findViewById(R.id.title);
title.setText(currentWord.getTitle());
TextView desc = (TextView) listItemView.findViewById(R.id.desc);
desc.setText(currentWord.getTitleDesc());
return listItemView;
}
}
Here is my NewFolder code. Which sets contentview to a different XML. it's pretty empty since I'm lost on what to do
public class NewFolder extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_folder_view);
Button add = (Button) findViewById(R.id.add);
//If the user clicks the add button - it will save the contents to the Word Class
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//make TextView variables and cast the contents to a string and save it to a String variable
TextView name = (TextView) findViewById(R.id.new_folder);
String title = (String) name.getText();
TextView descText = (TextView) findViewById(R.id.desc);
String desc = (String) descText.getText();
//Save it to the Word class
ArrayList<WordFolder> word = new ArrayList<>();
word.add(new WordFolder(title, desc));
//goes back to the MainActivity
Intent intent = new Intent(NewFolder.this, MainActivity.class);
startActivity(intent);
}
});
}
In my WordFolder class I made some TextView variables and save the strings to my ArrayList<> object but so far it's been useless since it doesn't interact with the previous ArrayList<> in ActivityMain which makes sense because its an entirely new object. I thought about making the ArrayList a global variable which atm it doesn't make sense to me and I'm currently lost.
Sample code would be appreciative but looking for a sense of direction on what to do next. I can provide other code if necessary. Thank you
To pass data between Activities to need to do a few things:
First, when the user presses your "Add" button, you want to start the second activity in a way that allows it to return a result. this means, that instead of using startActivity you need to use startActivityForResult.
This method takes an intent and an int.
Use the same intent you used in startActivity.
The int should be a code that helps you identify where a result came from, when a result comes. For this, define some constant in your ActivityMain class:
private static final int ADD_RESULT_CODE = 123;
Now, your button's click listener should looks something like this:
addButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View arg0) {
Intent intent=new Intent(MainActivity.this, NewFolder.class);
startActivityForResult(intent, ADD_RESULT_CODE);
}
});
Now for returning the result.
First, you shouldn't go back to your main activity by starting another intent.
Instead, you should use finish() (which is a method defined in AppCompatActivity, you can use to finish your activity), this will return the user to the last place he was before this activity - ActivityMain.
And to return some data, too, you can use this code:
Intent intent=new Intent();
intent.putExtra("title",title);
intent.putExtra("desc",desc);
setResult(Activity.RESULT_OK, intent);
where title and desc are the variables you want to pass.
in your case it should look something like this:
public class NewFolder extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.new_folder_view);
Button add = (Button) findViewById(R.id.add);
//If the user clicks the add button - it will save the contents to the Word Class
add.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//make TextView variables and cast the contents to a string and save it to a String variable
TextView name = (TextView) findViewById(R.id.new_folder);
String title = (String) name.getText();
TextView descText = (TextView) findViewById(R.id.desc);
String desc = (String) descText.getText();
//Save it to the Word class
ArrayList<WordFolder> word = new ArrayList<>();
word.add(new WordFolder(title, desc));
Intent intent=new Intent();
intent.putExtra("title",title);
intent.putExtra("desc",desc);
setResult(Activity.RESULT_OK, intent);
//goes back to the MainActivity
finish();
}
});
}
You should probably also take care of the case where the user changed his mind and wants to cancel adding an item. in this case you should:
setResult(Activity.RESULT_CANCELLED);
finish();
In your ActivityMain you will have the result code, and if its Activity.RESULT_OK you'll know you should add a new item, but if its Activity.RESULT_CANCELLED you'll know that the user changed their mind
Now all that's left is receiving the data in ActivityMain, and doing whatever you want to do with it (like adding it to the grid view).
To do this you need to override a method called onActivityResult inside ActivityMain:
// Call Back method to get the Message form other Activity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
super.onActivityResult(requestCode, resultCode, data);
// check the result code to know where the result came from
//and check that the result code is OK
if(resultCode == Activity.RESULT_OK && requestCode == ADD_RESULT_CODE )
{
String title = data.getStringExtra("title");
String desc = data.getStringExtra("desc");
//... now, do whatever you want with these variables in ActivityMain.
}
}

Getting a button to work in the list view

I am new to android and my code has got a bit messy. I have successfully created a list view extended from item_layout.xml. When I click on the list view It works exactly how I want it. However in each item of the list view I have a button that when clicked I want the item of the list to delete.
When researching I have come across that you need to create a customer adapter to do this however I have come so far in the project that I wouldn't even know where to start.
This code it used successfully to when the list items are clicked it works. This is just put in the Main Activity class
mylist.setOnItemClickListener(
new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
}
}
);
I populate the list using this function just outside the main activity class. It is needed to be written like this as It gets the items from a database and has to be called depending on different circumstances
private void populatelistView() {
Cursor res = userDb.getAllRows();
String[] fromFeildnames = new String[]{ DatabaseUser.KEY_1, DatabaseUser.KEY_2};
int[] toViewIds = new int[]{R.id.textViewNum, R.id.textViewItem};
SimpleCursorAdapter myCursorAdaptor;
myCursorAdaptor = new SimpleCursorAdapter(getBaseContext(), R.layout.item_layout, res, fromFeildnames, toViewIds, 0);
//ListView mylist = (ListView) findViewById(R.id.listViewID);
mylist.setAdapter(myCursorAdaptor);
}
I would like to be able to get the button on each items to work by not changing much of what I have already written. I have tried just using the following code. But because it is in a different xml layout it display an error of null reference towards the item button
delete.setOnClickListener(
new View.OnClickListener() {
#Override
public void onClick(View v) {
View parentRow = (View) v.getParent();
ListView listView = (ListView) parentRow.getParent();
final int position = listView.getPositionForView(parentRow);
Toast.makeText(getApplicationContext(), "Button " + position, Toast.LENGTH_SHORT).show();
}
}
);
Please could someone help me make the button work without changing much code or give me a step by step tutorial on how to add an adapter but make my populateListView function do the same thing.
Ps. I have looked at so many tutorials about list adapters but can't find ones that are for my specific need

Android ListView: How to add a row with a buttonclick

I have a listview. In it, each row had a text saying 0:00. But now, I added a button on my actionbar but then I got stuck. I don't know how to make the button create a new row, displaying 0:00
This is my code for the data in a row.
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RowData rowdata_data[] = new RowData[]
{
new RowData("0:00")
};
RowdataAdapter adapter = new RowdataAdapter(this,
R.layout.listview_item_row, rowdata_data);
listView1.setAdapter(adapter);
listView1 = (ListView)findViewById(R.id.listView1);
}
this is my RowData class:
public class RowData {
String title;
public RowData(String title) {
this.title = title;
}
}
So how should I implement a button click to add another row?
Under addtionbutton: should be the method.
public boolean onOptionsItemSelected(MenuItem item)
{
// Handle presses on the action bar items
switch (item.getItemId())
{
case R.id.additionbutton:
return true;
default:
return super.onOptionsItemSelected(item);
}
}
I don't know how to make the button create a new row
With your current solution it's not possible (in efficient way do it) because you're using static array of objects - it means array has fixed size (it means that you're assuming that size won't be changed at runtime).
But your goal is "slightly" different. You want after each click on Button increase number of objects by one. It means you don't know exactly how many rows you can have (or can be changed at runtime).
Due to things mentioned above you should (have to) use dynamic array with changeable size. For this reason you need to use as source of data List that is representation of dynamic array.
Basic algorithm:
Create new List with zero (or you can have by default one row at
start).
Then create public method in your adapter that will add new item to
collection and send request that Adapter should be refreshed (after you added new row into collection).
Assign OnClickListener to your Button and in onClick() method you'll use created method for adding new row into ListView.
Solution:
How to initialise ListAdapter:
// Activity-level variable scope
private List<RowData> items = new ArrayList<RowData>();
private RowdataAdapter adapter;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
listView1 = (ListView)findViewById(R.id.listView1);
// adding first item to List, it's optional step
items.add(new RowData("0:00"));
adapter = new RowdataAdapter(this, R.layout.listview_item_row, items);
listView1.setAdapter(adapter);
}
Method for adding new row into ListAdapter:
public void addRow(RowData newRow) {
// items represents List<RowData> in your Adapter class
this.items.add(newRow);
// sends request to update ListAdapter
notifyDataSetChanged();
}
How to update Adapter after click on Button:
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// add new row to Adapter
adapter.addRow(new RowData("0:00"));
}
});
Hope i helped you to solve your problem.
you need to create a dataset that you can change so you need to make your array a class wide variable so you can add to it when you need to
when you add the new row you need to notify the adapter that something changed so you do this
adapter.notifyDatasetChanged();
and that should update your list

Android BaseAdapters & Multiple Listviews

I am currently creating a basic news aggregator app for Android, I have so far managed to create multiple HorizontalListViews derived from this: http://www.dev-smart.com/archives/34
I am parsing all data from live JSON objects and arrays.
The process goes something like this:
1) Start app
2) Grab a JSON file which lists all feeds to display
3) Parse feed titles and article links, add each to an array
4) Get number of feeds from array and create individual HorizontalListView for each. i.e. "Irish Times".
5) Apply BaseAdapter "mAdapter" to each HorizontalListView during creation.
My baseadapter is responsible for populating my HorizontalListViews by getting each title and thumbnail.
My problem is however that all my feeds seem to contain the same articles and thumbnails. Now I am only new to Android so I'm not 100% sure whats going wrong here. See screenshot below.
Do I need to create a new BaseAdaptor for each HorizontalListview or can I use the same one to populate all my listviews with unique data.
Here's some code to help explain what I mean:
1) OnCreate method to get JSON data, parse it, get number of feeds and create each HorizontalListView
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.listviewdemo);
//--------------------JSON PARSE DATA------------------
// Creating JSON Parser instance
JSONParser jParser = new JSONParser();
// getting JSON string from URL
String json = jParser.getJSONFromUrl(sourcesUrl);
//Parse feed titles and article list
getFeeds(json);
//Create Listviews
for(int i = 0; i < feedTitle.size()-1; i++){
//getArticleImage(i);
addHorzListView(i);
articleArrayCount++;//Used to mark feed count for adaptor to know which array position to look at and retrieve data from.
//Each array position i.e. [1] represents a HorizontalListview and its related articles
}
}
2) addHorzListView method, used to create HorizontalListView and apply adaptor
//Method used to dynamically add HorizontalListViews
public void addHorzListView(int count){
LinearLayout mainLayout = (LinearLayout) findViewById(R.id.main_layout);
View view = getLayoutInflater().inflate(R.layout.listview, mainLayout,false);
//Set lists header name
TextView header = (TextView) view.findViewById(R.id.header);
header.setText(feedTitle.get(count));
//Create individual listview
HorizontalListView listview = (HorizontalListView) view.findViewById(R.id.listviewReuse);
listview.setAdapter(mAdapter);
//add listview to array list
listviewList.add(listview);
mainLayout.addView(view, count);
}
3) Baseadaptor itself:
private BaseAdapter mAdapter = new BaseAdapter() {
private OnClickListener mOnButtonClicked = new OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(HorizontalListViewDemo.this);
builder.setMessage("hello from " + v);
builder.setPositiveButton("Cool", null);
builder.show();
}
};
#Override
public int getCount() {
return noOfArticles.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
//Each listview is populated with data here
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewitem, null);
TextView title = (TextView) retval.findViewById(R.id.title);
title.setText(getArticleTitle(position));
new DownloadImageTask((ImageView) retval.findViewById(R.id.ImageView01)) .execute(getArticleImage(position));
Button button = (Button) retval.findViewById(R.id.clickbutton);
button.setOnClickListener(mOnButtonClicked);
return retval;
}
};
The adapter mAdapter is currently displaying the articles from the last HorizontalListView that calls it.
Currently I am using the same BaseAdaptor for each ListView as I figured it populated the listview as soon as its called but i looks as though a BaseAdaptor can only be called once, I really dont know.
I want to dynamically populate feeds though without having to create a new Adaptor manually for each HorizontalListView.
Any help would be much appreciated.
So...you got the same info in 4 listview, right? In that case you only need oneAdapter populating 4 listview.
An adapter just provide the views which are visible in that moment to the listview (if it is implemented in the right way) so you can reuse the adapter if the info contained is the same.

android - SimpleCursorAdapter for a View

is it possible to create a View which is driven by a SimpleCursorAdapter. The content from this view is ever time a entry from DB.
The View (dataView) looks like:
txtData1
txtData2
txtData3
btnPrev btnNext
I read around and tryd to setup this behavior. Hope its make sens:
public class mActivity extends Activity {
public Context me = this;
public SimpleCursorAdapter mAdapter = null;
public Cursor mCursor = null;
private OnClickListener btnStart_onClick = new OnClickListener() {
public void onClick(View v) {
setContentView(R.layout.dataView);
mCursor = mDB.rawQuery("SELECT * FROM Data", null);
startManagingCursor(mCursor);
mAdapter = new SimpleCursorAdapter(
me,
R.layout.dataView,
mCursor,
new String[] {"Data1", "Data2", "Data3"},
new int[] {R.id.txtData1 , R.id.txtData2, R.id.txtData3});
mAdapter.setViewBinder(VIEW_BINDER);
mCursor.moveToFirst();
}
};
static final ViewBinder VIEW_BINDER = new ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex)
{
switch (view.getId())
{
case R.id.txtData1:
TextView txt = (TextView) view;
if (txt != null)
{
int index = cursor.getColumnIndex("Data1");
txt.setText(cursor.getString(index));
}
return true;
case R.id.txtData2:
TextView txt = (TextView) view;
if (txt != null)
{
int index = cursor.getColumnIndex("Data2");
txt.setText(cursor.getString(index));
}
return true;
case R.id.txtData3:
TextView txt = (TextView) view;
if (txt != null)
{
int index = cursor.getColumnIndex("Data3");
txt.setText(cursor.getString(index));
}
return true;
default:
return false;
}
}
};
}
When I run from the btnStart_onClick I dont get Data in my Textboxes :-(
Can somebody help? Can it work like this?
Next question: how can I use the Prev or Next Buttons? Possible this is the only thing I miss to "load" the first data...
EDIT: I extended my example with the global mCursor and the call to mCursor.moveToFirst()
On my app I also tested with the next / prev buttons and the function mCursor.moveToNext() and mCursor.moveToPrevious()
But its not change :-(
As far as I can tell, there are a lot of what I think are conceptual/organizational/syntactical problems with your code. First of all, an adapter is usually exploited by a view such as ListView or Spinner, that gets populated with the data retrieved by the adapter via the cursor (or whatever data structure is backing it). However, I don't see this pattern in your code, and I'm left wondering what use an adapter would have in your case.
Second, you perform a whole SELECT * query in your click listener, i.e. you retrieve all your 1000 records for each click on... well, on what, exactly? You define the click listener, but never set it onto anything - just as you define the adapter, but you don't bind it to anything. The code that sets up the adapter, with the database query and the binder should really be placed outside the listener.
Last, I believe you mocked variable names a bit before posting the code, because in the following snippet:
TextView txt = (TextView) view;
if (txt != null)
{
int index = cursor.getColumnIndex("Data1");
String txt = cursor.getString(index);
txt.setText(txt);
}
I could hardly see how the compiler is intended to distinguish the two txt variables on the last line of the if body.

Categories

Resources