I currently have a list and would like to display a large amount of text once a list item has been clicked. The amount of text will vary depending on the list item that's been clicked, ranging anything from a paragraph to a number of paragraphs.
I'm still very much an Android noob, so any tutorials that you know of that relate to your answer would be most appreciated.
Thank you.
The specifics are up to how you want your App to look and feel, but I would say you cant go wrong with a textView with wrap_content for height and width, nested inside a scroll view.
Probably set that inside a custom dialog to pop up when the list is clicked, or make another activity to just show the text.
Depending on what type of information you are displaying, you might want to just have the ListView item redirect to an activity specifically for displaying this information in a nicely organized manner.
If there is going to be a lot of information (and interactivity such as links), then I recommend the new activity.
Pro: Flow! User can navigate back to your list.
Con: It's a new activity
Otherwise you could use a dialog or similar to show the information on the same activity as the list.
Short sample:
// bind your adapter here from database or wherever
String[] Columns = { "_id", "Name", "Description" };
int[] ItemIDs = { R.id.lbl_ID, R.id.lbl_Name, R.id.lbl_Description };
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.item, cursor, Columns, ItemIDs);
ListView list_list= (ListView)findViewById(R.id.list);
list_list.setAdapter(adapter);
list.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView parent, View view, int position, long id)
{
try
{
Intent i = new Intent(getBaseContext(), ViewItemDetail.class);
i.putExtra("ID", ID);
// any other data you need to pass on to your view here. ID should let you select from a database or however you are pulling data
startActivity(i);
}
catch(Exception ex)
{
Log.println(1, "item-click-event", ex.getMessage());
}
}
});
// Then in your activity to get intent data:
Bundle extras = getIntent().getExtras();
if(extras !=null)
{
string ID = extras.getString("ID");
}
Related
I have listview that populated from database.
When I click a row in that listview, it will pass data to another activity with the content of activity depend on the passing data.
This is my code:
private final ArrayList<String> results = new ArrayList<>();
private final AdapterView.OnItemClickListener onListClick = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent i = new Intent(ContentPick.this, Content.class);
String text = results.get(position);
i.putExtra(ID_EXTRA, String.valueOf(text));
startActivity(i);
}
};
The activity contain listview also have edittext that have filtering (when I type some text in the edittext it will filter the listview according to the text). The problem is, if I'm click a row in listview after I filtered it, the activity that showing is same result as if I'm not filter the listview.
Example:
When the edittext is empty, the first row of the listview is Cell structure . When I click the Cell structure it will show information about Cell structure.
I click Back, and I type Blood in EditText, it will filter the listview, and the first row of the listview is Blood Cell. When I click the row Blood Cell, it still show information about Cell Structure.
What I'm trying to do is with this code:
String text = results.get(position);
But I think it's the cause of the problem.
Please help me to solve this problem. Thank you very much.
change position in your code.like below
final int position
Use mAdapter.notifyDataSetChanged() to actual notify your dataset position. It might help you to solve problem.
After some trial and error I finally solve the problem.
I make a method displayResult and I set the adapter like this
dataAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, results);
In the method AdapterView.OnItemClickListener, I change variable text to this
String text = dataAdapter.getItem(position);
And it works!
i Have Two Database
first one Contain All The Items, and the ListView Display it
and the second db contain the the Favorite item , [selected from the first database]
what i want is that when the listview display all the items
check if the item is already exist in Favoritelist then make that textview background RED for this item
i have this code that work fine
public static void ChangeMyFavoritesBG(){
for (int i = 0; i < Items.size(); i++) {
if(db.verification(Items.get(i).toString())){
try {
TextView favtextview = (TextView) listview.getChildAt(i-listview.getFirstVisiblePosition()).findViewById(R.id.item_name);
favtextview.setBackgroundResource(R.drawable.redcolor);
}catch (NullPointerException e) {
}}}}
db.verification check if item exist in favorites database
if true . then it should change the background of this item to red
this code work fine but only if i put it in button click
i need to make the code work automatically
but if i made it start automatically when the activity is loaded i get NullPointer Error
i guess because the function ChangeMyFavoritesBG(); work before the listview display items
any idea guys? and sorry for my bad english
Do this control inside the getView(int position, View convertView, ViewGroup parent) method of the Adapter used by the listView.
If your favorite is not currently visible in the ListView then getChildAt() will return null.
You are looping over all items in the list view and my guess is that it holds more items than can fit on the screen. When your favorite item is one of them then this fragment of your code
listview.getChildAt(i-listview.getFirstVisiblePosition())
will return null. And that will cause the NullPointerException when you call findViewById(R.id.item_name) on it.
Just add a check for null on the result of getChildAt(). If it is null then do nothing, if it is non-null then call the second part. This will protect against the exception when your favorite item is not on the screen, and will allow it to be colored red when your favorite is visible on the screen.
update
My apologies, I read to quickly and misunderstood your problem to be about the NullPointerException but you say that your code works fine when you call it from a button click handler but not when you call it automatically at start-up.
You are right, the ListView does not yet have any items loaded when you are still in onCreate(). You can add a delay before running you code. The following works for me:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
// initialize the ListView with data for the list items. (I'm using a string array in this
// example. You are loading it from a database table, but that is the same in principle.)
ListAdapter adapter = new ArrayAdapter<String>(this, R.layout.item_list, R.id.item_name, Items);
ListView listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(adapter);
// ask the system to wait before setting the background color of the favorite item so that
// the ListView has time to load the items.
final int DELAY_IN_MILLISECONDS = 100;
listview.postDelayed(new Runnable() {
#Override
public void run() {
ChangeMyFavoritesBG();
}
}, DELAY_IN_MILLISECONDS);
}
As you can see in the above example, after initializing the ListView, you ask the system to wait 100 milliseconds before calling ChangeMyFavoritesBG(). Hopefully that is enough time to load the items from the database into the ListView. If it is not enough time then you can, of course, use a longer delay.
The alternative
The above should work, but to be honest I would not write it this way. The above code is very brittle because it depends on the timing of how long it takes to load the items. I recommend that you put your background coloring into a customized adapter.
Because you want the items displayed in a customized way -- you want them to have a red background when it is the favorite one -- you should use a customized adapter. Override the bindView() function to make the background red when it is the favorite one or give it a normal background when it is not the favorite.
I don't know how you currently get the items from the database into your ListView, but inheriting from SimpleCursorAdaptor would work pretty well.
public class FavoritesItemAdapter extends SimpleCursorAdapter {
public FavoritesItemAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) {
super(context, layout, c, from, to, flags);
}
#Override
public void bindView(View view, Context context, Cursor cursor) {
super.bindView(view, context, cursor);
// read the name from the database
int nameColumnIndex = cursor.getColumnIndexOrThrow("name");
String name = cursor.getString(nameColumnIndex);
// write the name to the TextView
TextView nameText = (TextView) view.findViewById(R.id.item_name);
nameText.setText(name);
// set the background to normal or to red, depending on if it is the favorite one or not
boolean isFavorite = db_verification(name);
if (isFavorite) {
nameText.setBackgroundResource(R.drawable.redcolor);
} else {
nameText.setBackgroundResource(android.R.color.transparent);
}
}
public boolean db_verification(String name) {
// this is a stub. You must use your own code here
return name.equals("the favorite one");
}
}
You can then throw away ChangeMyFavoritesBG() and initialize your ListView with the adapter in onCreate() like this.
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my);
Cursor cursor = readItemsFromDatabase();
String[] from = new String[] { "name_column" }; // mapping from database column name ...
int[] to = new int[] { R.id.item_name }; // ... to View ID in the item's layout.
FavoritesItemAdapter adapter = new FavoritesItemAdapter(this, R.layout.item_list, cursor, from, to, 0);
ListView listview = (ListView) findViewById(R.id.listview);
listview.setAdapter(adapter);
}
Good luck!
I am creating an app where you can insert tasks to do and amend them. I currently can view the tasks in a list which I have created, however when I click on the list only the title is shown, although the other entries aren't shown.
Within the entry screen I have code which populates the Entry screen with previous information:
mSaveButton = (ImageButton) findViewById(R.id.diaryform_ib_save);
Log.i(TAG,"Field Title: "+ mTitle);
Intent showTitle = getIntent();
String fieldTitle = showTitle.getStringExtra(Constants.DIARY_TITLE);
Log.i(TAG,"Field Title 2: "+ fieldTitle);
mTitle.setText(fieldTitle);
Intent showEntry = getIntent();
String fieldEntry = showEntry.getStringExtra(Constants.DIARY_ENTRY);
mEntry.setText(fieldTitle);
Log.i(TAG,"Field Entry: "+ mEntry);
Log.i(TAG,"Field Entry 2: "+ fieldEntry);
I have Log messages in there so I can see what information is being given. For fieldTitle the title is passed and for fieldEntry null is passed. When I make both fieldTitle both fields are filled with the title.
Within my ListActivity class I have the following code snippet:
diaryDAO = new DAO(this); //Creates an instance of the DAO
Cursor diaryCursor = diaryDAO.queryDiary(Diary.DiaryItem.LIST_PROJECTION, null, null);
Log.i(TAG, "I get to here!");
String[] diaryDataColumns = { Diary.DiaryItem.COLUMN_NAME_DIARY_TITLE,Diary.DiaryItem.COLUMN_NAME_DIARY_ENTRY };
Log.i(TAG, "Also here");
int[] viewIDs ={ R.id.textView1 };
Log.i(TAG, "Diary Data Col" +diaryDataColumns);
Log.i(TAG, "I'm here");
//Creates backing adapter for the ListView
#SuppressWarnings("deprecation") s
SimpleCursorAdapter diaryAdapter= new SimpleCursorAdapter(
this,
R.layout.activity_diary_list,
diaryCursor,
diaryDataColumns,
viewIDs
);
Log.i(TAG, "Now im here");
this.setListAdapter(diaryAdapter);
Where I create the diaryDataColumns string I tried added the Diary.DiaryItem.COLUMN_NAME_DIARY_ENTRY and it doesn't show within the entry screen BUT when I change the Diary.DiaryItem.COLUMN_NAME_DIARY_TITLE to ENTRY the list view and the entry shows the entry given.
Any ideas? Slightly confused as to what I am doing wrong.
Thanks
edit:
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
Intent openItem = new Intent(this, DiaryEntryActivity.class);
Cursor listCursor = (Cursor)l.getAdapter().getItem(position);
openItem.putExtra(Constants.DIARY_TITLE, listCursor.getString(1));
startActivity(openItem); //Starts the intent actions
}
It seems to me you give two columns, but only one text view. The first given columns data will be populated in the text view, but I think, there is no data in the first column, but your second column contains data, and when you switch them, that data will be populated in the text view. Try it out with two textViews.
But I think to work with content provider is an effecient way, there is a good tutorial on vogella.com about it.
Since you are using SQLite, I suggest you look at using SQLiteOpenHelper. Typically, you subclass this class from the Android API and then use it to implement a ContentProvider. The ContentProvider subclass in turn delivers Cursors to your app which can be used by a CursorAdapter. I suggest you start with a SimpleCursorAdapter and then customize it from there. You should also learn about CursorLoaders which allow you to load data from a database on a separate thread. For more details look at http://developer.android.com/guide/topics/ui/layout/listview.html.
The subject doesn't seem to have been discussed a lot in details so I am gonna explain my situation as well as possible to make it clear and hopefully get some explanations.
My app allows the user to get information about places : there are different menus with different buttons corresponding to categories of places (food/ fastfood, restaurants, ... OR stores/shops, .... and so on). The user clicks on the button of his choice, it will send a request to my database and display a listview with the results. This way :
It is one example, but there are 16 possibilities like this, and everytime it's opening the same activity (ResultListViewActivity) but displaying different content.
I want the user to be able to make more accurate research, so there is a filter mode as you can see on picture 3. The window appearing allows to choose some more criteria. What I planned so far was to fill some variable everytime the user clicks on something. Like if he chooses to pay with a credit card, VALUECARD = X, if budget = something then VALUEBUDGET = Y and so on and when you click on OK it sends all the value package to a method querying the database and open a new listview with the results. It would definitely works, and I know how to do. But I also think it's not really a good way to query the database every time, why not searching directly in the list view ?
I know how to query the database, as my method is working to display listview (see picture 2), but I have no idea how to query a listview, especially when some columns from the database I would use in my filering are not imported in my cursor and then in my listview. I guess I would first have to import every column I might need for filtering.
Here is the code of my method displaying the listview so you see how my cursor is filled and my adapter is made :
private void displayListView() {
// getExtra
Bundle bundle = getIntent().getExtras();
String title = bundle.getString("title", "Choose here :");
String inInterval = bundle.getString("inInterval");
Log.d(TAG, "inInterval = " + inInterval);
poititle.setText(title);
// put the results of the method in a cursor
Cursor c = dbHelper.findPoiInTable(inInterval);
String[] columns = new String[] { DatabaseAdapter.COL_NAME,
DatabaseAdapter.COL_STREET, DatabaseAdapter.COL_WEBSITE,
DatabaseAdapter.COL_TELEPHONE, DatabaseAdapter.COL_REMARKS,
DatabaseAdapter.COL_PRICE };
int[] to = new int[] { R.id.name, R.id.street, R.id.website,
R.id.telephone, R.id.remarks, R.id.price };
cursorAdapter = new SimpleCursorAdapter(this, R.layout.poi_info, c,
columns, to, 0);
ListView listView = (ListView) findViewById(R.id.poilistview);
// Assign adapter to ListView
listView.setAdapter(cursorAdapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
// Comportement des éléments de la listview
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent i = new Intent(getApplicationContext(),
POIActivity.class);
String name = ((TextView) view.findViewById(R.id.name))
.getText().toString();
String website = ((TextView) view.findViewById(R.id.website))
.getText().toString();
String telephone = ((TextView) view
.findViewById(R.id.telephone)).getText().toString();
String remarks = ((TextView) view.findViewById(R.id.remarks))
.getText().toString();
String price = ((TextView) view.findViewById(R.id.price))
.getText().toString();
// i.putExtra(ID_EXTRA, name) ;
i.putExtra(ID_NAME, name);
i.putExtra(ID_WEBSITE, website);
i.putExtra(ID_TELEPHONE, telephone);
i.putExtra(ID_REMARKS, remarks);
i.putExtra(ID_PRICE, price);
startActivity(i);
}
}); }
In this particular case, how could I for example filter the "COL_PRICE" which is in my cursor ? To be more precise, in my filter menu, when the user sets the budget and we get a value, how to use this value in relation to the value from COL_PRICE and keep elements under the given value ?
Thanks for any information !
The easiest solution with your current Code would be using adding a FilterQueryProvider to your adapter, but this will eventually start a new query in your database.
If you really don't want to do a new query on your database, you would have to implement your own custom adapter for your ListView. This will be a whole lot more work than the first solution and is probably slower too.
I have a ListView and I can reorder items, but every time I exit from the app and start it again the order goes back to default. I'd appreciate if someone can give me answer and maybe a little snippet of how I can do that.
Example: I have two items and two links. Google and Yahoo. I use drag and drop and ArrayList with that. Everything is fine except I don't know how to save the new order.
I don't know if there is some other way to reorder those items.
I use CWAC-TOUCHLIST to do this.
Here is how far I have got:
private static String[] items={"Google", "Yahoo"};
private static String[] links={"http://google.com", "http://yahoo.com"};
private IconicAdapter adapter=null;
private IconicAdapter1 adapter2=null;
ArrayList<String> array= new ArrayList<String>(Arrays.asList(items));
private ArrayList<String> array2=
new ArrayList<String>(Arrays.asList(links));
/** Called when the activity is first created. **/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TouchListView tlv=(TouchListView)getListView();
adapter=new IconicAdapter();
adapter2=new IconicAdapter1();
setListAdapter(adapter);
setListAdapter(adapter2);
tlv.setOnItemClickListener(itemclick);
tlv.setDropListener(onDrop);
}
private TouchListView.DropListener onDrop =
new TouchListView.DropListener() {
#Override
public void drop(int from, int to) {
String item=(String) adapter.getItem(from);
adapter.remove(item);
adapter.insert(item, to);
String link=(String) adapter2.getItem(from);
adapter2.remove(link);
adapter2.insert(link, to);
}
};
private TouchListView.OnItemClickListener itemclick =
new TouchListView.OnItemClickListener(){
public void onItemClick(AdapterView<?> parent, View view,
int from, long id) {
String item = adapter.getItem(from);
Toast.makeText(getBaseContext(), "you pick: "+item,
Toast.LENGTH_SHORT).show();
String link = adapter2.getItem(from);
Intent showContent = new Intent(getApplicationContext(),
Web.class);
showContent.setData(Uri.parse(link));
startActivity(showContent);
}
};
Is there a smarter way to do it?
You have to save the lists with their order either to a file or a DB.
When the application starts you have to initialize the ListViews from the saved lists.
When you drag & drop an item, you have to save the changes.
The method you need to change :
Your drop method should, in addition to what it already does, store the changes in a file or a DB.
Instead of the arrays that you pass in the IconicAdapter and IconicAdapter2 constructors (array & array2), you should pass the saved arrays.
You can read in many places how to store data to a file or a SQLite DB. For example, you can find a good tutorial for SQLite here - http://www.vogella.com/articles/AndroidSQLite/article.html#android_requisites (only the first four sections are relevant, since you don't have to use a ContentProvider).
If you choose to use a DB, you can create a table that contains the following columns : item, link & order. In the drop method you'll have to update the order column of all the rows whose order is between from and to (or if the lists are not too big, you can simply update all the rows and set the order to be the index in the array that holds the list).
When you load the table from the DB you should order it by the order column.