RecylerView not scrolling to last text in android test case with espresso - android

RecylerView contains a textView "Some content" in the last.I am not able to scroll my recylerview to last text to be shown.I have tried every hit and trial method found to me,but not able to find any solution.
Code which i have tried:-
1. onView(withId(R.id.recylerview)).perform(scrollToPosition(13));
//my last text view in recyler view is at position 13
2.onView(withText("Some content")).perform(scrollTo(), click());
//my text is "Some content"
My problem is that i cannot search it with id as recycler view contains same text view for all 13 items.As i have set text value programmatically.
So this code cannot apply:-
onView(withId(R.id.txtview)).perform(scrollTo(), click());
EspressoCode
UiObject2 button9 = device.findObject(By.text("S 5 [None]"));
button9.click();
try {
UiObject srText = new UiObject(new UiSelector().resourceId("com.example.project:id/radio"));
sText.click();
}catch(Exception e){
}
onView(withRecyclerView(R.id.recylerview).atPosition(13))
.check(matches((hasDescendant(withText("Some content")))));
UiObject2 button10 = device.findObject(By.text("S 6 [None]"));
button10.click();
try {
UiObject sensorText = new UiObject(new UiSelector().resourceId("com.example.project:id/radio"));
sensorText.click();
}catch(Exception e){
}

You could add this RecyclerViewMatcher file to your tests. Then add this method to your espresso test so you can use it
public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {
return new RecyclerViewMatcher(recyclerViewId);
}
and finally do
onView(withRecyclerView(R.id.recyclerview).atPosition(13))
.check(matches((hasDescendant(withText("Some content")))));
So your espresso file would look something like..
public class YouEspressoTest {
public static RecyclerViewMatcher withRecyclerView(final int recyclerViewId) {
return new RecyclerViewMatcher(recyclerViewId);
}
#Before
public void setUp() {
...
}
#Test
public void testRecyclerView() {
...
onView(withRecyclerView(R.id.recyclerview).atPosition(13))
.check(matches((hasDescendant(withText("Some content")))));
...
}
}

Related

How to change TextView text inside recyclerView items without notifyItemChanged?

I have a recyclerView which shows a title and link preview in every item. I want to search text in title and highlight searched_text if title contains the text.
Problem is: When I search something, everything works as expected but link preview start again and it takes few seconds to load preview again.
Is there any way to prevent reloading/restarting link preview? or
Is there any way to notify just a textView inside item and keep the other thing as it was?
Code for searching:
public boolean performSearch(TextView textViewResult,String searchKey){
this.searchKey = searchKey;
searchedPosition.clear();
for(int i=0;i<links.size();i++){
if(links.get(i).getTitle().toLowerCase().contains(searchKey)) {
searchedPosition.add(i);
}
}
if(searchedPosition.size()==0)
return false;//for downArrow
else {
currentPosition = 0;
for(int i=0;i<searchedPosition.size();i++)
notifyItemChanged(searchedPosition.get(i));
scrollListener.scrollToPosition(searchedPosition.get(currentPosition));
return true;
}
}
onBindViewholder:
#Override
public void onBindViewHolder(#NonNull final FileLayoutHolder2 holder, final int position) {
if(searchKey!=null && links.get(position).getTitle().toLowerCase().contains(searchKey)){
String newString = links.get(position).getTitle().replaceAll(
"(?i)"+ Pattern.quote(searchKey),
"<font color='red'>"+searchKey+"</font>");
holder.textViewHeading.setText(Html.fromHtml(newString));
}
else{
holder.textViewHeading.setText(links.get(position).getTitle());
}
try {//code for showing link preview: asynctask
}
catch(Exception ignored){}
}

Android - automatically scroll within AlertDialog TextView

I am using an AlertDialog to track a logFile which is updating in real time, and need to automatically scroll to the bottom of the view whenever an extra line is added.
I am able to cast the AlertDialog to a TextView (and e.g. using this TextView alter the text size) but any methods involving scrolling don't work.
Code:
LogFileView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
String logFile = "/data/data/com.test/test.log";
String logFileOutput = getFileOutput(logFile);
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setMessage(logFileOutput).show();
TextView textView = dialog.findViewById(android.R.id.message);
textView.setTextSize(8);
textView.scrollTo(0, textView.getLineCount());
} catch (IOException e) {
e.printStackTrace();
}
}
});
textView.setTextSize(8); will alter the text size on display
textView.scrollTo(0, textView.getLineCount()); will do nothing, and the alert dialog, despite having a scrollbar available, will remain focussed on the first line
Update 1:
I see there are a few requests for the dialog creation code/errors in the console output.
Firstly, I am not actually using a separate layout/class to create the dialog. It is applying the default layout associated with (android.R.id.message) to an instance of android.app.AlertDialog and is only constructed within the onClick method for the onClickListener in the code above.
Based on the feedback I've received so far, the code I've most recently attempted to use looks as follows:
LogFileView.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
String logFile = "/data/data/com.test/test.log";
String logFileOutput = getFileOutput(logFile);
final AlertDialog dialog = new AlertDialog.Builder(getActivity()).setMessage(logFileOutput).show();
TextView textView = dialog.findViewById(android.R.id.message);
textView.setTextSize(8);
//textView.scrollTo(0, textView.getLineCount());
textView.setMovementMethod(new ScrollingMovementMethod());
textView.post(new Runnable() {
#Override
public void run() {
textView.scrollTo(0, textView.getLineCount());
}
});
} catch (IOException e) {
e.printStackTrace();
}
}
});
Secondly, there is nothing appearing in the console when the scroll attempt is made - this simply gets ignored at runtime.
The default layout seemed like it would be fine for my purpose, given it appears like a blank TextView with a scrollbar attached, but I think it may be a sensible next step to use a new custom layout and add a ScrollView and see what happens
Use below code. I Tested & verified.
textView.movementMethod = ScrollingMovementMethod() // Add this
textView.text = "your text"
textView.post {
val scrollAmount = textView.layout.getLineTop(textView.lineCount) - textView.height
textView.scrollTo(0, textView.lineCount)
}
Edit:
Equivalent to java:
textView.setMovementMethod(new ScrollingMovementMethod());
textView.setText("your text");
textView.post(new Runnable() {
#Override
public void run() {
int scrollAmount = textView.getLayout().getLineTop(textView.getLineCount()) - textView.getHeight();
textView.scrollTo(0, scrollAmount);
}
});
Try to wrap it with post instead of calling directly to scrollTo,
something like this:
textView.post(new Runnable() {
#Override
public void run() {
textView.scrollTo(0, textView.getLineCount());
}
});

Add & delete item from LinearLayout using ArrayAdapter

I am doing bubble display of selected contacts. Each telephone bubble is a LinearLayout, which contains ImageView and TextView. These bubbles are then displayed in another LinearLayout which is child of HorizontalScrollView.
It child/parent tree looks like this:
- HorizontalScrollView
|- LinearLayout (id="#+id/telField")
|- LinearLayout (id="#+id/telBox") <- is programmatically added to parent
|- TextView (id="#+id/telNumber")
|- ImageView (id="#+id/delNumber")
In my .java class I call this method to display "telBox" LinearLayout in "telField" LinearLayout:
public void createAdapter() {
telList = new ArrayAdapter<>(this, R.layout.text_buble, R.id.telNumber, telNumList);
telField = (LinearLayout) findViewById(R.id.telField);
telField.removeAllViews();
final int adapterCount = telNumList.size();
for (ik = 0; ik < adapterCount; ik++) {
final View item = telList.getView(ik, null, null);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
telField.removeView(item);
telNumList.remove(ik-1);
telList.notifyDataSetChanged();
refresh();
}
});
}
}
Method refresh(); – is custom method which helps to "reload" Activity: it gets App values, refreshes warning ImageViews and cals createAdapter() method.
Big button "SELECT" calls an Intent which returns a selected phone number from a contacts book. I call this code to update my LinearLayout with id "telField":
telNumList.add(cursor.getString(cursor.getColumnIndexOrThrow(ContactsContract.CommonDataKinds.Phone.NUMBER)));
createAdapter();
Problem I face is:
After I click on LinearLayout with id "telNumber" it one by one deletes every bubble (no matter which I clicked) until it reaches first added bubble. It also crashes 50/50 when reaches first added element, I have not figured out a dependency. The error it returns is "out of bounds error", so I think it is connected with ik - 1 line.
My question is: How do I better construct my ArrayAdapter?
In your code you are trying to remove the view by ik which is getting change continuously because of which your coding is removing last view I have modified your code as given below
for (ik = 0; ik < adapterCount; ik++) {
final int position=ik;
final View item = telList.getView(ik, null, null);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
telField.removeView(item);
telNumList.remove(position);
telList.notifyDataSetChanged();
//refresh();
createAdapter();
}
});
}
Here position will help you to remove the particular view which you want to remove. I hope this is what you are asking for.
Inside your for loop, write these line of code:
for (ik = 0; ik < adapterCount; ik++) {
final View item = telList.getView(ik, null, null);
item.setTag(ik);
telField.addView(item);
item.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
int index = Integer.parseInt(v.getTag().toString());
telNumList.remove(index);
refresh();
}
});
}
Hope it will help you out.

Android Add Items One By One Into a LinearLayout

I'm new to Android and I'm trying to find out how to do that:
- I have an activity with a ScrollView and inside it I have a LinearLayout (R.id.my_layout)
- I nedd to add TextView programmatically so I'm doing this:
I load the main XML layout via seContentView, I refer to my LinearLayout inside the ScrollView as "mLayout" and so on.
I load a list of names from a file and with a function called populateList()I do:
private void populateList() {
try {
for (final String team : mTeams) {
rCount++;
addRow(team);
}
}
The addRow() method just create a new LinearLayout (mRow), a TextView, 2 Button, add the TextView and the 2 Buttons to the LinearLayout, and then I use addView to add the new mRow to the mLayout.
Everything is working fine, but the ScrollView is shown only when i finished creating the list (so when the populateList() ends). What I would like to do is to show the rows one by one in sequence to give the activty a better look and a bit of animation.
Is there a way to do this?
I hope i was able to explain it :-)
Thank you
new Thread(new Runnable() { // i am creating the new thread
#Override
public void run() {
// so call populateList() function here
}
}).start();
and for your addRow(String string) method the place you call View.addView(); edit it this way and place the following code in your addRow(String string) method
View.post(new new Runnable() {// view here is mlayout the scrollView.
#Override
public void run() {
mlayout.addView(yourview); // note yourview should be final,
//eclipse might help you with that
}
});
remember to declare mlayout globally, so you do not have to attach final

Select item from AutoCompleteTextView in uiautomator

UPDATE
This project is no longer maintained today, but solutions are most welcomed.
Thanks.
I am creating an automation test project in which I have issue to select the item from the AutoCompleteTextView.
You can see the snap and the views[all expanded] it has. The dropdown of the AutoCompleteTextView does not appear in view tree nor I am able to select using mouse.
I have tried below approaches to select the item form from the AutoCompleteTextView adapter:
UiScrollable locationList = new UiScrollable(new UiSelector().scrollable(true)); locationList.scrollTextIntoView(location);
UiScrollable locationList = new UiScrollable(locationEditText.getSelector()); locationList.scrollTextIntoView(location); Here locationEditText is my AutoCompleteTextView
UiObject selectedLocation = locationList.getChild(new UiSelector().text(location)); selectedLocation.click(); from the locationList it does not select the item with the string passed.
editLocationResId = "android:id/text1"; UiObject selectedLocation = new UiObject(new UiSelector().resourceId(editLocationResId)); selectedLocation.click(); The id from the adpter textview does not work either.
Can anybody help me with selecting the item from the AutoCompleteTextView in uiautomator? Or the more approaches get the desire output.
Get the cordinates of text field :
int x = element.getLocation().getX();
int y = elmement.getLocation().getY();
Add values to get the right cordinates.
x = x+x1
y = y+y1
Use tap function to click on it.
TouchAction action = new TouchAction(driver);
action.tap(x,y).perform();
first open the pick-up list, then try to use UiDevice.pressKey(), to send a DPAD_DOWN OR UP event and press Enter to select the item you want.
If you need to press the first element from the dropdown list, I have found a useful workaround:
public void selectFirstElement() {
TouchAction touchAction = new TouchAction(getAppiumDriver());
int xTapped = autoCompleteTextView.getLocation().getX() + autoCompleteTextView.getSize().getWidth() / 2;
int yTapped = autoCompleteTextView.getLocation().getY() + autoCompleteTextView.getSize().getHeight() ;
touchAction.tap(xTapped, yTapped).perform(); }
Given an AutoCompleteTextView declared as autoCompleteTextView, you can get the current location on the screen and calculate the item which is gonna be located below it. Hope it helps!
Well, i found a turn around(this is for autocompletetextview, for spinner delete setText()):
UiObject edit = mDevice.findObject(new UiSelector().className(EditText.class).instance(0));
edit.click();
edit.setText(name);
Rect rect = edit.getBounds();
mDevice.waitForWindowUpdate(Package.DIGI_PACKAGE, 1000);
mDevice.click(rect.left + 64, rect.bottom + 72);
Get object, click it, insert text that you want,wait for dropdown to appear then click under it with some pixels
I had created and have been using the simplest and the most efficient way. Just locate, type and then select the desired value in autocomplete text view.
Hope it will work for you as well.
driver.findElement(By.id(“Element ID”)).clear();
driver.findElement(By.id(“Element ID”)).sendKeys("Type what you want to select");
driver.pressKeyCode(AndroidKeyCode.KEYCODE_PAGE_DOWN);
driver.pressKeyCode(AndroidKeyCode.ENTER);
You can find the element that you want to select using its text. Make sure that this line of code is executed after the suggestion list has been shown.
//Get a reference to the autocomplete element
UiObject2 autocomplete = device.findObject(By.res("yourpackage","autocomplete_id"));
//Put a text that will trigger the suggestion list
autocomplete.setText("68623 Lampertheim");
//Gain the focus
autocomplete.click();
//Finally, find the element that we want in the suggestion list and click it
device.findObject(By.text("68623 Lampertheim")).click();
Hope it helps.
try the code below it worked for me.
I am using the the AutoCompleteText to auto complete the location where the user is currently in, the locationList is nothing but an array that i wrote in the strings.xml file, so use your own string array here.
locationList = res.getStringArray(R.array.ticketLocation);
ArrayAdapter<String> locationAdapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, locationList);
AutoCompleteTextView textView = (AutoCompleteTextView) findViewById(R.id.txtCountries);
textView.setThreshold(1);
textView.setAdapter(locationAdapter);
textView.setValidator(new Validator());
textView.setOnFocusChangeListener(new FocusListener());
textView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// TODO Auto-generated method stub
TextView ticketLocation = (TextView) view;
getTicketLocation = ticketLocation.getText().toString();
}
});
and below is the code for validating the text input in the location field, the fixText() method prevent the user from typing text that does not exist in your string array, for instance: if the user type "germany" which does not exist in your string array list, it will be replaced by " " which is an empty string inside your edittext input field
class Validator implements AutoCompleteTextView.Validator {
#Override
public boolean isValid(CharSequence text) {
// Log.v("Test", "Checking if valid: " + text);
Arrays.sort(locationList);
if (Arrays.binarySearch(locationList, text.toString()) > 0) {
return true;
}
return false;
}
#Override
public CharSequence fixText(CharSequence invalidText) {
// Log.v("Test", "Returning fixed text");
/*
* I'm just returning an empty string here, so the field will be
* blanked, but you could put any kind of action here, like popping
* up a dialog?
*
* Whatever value you return here must be in the list of valid
* words.
*/
return "";
}
}
class FocusListener implements View.OnFocusChangeListener {
#Override
public void onFocusChange(View v, boolean hasFocus) {
// Log.v("Test", "Focus changed");
if (v.getId() == R.id.txtCountries && !hasFocus) {
// Log.v("Test", "Performing validation");
((AutoCompleteTextView) v).performValidation();
}
}
}

Categories

Resources