I'm writing a game for OUYA and Android and I'm using the trackpad on the OUYA controller. When ever you touch it a mouse pointer comes up and I can't find a way to hide it. I image this would be a problem for games on an Android netbook as well.
Has anyone found a way to interact with the cursor instead of just listening for events?
This won't hide the mouse, but it will at least help prevent touch events from interfering with your joystick processing code -- not a proper solution I know, but still might help people who land on this page:
public boolean onGenericMotionEvent(MotionEvent event) {
if ( (event.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
//handle the event
return true;
}
else {
return false;
}
}
Android currently does not expose any functionality to hide the mouse cursor. Whenever you have an external pointing device (ie. usb/bluetooth mouse, trackpad, etc) a mouse pointer will appear on the screen whenever you interact with the device.
Unfortunately (as of JB 4.2.2) this means it is impossible without a modified ROM.
It is possible to request pointer capture now. You need to explicitly request capture:
fun onClick(view: View) {
view.requestPointerCapture()
}
As documented:
Android delivers pointer events from sources other than the mouse normally, but the mouse pointer is not visible anymore.
You can either handle pointer events by overriding onCapturedPointerEvent:
override fun onCapturedPointerEvent(motionEvent: MotionEvent): Boolean {
// Get the coordinates required by your app
val verticalOffset: Float = motionEvent.y
// Use the coordinates to update your view and return true if the event was
// successfully processed
return true
}
or registering an event handler for OnCapturedPointerListener:
myView.setOnCapturedPointerListener { view, motionEvent ->
// Get the coordinates required by your app
val horizontalOffset: Float = motionEvent.x
// Use the coordinates to update your view and return true if the event was
// successfully processed
true
}
And it's up to you to release the pointer when you're done:
override fun onClick(view: View) {
view.releasePointerCapture()
}
I know that the context of this question overall may not apply (ie: Ouya development), but this was the first search result when I looked into how to do this myself. So I figured that I'd update the answer!
Related
On Android, TalkBack announces "Double tap to activate, double tap and hold to long press".
How can I remove all these default actions and just have it say nothing?
While ignoring whether that is a good idea or not for now.
Update the below code seems to not do anything:
private class NoActionsAccessibilityDelegate : View.AccessibilityDelegate
{
public override void OnInitializeAccessibilityNodeInfo(View host, Android.Views.Accessibility.AccessibilityNodeInfo info)
{
base.OnInitializeAccessibilityNodeInfo(host, info);
foreach (var action in info.ActionList.ToList()) //to list ensures we are not iterating while modifying the readonly ActionList property
{
info.RemoveAction(action);
}
}
}
If your 'view' does not have a click action but for some reason the system detects it as clickable, use the following, (I am using Xamarin for my implementation and the code to disable actions is as follows):
myView.Clickable = false;
myView.LongClickable = false;
Yes that will disable interaction with the view, but in my case the view is not meant to be interactable to begin with. For some reason the system thinks it has an action though it does not.
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).
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 ;
});
I'm working on a Android App that will use a controller (at this time I'm using a Gamesir G3s gamepad on Samsung Galaxy S8 connected trough Bluetooth).
The application is using the standard Android API (level >= 19) for controller management.
I'm facing two major problems at this time:
how to discriminate events coming from DPAD pressure from analog
stick movements;
how to enumerate sources (i.e. axis, buttons, etc) of the controller before movement and pressure events arise.
In particular in this controller the event GenericMotionEvent is triggered for both analog stick motion and DPAD pressure:
#Override
public boolean onGenericMotionEvent(MotionEvent event)
{
int source = event.getSource();
if((source & InputDevice.SOURCE_JOYSTICK)== InputDevice.SOURCE_JOYSTICK && event.getAction() == MotionEvent.ACTION_MOVE)
{
.....
return true;
}
return super.onGenericMotionEvent(event);
}
the source variable always contains 16777232 (i.e. SOURCE_JOYSTICK referring to Android Developer docs).
If I attach the same controller to a standard Windows PC (trough USB) DPAD events are depicted in different way (in a system dialog) from inputs of the analog stick. Of course this may depend on the controller electronics that may behave differently depending on the connected host but I'm wondering why anyway.
To scavenge into gamepad sources the only hint I found (in Android docs) is to use InputDevice.getSources() and so I did:
#Override
public void onInputDeviceAdded(int deviceId)
{
InputDevice device = InputDevice.getDevice(deviceId);
if(null!=device)
{
final int sources = device.getSources();
Log.d("CONTROLLER", "Controller attached" + device.getDescriptor());
}
}
The same check is also done at application startup (assuming the controller is already connected at this time).
In this case sources variable contains 16786707 that correctly is SOURCE_JOYSTICK plus 0x2503 that should be the composed result of the following constants:
SOURCE_GAMEPAD,
SOURCE_CLASS_BUTTON,
SOURCE_KEYBOARD,
SOURCE_CLASS_JOYSTICK,
SOURCE_CLASS_POINTER,
SOURCE_MOUSE.
but adding single values sums a total of 0x2517 that's pretty strange.
My doubts about electronics behaviour are confirmed: attached to Android I found axis mapped in a different way than on Windows (on Windows analog sticks axis are mapped on X,Y,RX,RY while on Android X,Y,Z,RZ respectively).
Someone have hints?
Best regards.
I finally found the solution. Investigating the Android developer official sources I found a sample code that shows how to handle controller events (including DPAD ones) of course it wasn't working in my specific case.
The global misunderstanding arise from the fact that my controller it's not depicting himself as a SOURCE_DPAD and then every source bound to such distinction is failing. In the specific case of the source example provided by Android Developer the problem is this function:
public static boolean isDpadDevice(InputEvent event) {
// Check that input comes from a device with directional pads.
if ((event.getSource() & InputDevice.SOURCE_DPAD)
!= InputDevice.SOURCE_DPAD) {
return true;
} else {
return false;
}
}
That inhibits the caller method:
public int getDirectionPressed(InputEvent event) ...
That should handle the event. In my case the source responsible for DPAD events is SOURCE_JOYSTICK.
So first off, I got this snippet of code working in an empty activity, it just calls for every time when I touch the device.
#Override
public boolean onTouchEvent(MotionEvent ev) {
System.out.println("touch");
return mDetector.onTouchEvent(ev) || super.onTouchEvent(ev);
}
But as soon as I apply this snippet of code to an activity which also has a GridViewPager, the listener doesn't report any touch events.
So my guess is, that all touch Events are getting blocked by the GridViewPager and my listener is not getting anything.
Is there a way how I can fix that?