I'm quite new with Espresso and I'm trying to test an insertion, deletion and modification in a ListView with custom adapter.
With insertion is simple, I just add a new element and find it inside ListView to check that it has been added.
But the problem comes with deletion, this is what I'm trying to do:
Click in first row, on deletion button.
Confirm delete.
¿How can I assure that the element has been removed?
I mean, I think that I need to know the content of the item before delete it and then check that the row does not exist any more.
How can I do it? Maybe I'm not in the right path to perform this test and I need to do the test in a different way, but I can not find any information.
#Test
public void deleteEdition() {
startActivityWithintent();
// push delete button and delete
onData(anything()).inAdapterView(withId(R.id.listEdition))
.atPosition(1)
.onChildView(withId(R.id.imageDelete))
.perform(click());
// confirm delete
onView(withId(R.id.buttonDelete)).check(matches(isDisplayed()));
onView(withId(R.id.buttonDelete)).perform(click());
// HOW CAN I CHECK THE ELEMENT DOES NOT EXISTS?
// onView(withId(R.id.listEdition))
// .check(matches(not(withText(????))));
}
Thanks in advance.
try to search if there is no view that has a certain text inside its childs, like this:
onView(withId(R.id.listEdition))
.check(matches(not(hasDescendant(withText("should not exist")))));
or if this does not work, search for parts of the string.
onView(withId(R.id.listEdition))
.check(matches(not(hasDescendant(withText(containsString("should not exist"))))));
it works when i try to reproduce it on my computer.
store the text of the row you want to delete in a property, like "matchedText"
this.matchedText = null;
this.rowCounter = -1;
onView(new Matcher<View>() {
#Override
public boolean matches(Object item) {
boolean matches = withId(R.id.imageDelete).matches(item);
if(matches){
rowCounter++;
if(rowCounter == 5){ // 5 is an example of the index you want to access
View view = (View) item;
matchedText = ((TextView)view.getParent()).getText().toString(); // find the matching view by navigating to the right parent and child to get the text you need
return true
}
return false;
}
return false;
}
#Override
public void describeMismatch(Object item, Description mismatchDescription) {
}
#Override
public void _dont_implement_Matcher___instead_extend_BaseMatcher_() {
}
#Override
public void describeTo(Description description) {
}
}).check(matches(isDisplayed()));
after clicking on the delete button you can find out if the row really was deleted with following code:
onView(withId(R.id.listEdition))
.check(matches(not(hasDescendant(withText(this.matchedText)))));
Related
I have a method to add favorites from a search list.
This code allows to click on listview and call listener accordingly weather it is search listview or mytour Listview.
holder.imgaddFavourite.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (tourList.get(position).getFav().equalsIgnoreCase("0")) {
listener.onFavourited(tourList.get(position), true);
holder.imgaddFavourite.setImageResource(R.drawable.faved);
} else {
listener.onFavourited(tourList.get(position), false);
holder.imgFavourite.setImageResource(R.drawable.not_faved);
}
}
});
Below is the code for mytourList which works perfectly:
#Override
public void onFavourited(final Tour tour, final boolean fav) {
new SetFavourite(new SetFavourite.OnFavouriteSet() {
#Override
public void onFavouriteSet(Boolean response) {
int index = listTour.indexOf(tour);
tour.setFav(fav ? "1" : "0");
listTour.set(index, tour);
}
}, fav).execute(tour.getId(), application.getUser().getUid());
}
This code persist favourite state and got no problem.
Below is my code for adding favorites for search items list.
public void onFavourited(final Tour tour, final boolean fav) {
int index = searchOptions.getSearchedTours().indexOf(tour);
tour.setFav(fav ? "1" : "0");
searchOptions.getSearchedTours().get(index).setFav(fav ? "1" : "0");
searchOptions.getSearchedTours().set(index, tour);
}
I am able to click on and add it to favorites, but if I open another tab and reopen that list again, the state is lost. I guess it is cause it's not saving state globally. I've searched for similar answers but none of them helped.
Any help would be appreciated.
You are storing the state of wheather an item is favourite or not in a Boolean variable which is not a persistent storage. It will not be same when you close and reopen the app.
You should store the favourite items on SharedPreferences or in SQL Database which are persistent storage. In that way you can add and remove the data anytime you want, and it will be persisted.
Hope this helps, if you have any doubt, do let me know.
I think you are using ViewPager to handle fragments and always create new fragment when page changed. Therefore state cannot be retained. Try below method in the adapter of ViewPager:
Add variable to keep your desired fragment.
SearchTourFragment searchTourFragment = null;
In getItem(), create your desired fragment only when it is null.
if(searchTourFragment == null){
searchTourFragment = SearchTourFragment.newInstance();
}
return searchTourFragment;
Avoid deleting your desired fragment by override destroyItem().
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
if(position != POSITION_OF_SEARCHTOURFRAGMENT) container.removeView((View)object);
}
This is trying to keep your desired fragment from page change. But if you start another Activity and then back, the fragment may not be retained. Hope that helps!
Good morning,
I have a ListView in a first activity (main_activity), when I click on a selected item, I have a new activity (details_activity) that opens with more informations and details, and the user had to check it, then the (details_activity) is closed and back to the main_activity with the same list.
I want to disable the click on listView's rows that are already checked by the user.
I tried to get the position from main_activity to details_activity to use it in SQL to get the informations, it's working.
Then I sent it back, in the main_activity I used this code:
mPrr = getSharedPreferences("reponse",Context.MODE_PRIVATE);
int IDs = mPrr.getInt("ID",-1);
String rep =mPrr.getString("reponse","");
if(IDs != -1) {
lst.getChildAt(IDs).setFocusable(false);
}
Is there any help please?
Create a ArrayList in adapter than whenever perform click on that row check that row position if position not in list than add position to the array list and perform click else nothing to do.
private ArrayList<String> positionClicked = new ArrayList<>();
public void onBindViewHolder(final MyViewHolder holder, final int position) {
if (!positionClicked.contains(String.valueOf(position))) {
positionClicked.add(String.valueOf(position));
//perform Click
}else {
//
}
}
Write setClickable(false) instead of setFocusable(false);
Create custom ArrayAdapter, find the position of item you want to disable click and #Overide isEnabled method
#Override
public boolean isEnabled(int position) {
if(position == positionYouWannaDisableClick)
return false;
return true;
}
Hello I'm having an issue getting all of the items from my adapter in my fragment. To be more specific I am using a ScaleInAnimatorAdapter along with my Customer Adapter and when I attempt to get my checkbox items from the below posted code, within my Fragment, I only seem to get the visible items on screen.
private View.OnClickListener onAllClick = new View.OnClickListener() {
#Override public void onClick(View v) {
int count = listAdapter.getItemCount();
for (int i = 0; i < count; i++) {
View mChild = listTopics.getChildAt(i);
if( mChild != null ) {
Log.d(TAG,"getItemCount(): " + i );
CheckBox cBox = (CheckBox)mChild.findViewById(R.id.topic_chk);
cBox.setChecked(((CheckBox) v).isChecked());
Log.d(TAG,"isChecked" + cBox.getTag());
cBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(((CheckBox) v).isChecked()) {
checkboxAll.setChecked(false);
}
}
});
}
}
}
};
Essentially I am attempting to create a check all feature from the fragment, so that when this is clicked all of the checkbox items from the adapter are checked. I got that to work with the code I presented however the main issue is that I only get the items visible on the screen, so when I scroll to my other items they are not checked. Thus I am wondering if there is a better way or another way for me to get all of the items
Adapters are meant to bind underlying data stores to views; they generally shouldn't be used to store data themselves (except for having a copy of the data for view binding purposes) nor should they perform actions on data.
Instead, you should be modifying the underlying data, then updating the adapter through whatever mechanism you are already using. (Loaders, custom setters with notifyDataItemChanged, etc.).
Basically you can't. It'll be reusing the UI views.
You need to set a flag in all your data list objects, call notifyDataSetChanged() and onBindViewHolder check that flag and use it to check uncheck
if(listAdapter.getItem(position).getIsChecked())
viewHolder.checkBox.setChecked(true);
else
viewHolder.checkBox.setChecked(false);
Ok. Thank you all for those who have replied you helped me grasp something really basic and important that had alluded me.
I got it to work, so for anyone who might read this post, here is my solution:
Create necessary methods and field to update your data in a model (ie, private is_checked, set_checked(), is_checked(), etc)
In your adapter onBindViewHolder, you will set your holder checkbox to be associated to the data so something like:
holder.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
obj.setSelected(buttonView.isChecked());
}
});
holder.checkBox.setChecked(obj.isSelected());
Then in your fragment or activity I just have a click listener on my main checkbox, and then when checked I loop through my data list, and using the model method I update my data and just simply use listAdapter.notifyDataSetChanged()
You are doing it wrongly.
You should update the adapter instead of updating the check box view.
What you can do , you can create a field in adapter data holder .
And whenever you change the selection,just update the field or multiple field and finally refresh the view.
I'm working on a note taking app. I add a note, and it get's added to the bottom of the list. As the last assertion in the espresso test, I want to make sure that the ListView displays a listItem that has just been added. This would mean grabbing the last item in the listView. I guess you might be able to do it in other ways? (e.g. get the size of adapted data, and go to THAT position? maybe?), but the last position of the list seems easy, but I haven't been able to do it. Any ideas?
I've tried this solution, but Espresso seems to hang. http://www.gilvegliach.it/?id=1
1. Find the number of elements in listView's adapter and save it in some variable. We assume the adapter has been fully loaded till now.:
final int[] numberOfAdapterItems = new int[1];
onView(withId(R.id.some_list_view)).check(matches(new TypeSafeMatcher<View>() {
#Override
public boolean matchesSafely(View view) {
ListView listView = (ListView) view;
//here we assume the adapter has been fully loaded already
numberOfAdapterItems[0] = listView.getAdapter().getCount();
return true;
}
#Override
public void describeTo(Description description) {
}
}));
2. Then, knowing the total number of elements in listView's adapter you can scroll to the last element:
onData(anything()).inAdapterView(withId(R.id.some_list_view)).getPosition(numberOfAdapterItems[0] - 1).perform(scrollTo())
Iv'e got a custom Listview implemented in this particular class, it looks like
[Image/Textview/Checkbox]
When someone clicks on the text is should launch another class, this is working at the moment, however when someone clicks a checkbox I want to update an array that stores the current state of all the checkboxes, I tried doing that via using a onCheckedChanged method within the custom adapter however it doesn't work as the position variable isn't final. So two questions
1 within the adapter is their a way to get the position of the Checkbox so I can change the right position in the array, and
2 If not is their another way to update the array somewhere else without disrupting the current functionality of the onClick.
Here is my onCheckedChanged within my adapter
CheckBox.setOnCheckedChangeListener(new OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton but, boolean b) {
// TODO Auto-generated method stub
if(but.isChecked())
{
deleteList[???] = true;
}else{
deleteList[???] = false;
}
}
});
Have a look a this method. You can set a tag to a view containing any object you wish, which in your case may be the integer value associated with the CheckBox's row.
So when you create your CheckBox:
but.setTag(new Integer(position));
This would change your if statement to:
if (but.isChecked()){
deleteList[((Integer) but.getTag()).intValue()] = true;
} else {
deleteList[((Integer) but.getTag()).intValue()] = false;
}
Let me know if this helps!