How to click button inside method Adapter in RecyclerView? - java

I am working on stripe-terminal-android-app, to connect to BBPOS 2X Reader device,
wanted to click-item from list,(recyclerView).
I am trying to do:
when list of devices appears(readers), I am checking if readers.size()==1, then click first-device from list,else show recyclerView();
I have very less experience in Android(coming from JS, PY), :)
After going through debugger to understand flow of program-running, I used F8 key, or stepOver the functions one by one,
and where value is assigned to convert in displayble-format in adapter as here.
public ReaderAdapter(#NotNull DiscoveryViewModel viewModel) {
super();
this.viewModel = viewModel;
if (viewModel.readers.getValue() == null) {
readers = new ArrayList<>();
} else {
readers = viewModel.readers.getValue();
if(readers.size() == 1){
Log.e(TAG, "readers.size() is 1 "+ readers.size());
}
}
}
then in ReaderHolder-file, values are bind() as
void bind(#NotNull Reader reader) {
binding.setItem(reader);
binding.setHandler(clickListener);
binding.executePendingBindings();
}
}
I tried assigining button and manually clicking when only-one device appears, by clicing on reader[0], can't do that by findViewById inside Adapter file, to call onClick() method manually,
I tired another StackOverflow's answer but didn't understood, from here.
Main fragment is discovery-fragment,
how can I click first-device by checking readers.size()==1, then click onClick()?
my final-goal is to automate, whole stripe-terminal-payment process on android.
extra-info:
I am fetching data from python-odoo server, then using url, will open app through browser, (done this part), then device will be selected automatically as everytime-no any devices will be present except one,
so will automatically select that from recyclerView, then proceed.
I have asked for help in detailed way on GitHub-issues, and started learning Android's concepts for this app(by customizing stripe's demo app, which works great, but I wanted to avoid manually clicking/selection of devices).

Related

Clicking anywhere in JavaFX Listview returns index -1 and crashes

Im working on a simple todo list. Everything was working until fine until now. I worked on a couple methods that save data (no UI work at all) and when I came to test it all, I noticed that my list view has a blue outline around it and tapping things breaks the program. There are two scenarios:
1) run program -> tapping anywhere in list view (outside of the todo 1 cell) crashes program
2) run program -> tap todo cell -> todo info screen opens -> close info screen -> tapping anywhere in list view opens that todo info screen.
Heres an image of what that looks like
There error I get is: Exception in thread "JavaFX Application Thread" java.lang.IndexOutOfBoundsException: Index -1 out-of-bounds for length 1
static void selectedIndexListener(ListView<Todo> listView) {
listView.setOnMouseClicked(new EventHandler<MouseEvent>() {
#Override
public void handle(MouseEvent event) {
int selectedTodoIndex = listView.getSelectionModel().getSelectedIndex();
StageController.launchSelectedTodoStage(TodoList.getTodoListInstance().getTodoAtIndex(selectedTodoIndex));
}
});
}
and then
static Todo getTodoAtIndex(int index) {
return todoList.get(index);
}
I have an ObservableList that holds all the todos and so hence the error.
Im pretty comfortable with java but I'm new to javafx. The reason i'm building this program is to practice java, not so much javafx. That being said, i have no idea where to start debugging this.
All I can say is that the last things I did was write functions to save and load data using JSON. The biggest change is the fact that the list view get populated upon running the program where as before i used to run it, then add data. However scenario number 1 (crashing) happens when I comment out the load and save methods (i.e. run the program with no initial data as I used to). At the moment I am more concerned about the first scenario than the second
I barely ever post on here so let me know if there is anything I should include to help you help me.
If nothing is selected, then
listView.getSelectionModel().getSelectedIndex()
will return -1 (see the documentation). So in the case where nothing is selected, you get an ArrayIndexOutOfBoundsException. On the other hand, if you select something, then click in an empty cell, the selection is not changed and so you get the details of the previously-selected item.
It's generally a bad idea to equate mouse clicks with selection. While they're obviously related, as you've discovered they are not the same thing.
If you want to handle mouse-clicks on a cell, instead of registering a mouse event handler with the ListView itself, use a cell factory to define a cell that has the appropriate mouse-handlers registered. So something like:
listView.setCellFactory(lv -> {
ListCell<Todo> cell = new ListCell<Todo>() {
#Override
protected void updateItem(Todo item, boolean empty) {
super.updateItem(item, empty);
setText(item == null ? "" : item.toString());
}
};
cell.setOnMouseClicked(e -> {
if (! cell.isEmpty()) {
StageController.launchSelectedTodoStage(cell.getItem());
}
});
return cell ;
});

RecyclerView doesn't refresh after modifying database's row

I am programming an app for Android. I uploaded it to GitHub: app
I have a ViewPager (MainActivity.java) controlling two Fragments. On the first Fragment (FirstFragment.java) you can add People (People.java) which appears on the RecyclerView (also on FirstFragment.java). When you click one of the list items on the RecyclerView its details (name and id) appear on the second fragment (SecondFragment.java). The SecondFragment.java also contains a button you can delete the selected People with.
To store the People objects I used a List of People and managed it with the methods in PeopleLab.java. The program was working fine: I could add/remove People objects to the list and it appeared on the RecyclerView fine.
After that, I decided to replace the List with a database. It only meant creating the database (the 3 files in database folder) and editing the already existing and two new methods in PeopleLab.java. The other files remained untouched.
The database is working as expected (checked it with sqlite3), I can add/remove People like before and the queries work. My only problem is that the changes don't appear on the RecyclerView. But if I close and reopen the app, the changes appear.
It's like the RecyclerView doesn't care about the database in runtime, only do when the app starts (or closes, not sure).
Do you have any idea what could cause the problem? My only guess is I miss something about how Android apps handle databases.
P.S.: sorry for my English.
You do call notifyDataSetChanged() on the adapter but you don't provide any new data for that adapter.
In your FirstFragment :
private void updateUI() {
PeopleLab peopleLab = PeopleLab.get(getActivity());
List<People> peoples = peopleLab.getPeople();
if(mAdapter == null) {
mAdapter = new PeopleAdapter(peoples);
mRecyclerView.setAdapter(mAdapter);
} else {
// You actually have to change your dataset
mAdapter.changeDataSet(peoples);
}
}
And in your Adapter :
public void changeDataSet(List<People> people) {
this.mPeoples = people;
notifyDataSetChanged();
}
This some brutal way to do it though.
It would be better to notify your adapter on insertion / removal calling notifyItemInserted(int itemPosition) or notifyItemRemoved(int itemPosition). (And refreshing your dataset, by the way)
It will not work automatically.You can either use to notify the adapter the underlying data has been changed so that adapter can fetch and reload the data.It can be done using adapter.notifyDataSetChanged()
Or use can use CursorLoader to achieve the same

Pasting text from clipboard using a button across different apps (Android)

I tried finding something similar on the net, but couldn't. What I want, specifically, is the ability to have a button paste some text that originated in some other app rather than the one I'm making. So, say you copy some text from the "Google Chrome" app and go through the regular long tap and copy. Then, you open this app and press a button and it fetches the text from the clipboard and pastes it in a TextView. I understand that this isn't possible with the clipboard manager since all the examples I've seen show it as an object that stores information from within the app.
No, ClipboardManager is a system service, providing access to a device-wide clipboard.
Part of the reason why many examples might show both copying and pasting to the clipboard is so that the example is self-contained.
So, you get a ClipboardManager from getSystemService(), get the current contents via getPrimaryClip(), and use the ClipData as you see fit.
For example, this sample project contains two apps: drag/ and drop/. Mostly, this is to illustrate cross-app drag-and-drop operations on Android 7.0. But, drop/ supports a "Paste" action bar item (with associated keyboard shortcut), where I grab whatever is on the clipboard and, if it has a Uri, use it:
#Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId()==R.id.paste) {
boolean handled=false;
ClipData clip=
getSystemService(ClipboardManager.class)
.getPrimaryClip();
if (clip!=null) {
ClipData.Item clipItem=clip.getItemAt(0);
if (clipItem!=null) {
imageUri=clipItem.getUri();
if (imageUri!=null) {
showThumbnail();
handled=true;
}
}
}
if (!handled) {
Toast
.makeText(this, "Could not paste an image!", Toast.LENGTH_LONG)
.show();
}
return(handled);
}
return(super.onOptionsItemSelected(item));
}
There is no code in this app to put stuff on the clipboard, though the associated drag/ app has code for that.
I think what you want to achieve is available in this open-source library: https://github.com/heruoxin/Clip-Stack
The idea is that it keeps track of the clipboard entries in its own internal database while running a (in your case a floating button) service and then pasting that.

Implementing google places autocomplete in android

Im creating an android app where im reusing the google places api to get the autocomplete function. I way i have succesfully implemented functionality is by using this code.
int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1;
...
try {
Intent intent =
new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
.build(this);
startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
} catch (GooglePlayServicesRepairableException e) {
// TODO: Handle the error.
} catch (GooglePlayServicesNotAvailableException e) {
// TODO: Handle the error.
}
This code is launched when the user clicks on a menu_button from a popupmenu in the firstscreen (mainscreen)
This code is able to do what i want it to do, but i dont know how to edit the fragment it creates. I want to set a hint thats different from "search" which is by default. The reason i used this code was because its able to create a sort of dialog or dim the background and creating the the autocompletefragment on top of the first screen which is what i want. Is there an another way to implement the autocomplete?
tl:dr
I want to use the google places autocomplete, and i want it to pop up like a dialog (Dim the first screen and the searchbar goes on top of the first screen).
Does anyone have a solution?

Android AccessibilityDelegate force reading of ViewGroup not children

I'm using a viewpager which is made up of some number of relative layout siblings which are quite complex.
If I click on the relative layout, it will highlight the entire page and read the title and a few textviews one after the other as expected.
If I scroll the viewpager I'd like talkback to read the next page in the same way it reads the first if I click. Secondly, if I scroll to the second, third, etc. pages and click on those layouts, talkback will read as expected.
I am trying to achieve the click behavior after the scroll event has completed.
Here is what I have for the accessibilityDelegate.
viewPager.setAccessibilityDelegate(new AccessibilityDelegate () {
#Override
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
View page = viewPager.getCurrentPageView();
performAccessibilityAction(page, AccessibilityNodeInfo.ACTION_CLICK, Bundle.EMPTY);
}
return super.onRequestSendAccessibilityEvent(host, child, event);
}
});
I've verified that 'page' is the RelativeLayout parent that I think it is. I've also confirmed that the onRequestSendAccessibilityEvent is being fired, but it doesn't read the contents of its children. Am I missing something?
Updated
I've also tried using
viewpager.getCurrentPageView().sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
The above worked for another example when I needed to force talkback to reread a single item but does not have any affect if I try it on the page.
Thanks
Some background -- When you tap on the relative layout, TalkBack generates speech based on the layout's contents. On ICS, this is triggered by a HOVER_ENTER event. On Jelly Bean, it's triggered by an ACCESSIBILITY_FOCUS event. These events are sent automatically by the framework and should, generally speaking, never be sent manually from an app. The same goes for FOCUS events, except in the special case of custom views (see Accessibility talk from Google I/O 2013 for more details).
So, back on topic.
You can control the speech for SCROLLED events by populating the outgoing event with the text you want read. The down side of this is that you'll need to manually generate the text you want read, and it's very likely that this text will differ from what TalkBack will read if the user touches the layout.
viewPager.setAccessibilityDelegate(new AccessibilityDelegate () {
#Override
public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
super.onPopulateAccessibilityEvent(host, event);
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_SCROLLED) {
event.setContentDescription(/** your text */);
}
}
});
Another option is to do nothing and let the user explore the view on their own. This is the preferred interaction model for Android accessibility.
Edit: Video URL is broken, Changed.
This issue was reported on google check
where ViewPager does not set AccessibilityEvent parameters properly
when scrolling.
But after releas of Android Support Library, revision 23.2.1 (March 2016) This issue has been resolved.
update Support Library to Android Support Library to 23.2.1
I had the same issue before. And now I add android:focusable="true" to the ViewGroup, the TalkBalk will read the ViewGroup, instead of its children

Categories

Resources