I have a Listview that will list the alarms which are in the database.I need to add a Toggle Button beside each list item to set the alarm on/off.
How can I add the Toggle Button in the ListView?
R.layout.alarm_list:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ListView android:id="#+id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<TextView android:id="#+id/android:empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/no_reminders"
android:textColor="#FFF"/>
</LinearLayout>
Java Code:
private void fillData() {
Cursor remindersCursor = aDbHelper.fetchAllAlarms();
startManagingCursor(remindersCursor);
// Create an array to specify the fields we want to display in the list
// (only TITLE)
String[] from = new String[] { AlarmDbAdapter.KEY_TITLE };
// and an array of the fields we want to bind those fields to (in this
// case just text1)
int[] to = new int[] { R.id.text1};
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter reminders = new SimpleCursorAdapter(this,
R.layout.alarm_row, remindersCursor, from, to);
setListAdapter(reminders);
}
R.layout.alarm_row:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/text1"
android:padding="10dip" android:layout_width="242dp"
android:layout_height="wrap_content"/>
My project is getting delayed.
Help
There is no small snippet ans. to your problem. I assume you need to have multi-selection. Now here are the things you need.
Since you are using SimpleCursorAdapter, you should replace that with CursorAdapter. To do so you have to extend it as it is a abstract adapter. Once you done that you will be overriding two functions.
newView Where you will create your list item views by inflating R.layout.alarm_row (it should contain your toggle button too). You have make toggle button non-clickable.
bindView where you will set state of toggle button and text for your text view
That said this what you need on the Activity side.
You have make your ListView to multi-selection mode by android:choiceMode in xml or using setChoiceMode.
Now bindView will look like:
ListView lv = ((ListActivity)context).getListView();
// Containing all check states
SparseBooleanArray sba = lv.getCheckedItemPositions();
// I am using check box
cb.setChecked(false);
// Cursor is passed as an argument.
if(sba != null)
if(sba.get(cursor.getPosition()))
cb.setChecked(true);
Ref to docs:
CursorAdapter docs
http://developer.android.com/reference/android/widget/ListView.html
Try creating a custom adapter like:
public class YourAdapter extends BaseAdapter
and a custom layout for the rows with a toggle button (you will have to inflate the layout in the method geView).
Here you can find an example: http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/
Hope this helps..
Related
I want to implement a listView with 2 different lists which is using 2 different Items and want to display them using a same ListView.
Both lists are separated with a sectional divider
The above listView is having a custom selector imageButton in the item
below listView has dateDividers for their items
You should use
https://github.com/commonsguy/cwac-merge
in order to create and merge different adapters with the data you need. You should also insert a header view.
Here follows an example:
#BindView(R.id.lv_validation_errors)
ListView lvValidationErrors;
private List<Notification> notificationList = new ArrayList<>();
public MergeAdapter mergeAdapter = new MergeAdapter();
public ArrayAdapter errorAdapter;
private ArrayList<String> errorList = new ArrayList<>();
public ArrayAdapter alertAdapter;
private ArrayList<String> alertList = new ArrayList<>();
First I set the ListView (using ButterKnife, which does the findViewById stuff) then
errorAdapter = new ArrayAdapter(this, R.layout.adapter_error, R.id.text1, errorList);
mergeAdapter.addView(header("Erros"), false);
mergeAdapter.addAdapter(errorAdapter);
I created the adapters I want to mmerge and added the view for the section header (dont forget to set a value to your list to prevent it from being null) then
alertAdapter = new ArrayAdapter(this, R.layout.adapter_warning, R.id.text1, alertList);
mergeAdapter.addView(header("AdvertĂȘncias"), false);
mergeAdapter.addAdapter(alertAdapter);
same as the previous step and finally:
lvValidationErrors.setAdapter(mergeAdapter);
to set the merged adapter to the ListView.
for that you have to take one list with type Object
List<Object> listItems = new ArrayList<>();
your both different list values add in above listItems .
then after bind your adapter with listItems and when you bind your item in your BindView() write like below.
if(listItems instanceof firstListItemModel)
// bind item from your first list
else if(listItems instanceof secondListItemModel)
// bind item from your second list
As i can understand, you want a vertically half divided screen with containing ListView in each of them.
And you are saying that bottom ListView is completely based on upper ListView.
bottom ListView should load according to Upper ListView selection.
if Yes, then you can use weight to show bothListViews(upper and bottom) on layout like this :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="10dp">
<ListView
android:id="#+id/list_view1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ListView
android:id="#+id/list_view2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
Then you can take set Adapter on list_view2 on list_view1 item click :
ListView upperListView=(ListView) findViewById(R.id.list_view1);
ListView bottomListView=(ListView) findViewById(R.id.list_view2);
upperListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// You can put your logic here to fetch data according to upper ListView item clicked position. I am taking temp. data for now.
ArrayAdapter<String> adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_list_item_1, arrayList//your desired list here);
((ListView) bottomListView.setAdapter(adapter);
}
});
That's it!!
I have an activity that uses setContentView to initiate a listview, and then I have an If-Else condition. In the If part of the statement I use a simpleAdapter to place a new layout in the listview and other data from a cursor. In the Else part, I just want to put a sentence in a label to provide some information. How can I do that? I tried parameters and textview but they didn't work. I tried to put another setcontentView but it can't work either.
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_listview);
doMySearch() is a cursor that extracts data from database based on a keyword input by user.
public void onPostExecute() {
SimpleCursorAdapter adapter;
Int count = doMysearch().getCount;
If (count >= 1){
adapter=new SimpleCursorAdapter(this, R.layout.activity_results,
doMySearch(), new String[] {
DB.COL_NAME,
DB.COL_CITY },
new int[] { R.id.lblName, R.id.lblCity },
0);
setListAdapter(adapter);
}
Else {
}
I just want a sentence that says "No data found" for the Else part. Thanks.
It is not clear for me what you are asking but here we go.
There is empty view setting in ListView for empty lists, you have to add another empty view in your current layout. Then you will set the empty view layout in code like below:
//add to your layout
<LinearLayout
android:id="#+id/empty"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="There is no item" >
</TextView>
</LinearLayout>
//set empty view
ListView listView = (ListView) container.findViewById(R.id.list);
LinearLayout emptyView = (LinearLayout) container.findViewById(R.id.empty);
listView.setEmptyView(emptyView);
As far as I understand the label doesn't show up because of the listview, right?`
EDIT:
Okay I think I get it now.
To keep it simple you could hide your ListView with myList.setVisibility(View.GONE);
Then make a premade Label visible with myLabel.setVisibility(View.VISIBLE) that already holds your error-string.
The harder way you could make a StringArray, like this in (for example) the strings.xml
<string-array name="error">
<item>No results found</item>
</string-array>
Then, in your else-block you can do somethink like that:
ListView lv = (ListView) findViewById(R.id.myList);
String[] content = getResources().getStringArray(R.array.error);
ArrayAdapter<String> typeList = new ArrayAdapter<String>(this, R.layout.simple_list_item_custom, content);
lv.setAdapter(typeList);
I'm writing an IM client and I need to download (from filesystem or network) and show new elements at the top of ListView (it is history of messages -- older messages are at the top, newer -- at the bottom). I implemented my own Adapter for ListView but I can't add new elements at the beginning of the list and redraw it. (notifyDataSetChanged() isn't good for me, because indexes of messages in ListView changes and android can't redraw it normally).
How do other apps do something similar?
I don't create special code for it, I am simply creating new Adapter for my ListView:
messagesListView.setAdapter(new MessagesListAdapter(this));
And redefine getView() and getCount() method in MessagesListAdapter (extends ArrayAdapter now).
My XML for ListView is
<ListView
android:id="#+id/dialog_messages_list"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:layout_marginTop="#dimen/title_height">
</ListView>
And my XML for one element (one message) is
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/dialogMessageText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:background="#drawable/dialog_message_in"
/>
<TextView
android:id="#+id/dialogMessageDatetime"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=""/>
</LinearLayout>
May be you need other code?
EDIT: I tried
messagesListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, arrayList));
(new Thread() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
arrayList.add(0, "qwer");
}
}).start();
But it also not seems good. I tried to call ((ArrayAdapter<String>)messagesListView.getAdapter()).notifyDataSetChanged(); in thread, but it makes exception.
I suggest reversing the order of the List to display the newest result first.
Run this example:
public class Example extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
String[] array = {"oldest", "older", "old", "new", "newer"};
List<String> list = new ArrayList<String>();
Collections.addAll(list, array);
Collections.reverse(list);
// When you want to add new Strings, put them at the beginning of list
list.add(0, "newest");
ListView listView = (ListView) findViewById(R.id.list);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list);
listView.setAdapter(adapter);
}
}
You don't have to override anything in the ArrayAdapter or ListView this way.
you can programmatically add some views in the class associated with your list view. For example:
To add stuff to a layout and make new elements:
TextView tv = new TextView(getApplicationContext());
EditText edit = new EditText(getApplicationContext());
relative.addView(tv);
relative.addView(edit);
This is to manipulate an existing element in the xml layout:
final TextView tv = (TextView) v.findViewById(R.id.listItem);
tv.setText("This an item I am changing");
If you look at some of the related questions, they will give your more information on this. But you can also checkout other people's custom listviews and adapters online. This one is really nice: http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
I am trying to update a single row (two textviews) in a listview by changing the visibility of the second textview from "gone" to "visible".
Here is the XML for the custom layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/userlistlayout"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="#+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" android:textColor="#000000"/>
<TextView
android:id="#+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" android:visibility="gone"/>
I am using an arrayadapter to bind the data from a string[] to the listview. This is working perfectly. Where I am running into problems is pushing the change back to the screen.
Here is the test code I have for my array adapter and the attempt to set the visiblity on a single row's second textview.
searchResults = (ListView) findViewById(R.id.listView1);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,R.layout.userlist, R.id.textView1,names);
searchResults.setAdapter(adapter);
//all the code above this point works perfectly to populate the listview (textview1)
with the names passed in from the names string[]
LinearLayout hold = (LinearLayout) adapter.getView(2, null, null);
TextView hold2 = (TextView) hold.findViewById(R.id.textView2);
hold2.setVisibility(TextView.VISIBLE);
adapter.notifyDataSetChanged();
searchResults.invalidateViews();
This code does not throw any kind of error, however, i am not getting any kind of update on the listview. I am not sure what I am doing wrong or what step I am missing to get the visibility change made to hold2 to be pushed back into the adapter/listview and updated on the screen whereby the second textview on that particular row will be visible.
Once I get this working I want to trigger it onclick.
Any help would be much appreciated.
its pretty late but here is my answer ;
in your code , you are just doing refreshing in the oncreate , just once. but you have the listen for user for all the time , so you can do it
listview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
final int position, long id) {
//here
}
});
now you can use adapter.notifyDataSetChanged(); in the on click .
but i think you should check these posts
this
that
also there is a different solution, we use animations
in the global of adapter
public View selectedView ,previousView ;
public Animation fadeIn , fadeOut;
in the adapter's getview
try {
if (previousView != v){
Animation b = AnimationUtils.loadAnimation(context, R.anim.fadein);
b.setDuration(177);
b.setFillAfter(true);
previousView.startAnimation(b);
previousView.findViewById(R.id.llTicketViewOnClickContainer).setVisibility(View.GONE);
}
} catch (Exception e) {
e.printStackTrace();
}
//..... some other code
//just before closing of get view
previousView =v
}
I'm try to write a little application and the releated unit tests.
I have a ListView binded to a SimpleCursorAdapter reading data from an SQL table.
The Activity#onCreate() method is:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dbHelper = new DatabaseHelper(this);
SQLiteDatabase dbRead = dbHelper.getReadableDatabase();
String[] columns={BaseColumns._ID, ENTRY_VALUE};
cursor = dbRead.query(ENTRIES_TABLENAME, columns, null, null, null, null, null);
String[] from = {"value"};
int[] to = {R.id.value};
adapter = new SimpleCursorAdapter(this, R.layout.list_entry, cursor, from, to);
setListAdapter(adapter);
}
My test inside the unit-test is:
#UiThreadTest
public void testTheElementInsideTheDBisDisplayedInTheList() {
String entryValue = "clipboard entry 1";
DatabaseHelper dbHelper = new DatabaseHelper(cmActivity);
Cursor beforeCursor = selectAllEntries(dbHelper);
// The table, at the begining of the test, is empty, I control that
assertEquals(0, beforeCursor.getCount());
// I insert the new value in the table
insertEntry(dbHelper, entryValue);
// and I control that is really inside the table now
Cursor afterCursor = selectAllEntries(dbHelper);
assertEquals(1, afterCursor.getCount());
// This method calls the method "requery()" on the cursor associate
// to the listView's adapter to update the list view
cmActivity.updateList();
// I control that the listView is updated
assertEquals(1, entryList.getCount());
// Now I try to retrive the only child inside the list view
// to extract the text inside it and to compare this text with
// the value inserted into the DB table.
TextView entryView = (TextView) entryList.getChildAt(0);
String viewText = entryView.getText().toString();
assertEquals(entryValue, viewText);
}
My problem is in the third-last row:
TextView entryView = (TextView) entryList.getChildAt(0);
I sude getChildAt() to get the first TextView child of the ListView. But this method returns null, so the test gets a NullPointerException.
Maybe getChildAt() is not the right method to get the View child from a ListView, so which is the correct one?
I see from the documenation that the method works with GroupView, I didn't use them, do I need to configure a default GroupView and put all the entry inside it? In this way, will getChildAt(0) work? Is this the correct way to setup a ListView?
thank you, bye
Andrea
As asked by Vivek, I post here the main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView android:id="#android:id/empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Empty set"
/>
</LinearLayout>
As you can see is very very basic. Also le list entry is very simple:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/value"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="10dp"
android:textSize="16sp" >
</TextView>
I doubt if the list is populated when you call getChildAt() method. So call getChildCount() method and see if the list is populated. And post back the output here.
Edit:
Now I understand the problem. ListView.getCount() method returns the number of items populated in the list. And ListView.getChildCount() Method or ListView.getChildAt() Method will return 0 here because these methods will return a value only when the view is visible to the user. You can use getChildAt() method only after the textviews are generated. i.e If you use the method in OnItemClick method of the listview, or any listview listener implementation, you will get the desired output. What is the need to get the reference to the textviews here in this method anyways?