How can I detect when the listview item has been clicked a second time?
I have made it so that when an item in the listview is clicked, the color is set to green. Now what I want is the color to change back on a second click.
Can anyone explain how I can do so?
Heres where I set the color green:
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id){
parent.getChildAt(position).setBackgroundColor(Color.GREEN);
}
});
If you are trying to modify anything from your cell it not gonna work for the second click.
For that, try to make your listener inside your adapter and then change the color of the background (convertView.setBackground(*)). For me it works like below:
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
convertView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (viewHolder.addedButton.getVisibility() == View.INVISIBLE) {
viewHolder.addedButton.setVisibility(View.VISIBLE);
convertView.setBackground(any_color_you_want);
listener.onButtonAdd(v, position);
} else {
viewHolder.addedButton.setVisibility(View.INVISIBLE);
convertView.setBackground(any_color_you_want);
listener.onButtonRemove(v, position);
}
}
});
}
In this example, I was trying to do a checkable list.
Try this way
Boolean flag=false;
listView.setOnItemClickListener(new OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id){
if(flag==false){
parent.getChildAt(position).setBackgroundColor(Color.GREEN);
flag=true;
}
else{
parent.getChildAt(position).setBackgroundColor(Color.RED);
flag=false;
}
}
});
Just add an attribute variable in your Listener. Like this:
listView.setOnItemClickListener(new OnItemClickListener(){
private Set<Integer> hasClickedSet = new HashSet<Integer>();
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id){
if (hasClickedSet.contains(position)){
v.setBackgroundColor(Color.BLACK);
} else {
v.setBackgroundColor(Color.GREEN);
hasClickedSet.add(position);
}
}
and you need not calling parent.getChildAt(position). Just use the 'v' parameter.
========EDIT============
ok, try this:
listView.setOnItemClickListener(new OnItemClickListener(){
private SparseArray<Boolean> hasClicked = new SparseArray<Boolean>();
#Override
public void onItemClick(AdapterView<?> parent, View v, int position, long id){
if (hasClicked.get(position, false)){
v.setBackgroundColor(Color.RED);
hasClicked.put(position, false);
} else {
v.setBackgroundColor(Color.GREEN);
hasClicked.put(position, true);
}
}
You can track n number of click
int count = 0; // define globally
view.clickListener(){
count++;
if (count==1)
{
// first click
}
else{
// not first click
}
}
Try this way,hope this will help you to solve your problem.
Take HashMap which hold all position and Boolean for is click or not :
HashMap<Integer,Boolean> clickMap = new HashMap<Integer, Boolean>();
Check HashMap contain this position mean this position item clicked base on change background as well Boolean value in HashMap :
if(clickMap.containsKey(position) && clickMap.get(position)){
parent.getChildAt(position).setBackgroundColor(Color.orignal);
clickMap.put(position,false);
}else{
clickMap.put(position,true);
parent.getChildAt(position).setBackgroundColor(Color.GREEN);
}
Related
I am designing a game in which the player has to complete the levels in sequence in order to proceed to the next level. Is there a way to implement this?
I have tried this in my custom ListAdapter
#Override
public boolean isEnabled(int position) {
if(position==0){ return true;}
else{return false;}
}
But I'm not able to find a way to work this for more than one level.
You can do it by following code inside setOnItemClicklistener()
ListView listview = (ListView) findViewById(R.id.listview);
listview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if (listview.getChildAt(position).isEnabled()) {
listview.getChildAt(position).setEnabled(false);
}
}
});
I would like to set an action listener for my listview, such that specific details will be displayed depending on the position clicked. However I encountered an error in while using the getPosition() and getName() methods. Please help me remedy the situation, as well as explain how it functions as I'm confused.
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?>adapter, View v, int position, long id) {
String item = yourData.getPosition(position).getName(NAMES);
Intent intentProduct = new Intent(Scrollable.this, ProductDetail.class);
intentProduct.putExtra("Key", item);
startActivity(intentProduct);
}
});
Use this
String item = yourData.getPosition(position).getName();
insted of
String item = yourData.getPosition(position).getName(NAMES);
code
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?>adapter, View v, int position, long id) {
String item = yourData.getPosition(position).getName();
Intent intentProduct = new Intent(Scrollable.this, ProductDetail.class);
intentProduct.putExtra("Key", item);
startActivity(intentProduct);
}
});
String item = yourData.getPosition(position).getName(NAMES); //NAMES not nessasry
listView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?>adapter, View v, int position, long id) {
String item = yourData.getPosition(position).getName();
Intent intentProduct = new Intent(Scrollable.this, ProductDetail.class);
intentProduct.putExtra("Key", item);
startActivity(intentProduct);
}
});
After a thorough search and quite a lot of thinking, I couldn't find a solution to the following problem in AndroidStudio:
I have 2 spinners (input and output). I want to pass the value of the input spinner to a method that is called upon selection of a value of the output spinner (onItemSelected). The regarding code passage looks as follows:
private void setupSpinnerListeners() {
spinnerLengthInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String itemSelectedInSpinnerLengthInput = parent.getItemAtPosition(position).toString();
checkIfConvertingFromMeter(itemSelectedInSpinnerLengthInput);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinnerLengthOutput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String itemSelectedInSpinnerLengthOutput = parent.getItemAtPosition(position).toString();
updateOutputTextfield(itemSelectedInSpinnerLengthInput, itemSelectedInSpinnerLengthOutput);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
I want the String itemSelectedInSpinnerLengthInput (that gets its value from the input spinner) to be available in the onItemSelected method of the output spinner. How to accomplish this?
Any help is greatly appreciated.
EDIT: Create a global variable INSIDE the setupSpinnerListeners Method, that is an array with length 1. The it'll work as I had intended.
I recommend you to use OnItemSelectedListener.
Then create a globalVariable to get the String to your first Spinner as follows :
String FirstValue = "";
Then you'll need to call this :
spinnerLengthInput.setOnItemSelectedListener(this);
spinnerLengthOutput.setOnItemSelectedListener(this);
Of course you'll need to implements OnItemSelectedListener
Then inside you can do the same that you were doing.
#Override
public void onItemSelected(AdapterView<?> spinner, View view, int position,long id)
{
FirstValue = spinner.getItemAtPosition(position).toString();
checkIfConvertingFromMeter(itemSelectedInSpinnerLengthInput);
}
Then in your other Spinner use the FirstValue value.
You should change itemSelectedInSpinnerLengthOutput as a global variable. After that, you can easy access to it in the onItemSelected method of the output spinner
String itemSelectedInSpinnerLengthInput; // global variable
private void setupSpinnerListeners() {
spinnerLengthInput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
itemSelectedInSpinnerLengthInput = parent.getItemAtPosition(position).toString();
checkIfConvertingFromMeter(itemSelectedInSpinnerLengthInput);
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
spinnerLengthOutput.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
String itemSelectedInSpinnerLengthOutput = parent.getItemAtPosition(position).toString();
if(itemSelectedInSpinnerLengthInput != null){
updateOutputTextfield(itemSelectedInSpinnerLengthInput, itemSelectedInSpinnerLengthOutput);
}else{
Toast.makeText(getApplicationContext(), "please select input", Toast.LENGTH_LONG).show();
...
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}
Hope this help
I have created a list view and it contains integer values. I have set them inside a textview and now from another layout I need to get those integer values and pass it to another activity! How can I do that? Please help I'm new to android .
private void viewFunction() {
Button messageButton=(Button)findViewById(R.id.btnCreate);
messageButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
;
Units units=new Units(dbHandler.getUnitsCount(),String.valueOf(myTry.getText()),String.valueOf(bulbSpn.getSelectedItem()),String.valueOf(fanSpn.getSelectedItem()));
//addUnits(0,myTry.getText().toString(),bulbSpn.getSelectedItem().toString(),fanS pn.getSelectedItem().toString());
if(!unitExsits(units)) {
dbHandler.createUnit(units);
Unit.add(units);
unitsAdapter.notifyDataSetChanged();
// populateList();
// startActivity(new Intent(getApplicationContext(),HomePage.class));
Intent intent_valueBulb = new Intent(CreateNewUnit.this,
HomePage.class);
intent_valueBulb.putExtra("key2",noOfBulb);
intent_valueBulb.putExtra("keyFan",noOfFan);
startActivity(intent_valueBulb);
Toast.makeText(getApplicationContext(),String.valueOf(myTry.getText())+"has been added to units",Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getApplicationContext(), String.valueOf(myTry.getText()) + " already exists !!! Please use a different name!", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
view = getLayoutInflater().inflate(R.layout.listview_item,parent ,false);
}
Units currentUnit = Unit.get(position);
TextView name = (TextView)view.findViewById(R.id.lblLUnitName);
name.setText(currentUnit.getName());
TextView bulb=(TextView) view.findViewById(R.id.lblLNoofBulbs);
bulb.setText("Number of Bulbs :"+currentUnit.getBulbNo());
TextView fan=(TextView) view.findViewById(R.id.lblLNoOfFans);
fan.setText("Number of Fans :"+currentUnit.getFanNo());
return view;
}
If you want to store the contents of the list in a variable, you can call getCount to determine the size of the list, and then do a for loop to add each item to an ArrayList.
ArrayList<Integer> numbers = new ArrayList<Integer>();
int size = myList.getAdapter().getCount();
for(int i = 0; i < size; i++)
{
numbers.add((Integer) myList.getAdapter().getItem(i));
}
If you're trying to store the list item selected by the user, you need to implement an onItemClickListener, and then grab the selected item from the adapter using its index in the list:
myList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
//this is what happens when an item in the list is clicked
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
//the location of the selected item is stored in i
//use this location to pull the value and store it in a variable
int selectedNumber = (Integer) adapterView.getAdapter().getItem(i);
//you now have the chosen number stored in a variable
}
});
I'm trying to make two side by side ListViews act like a GridView to an extent. The reason I'm not using GridView is because there's no support for a Staggered Look. Anyways, I have the following code so far:
<- Old,now irrelevant code ->
EDIT:
I did as #Sam suggested and used the following code:
lv1.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (touchSource == null) {
touchSource = v;
}
if (v == touchSource) {
lv2.dispatchTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
clickSource = v;
touchSource = null;
}
}
return false;
}
});
lv1.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (parent == clickSource) {
//my own code here
}
}
});
lv1.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (view == clickSource) {
}
boolean loadMore = /* maybe add a padding */
firstVisibleItem + visibleItemCount + 10 >= totalItemCount;
if (loadMore) {
//add items, load more
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
lv2.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (touchSource == null) {
touchSource = v;
}
if (v == touchSource) {
lv1.dispatchTouchEvent(event);
if (event.getAction() == MotionEvent.ACTION_UP) {
clickSource = v;
touchSource = null;
}
}
return false;
}
});
lv2.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (parent == clickSource) {
}
}
});
lv2.setOnScrollListener(new OnScrollListener() {
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
if (view == clickSource) {
}
boolean loadMore = /* maybe add a padding */
firstVisibleItem + visibleItemCount + 2 >= totalItemCount;
if (loadMore) {
}
}
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
});
I am also using a header on one of the lists to create a Staggered Effect and I need to keep this stagger at all costs. This is mostly working (the above code) but it unsyncs a lot of the time. I have figured out this is only when I have small short swipes. I'm not sure why, and I can't find a good solution. It seems to me that the above logic should work.
Also, just in case it matters, I am using UniversalImageLoader to load photos and a simple EndlessScroll logic to load more photos (directly calling adapter.notifyDataSetChanged()). This stuff doesn't seem too relevant though. Even when photos are loaded, I can still see it unsyncing.
I want to be clear: if I do short swipes (and sometimes just in general repeated scrolling) I can unsync the lists at will.
Any help is appreciated. Thanks.
EDIT 2:
Yet to find a good solution. Here are the solutions that I have found that don't quite work:
The above solution: unsyncs far too often
Pinterest List View: no OnScrollListener/onItemClick differentiation
StaggeredGridView: No onScrollListener
Stag Project: No onItemClick listener
Linear Layout Method: No onItemClick Listener
Any ideas? Thanks.
Okay, so I ended up using the Linear Layout Method(See the Question) and used setTag to get the onItemClickListener working, and a CustomScrollView implementation to get the infinite List working.
Basically, two linearLayouts stacked horizontally, inside a scrollview. It works rather well, and loads much faster.
Also, to load my images SmartImageView if that helped.
If someone wants the code, I might be able to post parts of it.
Instead of listening to onTouch why don't you scroll lists in the onScroll listener of ListViews. That's what I'm using in that library with sort of tracks the scroll of a ListView similarly and it works like a charm. Check out this file. https://github.com/JlUgia/list_moving_container/blob/master/src/com/ugia/listmovingcontainer/fragment/BottomListMovingContainerFragment.java
Pay attention specially to 81 (don't forget to add the global layout updater listener) and 89 (with the onScroll Listener).
That way you can forget about the click hacks as well.
UPDATE
I'd code it the following way.
lv1.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
updateListPosition(lv2, lv1);
}
});
lv1.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateListPosition(lv2, lv1);
}
});
lv2.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
updateListPosition(lv1, lv2);
}
});
lv2.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
updateListPosition(lv1, lv2);
}
});
private void updateListPosition(ListView updatedList, ListView scrolledList){
updatedList.setScrollY(scrolledList.getScrollY());
}
** setScrollY already invalidates your list.
** Note that I didn't test the code. Although it should be simple enough.