I have a layout for list item, which consists of two LinearLayouts. What I want to achieve is: when item is clicked, second LinearLayout should become visible/gone, depending on the current visibility.
I am experimenting with this code:
getListView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
view.getViewById(R.id.id_of_the_second_linear_layout).setVisibility(View.GONE);
}
});
However when item is clicked, several other linear layouts (in different items) become visible/hidden. Why?
Update:
Adapter:
public class ExpensesCursorAdapter extends SimpleCursorAdapter implements SimpleCursorAdapter.ViewBinder {
public ExpensesCursorAdapter(Context context, Cursor cursor) {
super(context, R.layout.single_expense, cursor,
new String[]{
ExpenseContract._AMOUNT,
CategoryContract._NAME,
ExpenseContract._DATE
},
new int[]{
R.id.expense_amount,
R.id.expense_category,
R.id.expense_date
},
CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
setViewBinder(this);
}
public View getView(int position, View convertView, ViewGroup viewGroup) {
View v = super.getView(position, convertView, viewGroup);
final View expandablePanel = v.findViewById(R.id.expandable_panel);
expandablePanel.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
expandablePanel.setVisibility(view.getVisibility() == View.GONE ? View.VISIBLE : View.GONE);
}
});
return v;
}
#Override
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if (columnIndex == cursor.getColumnIndex(ExpenseContract._AMOUNT)) {
return handleAmountView((TextView) view, cursor);
}
else ...
return false;
}
private boolean handleAmountView(TextView view, Cursor cursor) {
TextView textView = (TextView) view;
Double amount = ExpenseDbHelper.getAmount(cursor);
String formattedAmount = new DecimalFormat("##.00").format(amount);
textView.setText(formattedAmount);
return true;
}
}
Each item has LinearLayout already added in XML, I want to toggle visibility flag, if possible.
You are writing your logic on wrong places. You want to listen clicks of views inside listitem. Write your logic in Adapter's getView method. In your getView logic can be like this
ll1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ll2.setVisibility(View.GONE);
}
});
ll2.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
ll1.setVisibility(View.GONE);
}
});
Something like this.
When you scroll through the list items, some layouts will hide and un-hide, in that case, if you are targeting just one view to be visible at a time (that is just considering one cell at a time), then you could maintain the position of the item clicked, or the id, since you are using a cursorAdapter. Else if you are considering more than one cell then maintain a list where in you store each id of the cell that has been tapped on.
Pass the list or the single position value to the adpater, and in the getview compare the id or position and then perform the visiblity code.
Hope this hint helps.
Related
I have multiple AutoCompleteTextView in layout, so i've implemented AdapterView.OnItemClickListener globally.
Now issue is that,
i can't compare AutoCompleteTextView using switch case inside listener,
Code
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
switch (v.getId()) {
case R.id.ac_education:
s_ac_education = testArray[position];
break;
case R.id.ac_ethincity:
s_ac_ethincity = testArray[position];
break;
case R.id.ac_languages:
s_ac_languages = testArray[position];
break;
case R.id.ac_location:
s_ac_location = testArray[position];
break;
case R.id.ac_religion:
s_ac_religion = testArray[position];
break;
case R.id.ac_travel:
s_ac_travel = testArray[position];
break;
}
}
Note: view.getId() always returning same value,
i've also tried if-else but that doesn't work also.
(I've already wasted couple of hours)
EDIT
private void init(View v) {
ac_languages = v.findViewById(R.id.ac_languages);
ac_religion = v.findViewById(R.id.ac_religion);
ac_location = v.findViewById(R.id.ac_location);
ac_travel = v.findViewById(R.id.ac_travel);
ac_ethincity = v.findViewById(R.id.ac_ethincity);
ac_education = v.findViewById(R.id.ac_education);
ptr.setACTVAdapter(getActivity(), ac_education, ac_ethincity, ac_languages, ac_location, ac_religion, ac_travel);
ac_languages.setHint(R.string.languages);
ac_religion.setOnItemClickListener(this);
ac_religion.setHint(R.string.religion);
ac_location.setOnItemClickListener(this);
ac_location.setHint(R.string.where_do_you_live);
ac_travel.setOnItemClickListener(this);
ac_travel.setHint(R.string.where_can_you_travel);
ac_ethincity.setOnItemClickListener(this);
ac_ethincity.setHint(R.string.ethincity);
ac_education.setOnItemClickListener(this);
ac_education.setHint(R.string.education);
}
setAdapter(is defined in another class)
public void setACTVAdapter(Activity activity, AutoCompleteTextView... actv) {
testArray = activity.getResources().getStringArray(R.array.testArray);
ArrayAdapter<String> adapter = new ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1, testArray);
for (AutoCompleteTextView ac : actv) {
ac.setAdapter(adapter);
adapter.notifyDataSetChanged();
}
}
Thanks
First, create your custom onItemClickListener:
public class MyClickListener implements AdapterView.OnItemClickListener {
AutoCompleteTextView ac;
public MyClickListener(AutoCompleteTextView myAc){
ac = myAc;
}
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
switch(ac.getId()){
case R.id.autocomplete_1:
//your code
break;
case R.id.autocomplete_2:
//your code
break;
}
}
}
Use it for your AutoCompleteTextView:
autoCompleteTextView.setOnItemClickListener(new MyClickListener(autoCompleteTextView));
You should not rely on view when you're working with a list, specially when you're setting a general item click listener.
Instead get an instance to each view by their id on public View getView(int position, View convertView, ViewGroup parent) method of your AutoCompleteTextView adapter and declare a click listener to work with the position you got there, if you want to set multiple click listeners on a row individually.
For example:
public class ExampleAdapter extends BaseAdapter {
...
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView.findViewById(R.id.ac_education);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Your code here
}
});
}
...
}
According to official doc for AdapterView.OnItemClickListener,
onItemClick() method have following parameters,
parent: The AdapterView where the click happened.
view: The view within the AdapterView that was clicked (this will be a
view provided by the adapter)
position: The position of the view in the adapter.
id: The row id of the item that was clicked.
So, you might want to use parent instead of view, to receive id of that parent AutoCompleteTextView.
(Check this answer to get more details.)
It's not the child that you want to track it's clicks, it's convertView.
So, if you really want to handle child clicks outside of your adapter, you can do like this:
public interface OnViewClickListener {
void onViewClick(View view, int position);
}
Then inside of your adapter:
private OnViewClickListener mListener;
public void setOnViewClickListener(final OnViewClickListener listener) {
mListener = listener;
}
And for every child you want:
child.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
if (mListener != null) {
mListener.onViewClick(v, position);
}
}
});
And with this you can get item clicks:
adapter.setOnViewClickListener(new OnViewClickListener() {
#Override
public void onViewClick(final View view, final int position) {
** PUT YOUR SWITCH CASE HERE! **
}
});
First setup data into Pojo class using array list. And return as string for autotextview. Match that string with arraylist's item value using for loop.
autoPartyName.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
for (CustomersModel list : customersList) {
if(list.toString().equals(adapterView.getItemAtPosition(position))){
etContactPhone.setText(list.getContact());
etContactAddress.setText(list.getAddress());
}
}
}
});
I am working on a project which uses a TableLayout, and the user can add a new row to the table layout. Each new row is inflated as a new view and then the view is added to the table layout. One of the controls within the row is an AutoCompleteTextView.
The user can start typing into the AutCompleteTextView and then select one of the items in the suggestion list, when the user selects the item, the selected item is added to the text box as expected, but I want to then set the cursor position as the user can then change the value of the text. For example, the selected item might be sometext() but they can amend the text after selecting it to become sometext(25), so I am trying to set the position of the cursor within the brackets.
This is working fine for one AutoCompleteTextView in the layout but I can't figure out how to do it when its dynamically generated.
I'm finding the AutoCompleteTextView from the inflated layout and creating a set on item click listener, and using the view parameter in the OnItemClick function to ensure I am using the correct view that triggered the event handler, but on the setSelection I am getting an exception java.lang.ClassCastException: android.support.v7.widget.AppCompatTextView cannot be cast to android.widget.AutoCompleteTextView
Below is the code I am using:
private void addRow()
{
TableRow row = (TableRow)LayoutInflater.from(this).inflate(R.layout.create_table_column_row, createTable, false);
txtColumnName = row.findViewById(R.id.txtColumnName);
txtDataType = row.findViewById(R.id.txtDataType);
txtDataType.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
txtDataType.showDropDown();
}
});
txtDataType.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
String selectedItem = parent.getItemAtPosition(position).toString();
//Check if the string has a ( and if so, set the cursor to be just after it so the user can enter the size
int bracketPos = selectedItem.indexOf("(");
if (bracketPos > 0)
{
//Crashes on this line
((AutoCompleteTextView)view).setSelection(bracketPos+1);
}
}
});
List<String> datatypes = Arrays.asList(getResources().getStringArray(R.array.table_datatypes));
datatypeAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, datatypes);
txtDataType.setAdapter(datatypeAdapter);
rowViews.add(row);
createTable.addView(row);
}
I tried casting the view to AppCompatTextView but then this doesn't have the setSelection() method.
The view in onItemClick() is the AppCompatTextView that is clicked in the drop down box for the AutoCompleteTextView. That is why you can't cast it.
Since you have multiple AutoCompleteTextViews, use a focus change listener to capture which AutoCompleteTextView is being addressed by the user. You can then use that value to set the position of the cursor.
private AutoCompleteTextView textView;
private AutoCompleteTextView mAuto;
textView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
mAuto = (AutoCompleteTextView) v;
}
});
textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("MainActivity", "<<<<onItemClicked");
int bracketPos = textView.getText().toString().indexOf("(");
if (bracketPos > 0) {
mAuto.setSelection(bracketPos + 1);
}
}
});
I believe that the AutoCompleteTextView is already populated when this method is called, so you could just search for ( within that field.
Here is a slightly different way. After
txtDataType = row.findViewById(R.id.txtDataType);
add
txtDataType.setOnClickListener(new View.OnClickListener() {
private AutoCompleteTextView mAutoView;
#Override
public void onClick(View v) {
mAutoView = (AutoCompleteTextView) v;
mAutoView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.d("MainActivity", "<<<<onItemClicked");
int bracketPos = mAutoView.getText().toString().indexOf("(");
if (bracketPos > 0) {
mAutoView.setSelection(bracketPos + 1);
}
}
});
}
});
You can delete your other listeners.
I have button on items in my list adapter. The problem occurs when I click the button. The action is performed on the right item, but it disables wrong button.
My code:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater =
(LayoutInflater)context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.item_friend, parent, false);
user = userList.get(position);
ImageView imageView = (ImageView)view.findViewById(R.id.user_image);
Picasso.with(JSONUserAdapter.this.getContext()).load("https://s3.amazonaws.com/profiles-pictures/"+ user.getPath()).into(imageView);
sendRequest = (ImageButton)view.findViewById(R.id.sendRequest);
sendRequest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendFriendRequest();
disabledAdd();
}
});
return view;
}
Do not try to catch click events for the buttons inside the rows of ListView. Each row of ListView is already clickable. Set the onItemClickListener for the ListView:
listview.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> adapter, View v, int position, long l) {
//DO SOMETHING HERE
//Use "position" to get the index of item clicked
}
});
As i can see that we had defined the "User" object as a globel variable and it will store the last postions item data.
So when you will click on any button the last items data will be reflected.
{UserType}Object user = userList.get(position);
You can set Tag on View
Use like this:
sendRequest.setTag(user);
And When user clicks item let's get data from tag like this
sendRequest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Here you have user that was clicked.
User user = v.getTag();
sendFriendRequest();
disabledAdd();
}
});
I was wondering if someone could help me with something as I can't seem to find any documented way to do it, how do you get the view of a column in a list view?
So what I have is a list view, with a custom adapter which has three controls, two textviews and a imageview, what I want to happen is when you press the last column(the image) I want to be able to delete that row, I could do it using the entire row, but I want the user to have to click the imageview column in order to trigger delete.
How do I do this? what do I have to reference to within my OnClickListener in order to check the selected the imageview column?
Thank you for reading
lstNotes.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
}
});
position just references the position of the list row and doesn't allow you to specify a column index or something similar
You can't detect clicks using lstNotes.setOnItemClickListener - that's purely for item clicks. Instead inside your list view's adapter you should set click listeners for each view item.
You could then use an interface to let your activity know. Something like the following would work:
public interface OnViewClickListener{
void onTextView1Click();
void onTextView2Click();
void onImageViewClick();
}
OnViewClickListener listener;
public CustomAdapter(Context context, int layout, ArrayList<Object> list, OnViewClickListener listener) {
this.listener = listener;
super(context, layout, list);
}
...
public View getView(int position, View convertView, ViewGroup viewGroup) {
...
textView1.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
listener.onTextView1Click();
}});
textView2.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
listener.onTextView2Click();
}});
imageView.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View arg0) {
listener.onImageViewClick();
}});
}
I have implemented an ArrayAdapter for customizing a GridView. The layout of each item is defined in xml code that produce something like this:
In my Activity I have implemented the following code:
GridView gridview = (GridView) findViewById(R.id.gridview);
adapter = new myArrayAdapter(this, articlesList);
gridview.setAdapter(new myArrayAdapter(this, articlesList));
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
// here I want to change the text of the `TextView` in the right bottom corner to "CLICKED"
}
});
As explained in the commented section of the code, I simple want to update the TextView in the right bottom corner, writing in it the text "CLICKED".
The View parameter to AdapterView.OnItemClickListener onItemClick() is the view that was clicked. In your case it will be the item root RelativeLayout. Call findViewById() on it or use the ViewHolder pattern to obtain a reference to the TextView you want to update and just update it.
Also note that when the views are recycled i.e. your adapter's getView() is called with a non-null convertView, you need to reset the TextView to its default state.
You may not need to set a TextView to "Clicked", if all you want to do is give the user the feedback that they have checked an item. An alternative might be to do the following. Note, this method will also help you set a textview to "clicked" if you still need to.
To check an item I would extend your RelativeLayout as follows:
public class CheckableRelativeLayout extends RelativeLayout implements Checkable {
private boolean mChecked;
private static final int[] CHECKED_STATE_SET = {
android.R.attr.state_checked
};
public CheckableRelativeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
if (isChecked()) {
mergeDrawableStates(drawableState, CHECKED_STATE_SET);
}
return drawableState;
}
public void toggle() {
setChecked(!mChecked);
}
public boolean isChecked() {
return mChecked;
}
public void setChecked(boolean checked) {
if (mChecked != checked) {
mChecked = checked;
refreshDrawableState();
}
}
}
Then you can call parent.setItemChecked(position,true); in onItemClick which will actually set the item as checked within the AdapterView.
Doing this will then allow you to set a background selector on the extended RelativeLayout and the items will perform selected, pressed, checked etc actions. However, you don't need to use a background selector.
There is more, you can alway see whether the view is checked with gridview.getCheckedItemPosition() which you may find useful if you want to actually set the textview to "Clicked".
gridview.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
parent.setItemChecked(position,true);
yourAdapter.ViewHolder vh = (yourAdapter.ViewHolder) v.getTag();
vh.textView.setText("Clicked");
}
});
In your adapter you can hold a reference to you extended relative layout in your static ViewHolder class and if checked (e.g. holder.extendedrelativeLayout.isChecked()) then make sure you set the textView to "Clicked".
try gridView.invalidateViews(); it automatically calls getView() method of the adapter and updates the view.