Click event from checkbox in custom listview in Android - android

I have a custom layout for my list view rows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/listSelector"
android:orientation="horizontal">
<LinearLayout
android:id="#+id/checkboxSelection1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="3dip">
<CheckBox android:id="#+id/checkbox1" />
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/checkbox1"
android:orientation="vertical">
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
I've also got an adapter to get the appropriate data to display; which it does. From the UI perspective, it looks like I want it to.
However, when I click a checkbox - nothing happens. I want to store a list of the items I've selected in the backend (in the activity class ideally).
In my onCreate in the activity class, I've got this code:
listView.setAdapter(adapter);
listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
// Click event for single list row
listView.setOnItemClickListener(new OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
int i = 1;
}
});
I've got the int 1 = 1; line there just so I could add a breakpoint to see if it gets hit. It doesn't. I'm sure I'm doing something wrong, like it's hooked up to the list view row instead of the checkbox or something - but I'm not sure how I can hook the event up to the checkbox.
If anyone could point me in the right direction I would appreciate it.
Thanks
Edit: JUST TO CLARIFY
I have this in the adapter:
taskChecked.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
public void onCheckedChanged(CompoundButton arg0, boolean arg1)
{
// TODO Auto-generated method stub
int i = 1;
}
});
And that breakpoint does get hit. So I'm just trying to find out how I get have an event get raised in the activity, instead of just the adapter, when a checkbox is selected or unselected.

Don't do it!!! I almost went mad trying to get widgets in a ListView to respond to clicks. Do not put Button, ImageButton, or CheckBox widgets in a ListView. TextViews and ImageViews are the way to go. Trying to react to that click on that CheckBox to find what ListView item it is in and then send something to the Activity could be very harmful to your health. I tried.
TextView + ImageView that can vary between an icon showing a checkmark and one without - simulate a CheckBox;
ImageView by itself can simulate a Button.
The ImageView needs to be set to focus=false.
First, create a new class that has the fields you want to display for each item in the ListView. I made one with the text to display and a boolean that indicates whether it is checked or not. Use this class for your ArrayList and ArrayAdapter.
Then you add the setOnItemClickListener() for the ListView, then use the position to find the item view, and then get the item of your new class and toggle its boolean.
In the MyArrayAdapter.getView method, getItem(position) returns the instance of the new class for that item. Use the boolean to determine what icon to use for the ImageView.
When you need to know what is and isn't "checked" in the ListView, you just go through the ArrayList and check the boolean for each item.

I figured it out.
In the adapter I added this:
With _activity being the activity passed into the constructor from the calling activity. myObj is declared as a final earlier up in the code, based on the position in getView and the data passed in when the adapter was constructed.
taskChecked.setOnCheckedChangeListener(new OnCheckedChangeListener()
{
#Override
public void onCheckedChanged(CompoundButton button, boolean checked)
{
// Cast it so we can access the public functions
MyActivity myActivity = (MyActivity) _activity;
if (checked) // true if the checkbox is checked, false if unchecked
{
myActivity.checkboxSelected(myObj);
}
}
});
And in the activity I added this:
public void checkboxSelected(MyObj myObj)
{
// Do stuff with myObj here
}
Hopefully this helps someone.

Related

How to visually affect all items in an android listview row upon click?

I have a listview adapter which uses a linear layout for its rows , each row simply contains two text boxes.
I need to highlight the whole row when either the code or the book name is touched.
The layout XML for each row of the listadapter ( removed unnecessary properties for brevity)
<LinearLayout
...
android:id="#+id/bookrowbackground">
<TextView
...
android:id="#+id/book_code"
android:onClick="ToggleBookSelection" />
<TextView
...
android:id="#+id/book_name"
android:onClick="ToggleBookSelection"
/>
</LinearLayout>
The ToggleBookSelection handler
public void ToggleBookSelection(View view) {
TextView selectedTextView = (TextView)view;
//Some code lines not related to the question ...
selectedTextView.setBackgroundColor(getResources().getColor(R.color.colorPrimaryDark));
selectedTextView.setTextColor(Color.WHITE);
}
But this only highlights ONE box at a time, like below
I have googled and using the same tag for each row textbox seems to be one solution but I'm not sure if that is the cleanest way to set the background colour for both the textviews in the row.
How should I go about implementing the whole row selection?
Thanks
May these will work for you
dataListView.setAdapter(aa);
//attach a listener to the list view
dataListView.setOnItemClickListener (listener);
dataListView.setItemsCanFocus(true);
Use OnItem Click Listener and do your stuff in it.
OnItemClickListener listener = new OnItemClickListener (){
#Override
onItemClick(AdapterView<?> parent, View view, int position, long id){
((TextView)view.findViewById(R.id.yourTextViewId)).getText();
//or do your stuff }
}
Use/add this in to your ListView :
android:listSelector="#color/colorPrimary"
Example :
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/list"
android:listSelector="#color/colorPrimary">
</ListView>

Deleting custom objects from a listview within a fragment using onClick XML

I'm still learning a lot about programming.
I've currently set up my own listview item layout to display a custom object.
Within this custom listview layout, there's an image button that has an onClick method associated to it.
I've realised that the onClick is passed back to the parent activity, but i'm not sure how to remove my listview item as my arraylist of the custom object is within the fragment.
I'm probably not explaining myself very well, so here is code snippets to go with it.
Image button XML within custom listview layout:
<ImageButton
android:layout_width="0dp"
android:layout_height="match_parent"
android:src="#drawable/deleteitem"
android:scaleType="fitCenter"
android:background="#null"
android:adjustViewBounds="true"
android:layout_weight="0.15"
android:layout_marginEnd="5dp"
android:id="#+id/deleteItemButton"
android:onClick="delItem"/>
OnClick method in parent Activity:
public void delItem(View v) {
_ItemObject itemToRemove = (_ItemObject) v.getTag();
ItemList_Fragment itemlistclass = new ItemList_Fragment();
itemlistclass.removeItem(itemToRemove);
}
removeItem method found in fragment:
public void removeItem(_ItemObject itemToRemove) {
adapter.remove(itemToRemove);
adapter.notifyDataSetChanged();
}
This error received says that "adapter" in my fragment is null. This is earlier initialised when the fragment is created. Any help would be greatly appreciated.
You don't need to make it so complex. Remove android:onClick="delItem" from the view and attach listener in your getView() .
Initialize deleteItemButton and setOnClickListener() -
deleteItemButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
_ItemObject itemToRemove = (_ItemObject) v.getTag();
remove(itemToRemove);
notifyDataSetChanged();
}
});

How can I access my main activity from an adapter and how to get the state of elements in views?

I have an Android activity which is a map and an ExpandableListView. This ExpandableListView is populated using a collection built in run time and an adapter.
This list view contains a label, an image and a checkbox. They should work as filters: if the checkbox is checked, the items related to that label should appear in my map. If the checkbox is not checked. These items should disappear.
This is the code for my activity and adapter (most important parts)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/list_item_child"
android:gravity="center_vertical"
android:background="#android:color/white">
<CheckBox
android:id="#+id/filtro_checkbox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:checked="true"/>
<ImageView
android:id="#+id/filtro_imgView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/list_item_text_child"
android:textSize="20sp"
android:padding="10dp"
android:layout_marginLeft="5dp"/>
</LinearLayout>
Code:
#Override
//in this method you must set the text to see the children on the list
public View getChildView(int i, int i1, boolean b, View view, final ViewGroup viewGroup) {
if (view == null) {
view = inflater.inflate(R.layout.list_item_child, viewGroup,false);
}
TextView textView = (TextView) view.findViewById(R.id.list_item_text_child);
//"i" is the position of the parent/group in the list and
//"i1" is the position of the child
Filtro child = mParent.get(i).getArrayChildren().get(i1);
textView.setText(child.getTitle());
ImageView imageView = (ImageView) view.findViewById(R.id.filtro_imgView);
//"i" is the position of the parent/group in the list
Drawable drawable = view.getResources().getDrawable(child.getImage());
imageView.setImageDrawable(drawable);
CheckBox chkbox = (CheckBox) view.findViewById(R.id.filtro_checkbox);
chkbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
View view2 = inflater.inflate(R.layout.list_item_child, viewGroup,false);
// TODO Auto-generated method stub
if (buttonView.isChecked()) {
Toast.makeText(view2.getContext(), "Checked",
Toast.LENGTH_SHORT).show();
}
else
{
Toast.makeText(view2.getContext(), "UnChecked",
Toast.LENGTH_SHORT).show();
}
}
});
//return the entire view
return view;
}
I am new to Android development, but as far as I understood, this method code will "instantiate" the activity layout for each item. This is working and the items are being populated in the emulator.
Then, I added the onCheckedChanged listener. It works, the toast is shown.
But now I would like to make the pins show/hide depending on the checkbox selection.
To do that, I would like to
Get the checkboxes which are checked
Erase all the pin from the maps (To do that, I need to reach the main_activity somehow)
Show the pins related to the checked checkboxes
I do not know how to perform these steps, I thought about using a singleton or an observer design pattern to reach the MainActivity in order to be able to call the methods to reload the pins.
Would that be an elegant approach?
How could I check the state (checked/not checked) for all of my checkboxes?
Thanks
You can use preferences to store the value of checked or unchecked items. Also you can register a listener when the preferences are changed. Otherwise, you can read the preferences in the activity where you want to display the maps.
Read the preferences, and update your checkboxes. When the user changes the checkbox, update the preferences
In your map display activity, read the preferences, and PIN accordingly. Also when the user pins/unpins, you can update the preferences.
https://developer.android.com/reference/android/preference/Preference.html

ActionbarSherlock list navigation - scroll to top/focus first row

I need some help with sherlock list navigation.
Goal: when you open navigation, I want scroll to top/focus to first row, so 1st item is always visible.
Problem: now when list has more items as screen can display(usually in landscape mode), when i select ie 4th item and then open list, first item is not visible, it's focused to last selected item.
It works for me with code bellow in custom spinner, but when I tried override same methods in IcsSpinner it haven't worked.
Code:
/**
* Cusrom spinner class - when open always focus on first item
*
*/
class CustomSpinnerSelection extends Spinner {
private boolean mToggleFlag = true;
//some constructors here
#Override
public int getSelectedItemPosition() {
// this toggle is required because this method will get called in other
// places too, the most important being called for the
// OnItemSelectedListener
if (!mToggleFlag) {
return 0; // get us to the first element
}
return super.getSelectedItemPosition();
}
#Override
public boolean performClick() {
// this method shows the list of elements from which to select one.
// we have to make the getSelectedItemPosition to return 0 so you can
// fool the Spinner and let it think that the selected item is the first
// element
mToggleFlag = false;
boolean result = super.performClick();
mToggleFlag = true;
return result;
}
}
There is one possible way of doing so, now that you've done it with spinner.
You can use custom view for the action bar, that contains a spinner for list navigation, and use your custom spinner class instead of the default spinner.
The custom view xml might look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Spinner
android:id="#+id/actionBarSpinner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:entries="#array/default_list" />
</LinearLayout>
You will need to enable and set custom view from code.
View view = this.getLayoutInflater ().inflate (R.layout.actionbar_customview, null);
actionBar.setCustomView (view);
actionBar.setDisplayShowCustomEnabled (true);
Also, you can save the spinner to set any listeners or do any other operations.
Spinner actionBarSpinner = ((Spinner) view.findViewById (R.id.actionBarSpinner));
Just instead of Spinner, it would be your CustomSpinner class.
I'm not sure if this is your case, but one thing I found out about spinners: sometimes if you populate them on onCreate(), a little bit of low-level trickiness happens. Remember that Android is event-based, so putting the data in onCreate actually might not fill the spinner. The spinner sometimes gets filled after the screen is drawn!
So, if this is happening, try doing in a call after onCreate like onWindowFocused or whatever it's called
setSelection might be the only way to load the spinner with the first item focused. Try this:
Spinner s = (Spinner) findViewById(R.id.spinner_id);
int i = adapter.getPosition("blue");
s.setSelection(i);

Updating a single row in a listview to show a hidden textview

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
}

Categories

Resources