Codename One Right side menu shadow is flipped - android

I've noticed using the latest build of Codename one.
When my sidemenu (hamburger menu) is on the right hand side, the shadow image is flipped.
Seems to be the case on the simulator and Android and iOS.
I seem to remember I had to put in a work around to get this working recently, but that work-around doesn't seem to work anymore.
I tried to replace the imahe using the theme constants, and also to turn it off by setting sideMenuShadowBool to false. but neither of these seem to do anything anymore.
Screenshot:
Code snipit (called on beforeShow for each form):
private void setupTitleBar(Form f, FormController fc) {
if (handler == null) {
handler = new MenuHandler();
sm.addCommandListener(handler);
}
for (int c = 0; c < f.getCommandCount(); c++) {
f.removeCommand(f.getCommand(c));
}
Toolbar tb = new Toolbar();
f.setToolbar(tb);
fc.setupTitlebar(tb);
String formName = f.getName();
if (!"Main".equals(formName)
&& !"Signup".equals(formName)
&& !"MyCards".equals(formName)
&& !("Orders".equals(formName) && !ModuleManager.isModuleEnabled(ModuleManager.LOYALTY))) {
Command back = new Command("", sm.getImage("back.png"), BACK);
back.putClientProperty("TitleCommand", true);
f.setBackCommand(back);
tb.addCommandToLeftBar(back);
}
if (!"Main".equals(formName)
&& !"Signup".equals(formName)) {
addSideCommand("Logout", "LogoutSideOption", LOGOUT, e->logoutUser(), tb);
addSideCommand("View T&Cs", "TnCSideOption", TANDC, e->showTandCs(), tb);
addSideCommand("Reset Tutorials", "TnCSideOption", CLEAR_TUTORIAL, e->clearTutorial(), tb);
}
}
private void addSideCommand(String name, String udid, int commandID, ActionListener event, Toolbar tb) {
Command command = new Command(name, null, commandID);
command.putClientProperty(SideMenuBar.COMMAND_PLACEMENT_KEY, SideMenuBar.COMMAND_PLACEMENT_VALUE_RIGHT);
Button comandLabel = new Button(name);
comandLabel.setUIID(udid);
command.putClientProperty(SideMenuBar.COMMAND_SIDE_COMPONENT, comandLabel);
tb.addCommandToSideMenu(command);
comandLabel.addActionListener(event);
}

This issue should be resolved and will be in the release this Friday (June 3rd 2016)

Related

Unity Raycast results different on two devices

I use the following codes to detect which UI element is the player pointing. It works well in Unity Editor, on one of my Android phone, but failed on a second Android phone.
public static T RaycastOnFirstPointed<T>(EventSystem eventSystem, GraphicRaycaster raycaster)
{
if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
if (Input.touches == null || Input.touches.Length == 0) return default;
}
var m_PointerEventData = new PointerEventData(eventSystem);
m_PointerEventData.position = Input.mousePosition;
var results = new List<RaycastResult>();
raycaster.Raycast(m_PointerEventData, results); // On the 2nd phone the results.length is 0
foreach (RaycastResult result in results)
{
var component = result.gameObject.GetComponent<T>();
if (component != null)
{
return component;
}
}
return default;
}
This method is called within a IEndDragHandler.OnEndDrag method. I tried to debug it on the 2nd Android phone, and saw the results.length is 0 after Raycast was executed.(it should be > 0 since I ended my drag on several overlapped UI elements, and it is > 0 on the 1st phone, not sure why the 2nd phone is different)
I don't have any clue where should I go from here to find the problem. Please show me some directions, thank you!
More info:
Phone 1: MI 8 Lite, OS: MIUI 10.3
Phone 2: MI 9, OS: MIUI 10.2.35
============Update===========
Reason found:
When IEndDragHandler.OnEndDrag is triggered, the Input.mousePosition has different value on the two devices. 1st Phone has the touch position from the last frame, while the 2nd phone seems clears that value, and it has a very large wrong value. I'm working on how to solve this in a proper way. Any suggestions are welcomed.
Problem solved. As I updated in the question, this problem is caused by wrong Input.mousePosition value on different devices. So I updated the RaycastOnFirstPointed method as follows:
public static T RaycastOnFirstPointed<T>(EventSystem eventSystem, GraphicRaycaster raycaster, PointerEventData eventData = null)
{
if (Application.platform == RuntimePlatform.Android || Application.platform == RuntimePlatform.IPhonePlayer)
{
if (Input.touches == null || Input.touches.Length == 0) return default;
}
var m_PointerEventData = new PointerEventData(eventSystem);
if (eventData == null)
{
m_PointerEventData.position = Input.mousePosition;
}
else
{
m_PointerEventData.position = eventData.position;
}
var results = new List<RaycastResult>();
raycaster.Raycast(m_PointerEventData, results);
foreach (RaycastResult result in results)
{
var component = result.gameObject.GetComponent<T>();
if (component != null)
{
return component;
}
}
return default;
}
When call this method within OnEndDrag, pass in the PointerEventData that unity provides and use its position.

Xamarin.Forms and Android - Getting the result of a toggle button from a different view

I have been following the custom pin tutorial using Xamarin.Forms which I have linked below. I have finished implementing it and I have also moved onto adding pins to the map as well through tapping.
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/map/customized-pin
(side note: I am working almost exclusively with Xamarin.Forms and Android)
Currently, I am able to tap on the map and a new custom pin will be added at that location, which is great. What is not great is that I was unable to figure out how to get a tap and long hold gesture to work instead of just the normal tap. To try to combat this, and because I will eventually have to add these anyways, I am planning on adding a button that the user can press to initiate that they want to add a button to the map, and I will later add an undo button, and many others, etc.
The problem is, I have no idea how to get the result of what my toggle button state is from the custom render that I am using for the map. Where can I get the result of my toggle button and use it as a boolean towards whether to add a button or not?
Here is the toggle button code, which I took line by line from their example on this page:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/button
Here is the code where I add a custom pin just by a single tap:
private void GoogleMap_MapClick(object sender, GoogleMap.MapClickEventArgs e)
{
((CustomMap)Element).OnTap(new Position(e.Point.Latitude, e.Point.Longitude));
var addingPin = new CustomPin
{
Type = PinType.Place,
Position = new Position(e.Point.Latitude, e.Point.Longitude),
Address = " - need to possibly implement - ",
Id = "shelter",
Label = "Pin from tap",
Url = "http://www.redcross.org"
};
Map.Pins.Add(addingPin);
this.customPins.Add(addingPin);
}
I thought about making a custom button render but by my knowledge I can only apply one Android render to a content page at a time, and when I tried to add a custom button render to the map render then this method was not happy, as it was taking in some sort of Android Map View and not a button view:
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
Control.GetMapAsync(this);
}
}
Any help is greatly appreciated. Below I have included a pic of what my application looks like so far, along with the custom page that I am using as well.
using Hermes.Models;
using System;
using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
namespace Hermes
{
public class MapPage : ContentPage
{
public MapPage()
{
CustomMap customMap = new CustomMap()
{
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand,
MapType = MapType.Street,
};
var examplePinSupplies = new CustomPin
{
Type = PinType.Place,
Position = new Position(42.02525, -93.65087),
Address = " - need to possibly implement - ",
Id = "supplies",
Label = "supplies",
Url = "https://www.redcross.org/store"
};
var examplePinMedical = new CustomPin
{
Type = PinType.Place,
Position = new Position(42.02290, -93.63912),
Address = " - need to possibly implement - ",
Id = "medical",
Label = "medical",
Url = "http://www.redcross.org"
};
var examplePinShelter = new CustomPin
{
Type = PinType.Place,
Position = new Position(42.02045, -93.60968),
Address = " - need to possibly implement - ",
Id = "shelter",
Label = "shelter",
Url = "http://www.redcross.org"
};
customMap.CustomPins = new List<CustomPin> { examplePinSupplies, examplePinMedical, examplePinShelter };
customMap.Pins.Add(examplePinSupplies);
customMap.Pins.Add(examplePinMedical);
customMap.Pins.Add(examplePinShelter);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(42.025250, -93.650870), Distance.FromMiles(1.0)));
var addPin = new ToggleButton { Text = "Add pin" };
var buttons = new StackLayout
{
Orientation = StackOrientation.Horizontal,
Children = {
addPin
}
};
Content = new StackLayout
{
Spacing = 0,
Children = {
customMap,
buttons
}
};
}
}
}
What I am trying to do: I am trying to tap the 'add pin' toggle button, and then the map will allow me to only add one pin on the map by tapping, and then any other consecutive taps that are not on another pin will not add another pin to the map.

How to close an Android app using UiAutomator?

How can I close an especific Android app using UiAutomator API?
Like when you manually press the Recents button and swipe the app you want to close.
Better way (not device, OS version, UI or orientation specific):
Runtime.getRuntime().exec(new String[] {"am", "force-stop", "pkg.name.of.your.app"});
Tested and working on a Nexus 5X with android 6.0
The best option would be to use getUiDevice.pressRecentApps, this will load up the recent apps for you, then take a screenshot using the uiautomator viewerso you have a view of the xml of the screen that has been loaded. You can then use this xml to select the object you wish to swipe using
UiObject app = new UIObject(new UiSelector().resourceId("The id of the app");
app.swipeLeft(100);
or right
This should be able to close your app. The xml will depend on what style of android you are using and the device.
This is how I kill all android apps at once with uiautomator:
public static void killApps()
{
UiDevice device = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
try
{
device.pressHome();
device.pressRecentApps();
// Clear all isn't always visible unless you scroll all apps down
int height = device.getDisplayHeight();
int width = device.getDisplayWidth();
device.swipe(width/2,height/2, width/2, height, 50);
UiObject clear = device.findObject(new UiSelector()
.resourceId("com.android.systemui:id/button")
.text("CLEAR ALL")
);
if (clear.exists())
{
clear.click();
}
}
catch (RemoteException e)
{
e.printStackTrace();
}
catch (UiObjectNotFoundException e)
{
e.printStackTrace();
}
}
Building on the solution from #user597159 I got the following to close all applications on a Pixel 2 for Firebase Test Lab (i.e. the "walleye" device type):
private void killAllApps() throws Exception {
boolean keepSwiping = true;
int maxSwipeAttempts = 10;
uiDevice.pressRecentApps();
for (int swipeAttempt=0; swipeAttempt<maxSwipeAttempts && keepSwiping; swipeAttempt++) {
int height = uiDevice.getDisplayHeight();
int width = uiDevice.getDisplayWidth();
uiDevice.swipe(width / 2, height / 2, width, height / 2, 50);
UiObject clearAll1 = uiDevice.findObject(new UiSelector().text("Clear all"));
UiObject clearAll2 = uiDevice.findObject(new UiSelector().textStartsWith("Clear all"));
UiObject clearAll3 = uiDevice.findObject(new UiSelector().textContains("Clear all"));
UiObject clear = clearAll1.exists() ? clearAll1 :
(clearAll2.exists() ? clearAll2 : clearAll3);
if (clear.exists()) {
Logger.debug(TAG, "Attempting to close app by killAllApps and found clear=all button on swipeAttempt=" + swipeAttempt);
clear.click();
keepSwiping = false;
} else {
Logger.debug(TAG, "Attempting to close app by killAllApps but have to keep swiping swipeAttempt=" + swipeAttempt);
keepSwiping = true;
}
}
}
Note on the Pixel 2, it is spelled "Clear all" not "CLEAR ALL".
I could not get some of the other solutions to work. I got UiObjectNotFoundException for the following:
app = uiDevice.findObject(new UiSelector().textContains("SDK Test App"));
And also for:
app = uiDevice.findObject(new UiSelector().className(com.locuslabs.android.sdk.SdkTestApplication.class));
In other words app.exists() returned false for these approaches that attempted to swipe up on the app to close on Pixel 2.
When it is just one app that will be in the recent app list, this worked for me.
if(mDevice.pressRecentApps()) {
Thread.sleep(1000);
int startX = 300; int startY =835; int endX = 1000; int endY = 835; // co-ordinates refer to x-axis from left of screen to right.
int steps = 8;// speed at which the app closes
mDevice.swipe(startX,startY,endX,endY,steps);
}
Here's a Kotlin answer that is similar to this answer. It adds an extension function to UiDevice to clear all tasks. I tested this on a Pixel 2 emulator.
fun UiDevice.clearAllTasks(swipeAttempts: Int = 10 ) {
pressRecentApps()
var currentAttempt = 1
val centerScreenX = displayWidth / 2
val centerScreenY = displayHeight / 2
while (currentAttempt <= swipeAttempts) {
Timber.d("Clear all tasks attempt $currentAttempt")
swipe(centerScreenX, centerScreenY, displayWidth, centerScreenY, 50)
val uiObject = findObject(UiSelector().text("Clear all"))
if (uiObject.exists()) {
uiObject.click()
break
} else {
currentAttempt++
}
}
}
So I took a little more comprehensive approach to this at it seemed quite unreliable with others answers. I use A LOT of custom extensions so will try to post most of them:
fun UiDevice.clearTasks(swipes: Int = 2) {
logInfo { message("clearTasks swipes:$swipes") }
pressHome()
wait()
pressRecentApps()
wait()
repeat(swipes) {
if (context.isPortrait)
swipe(centerScreenX, centerScreenY, centerScreenX, 50, 10)
else
swipe(centerScreenX, centerScreenY, 25, centerScreenY, 10)
wait()
}
}
fun UiDevice.wait(seconds: Int = defaultWaitTime) {
logInfo { message("wait:$seconds") }
waitForWindowUpdate(null, seconds * SecondLong)
waitForMoreIdle()
}
fun UiDevice.waitForMoreIdle(times: Int = 3) {
logInfo { message("waitForMoreIdle times:$times") }
repeat(times) { waitForIdle() }
}
val UiDevice.centerScreenX get() = displayWidth / 2
val UiDevice.centerScreenY get() = displayHeight / 2
val Context.isPortrait get() = resources.configuration.orientation == ORIENTATION_PORTRAIT
val context: Context get() = ApplicationProvider.getApplicationContext()
Note: I don't really on some text as it depends on language on phone that can be different. Also I like more this custom swipe times approach as I know how much tasks approximately I need to clear out most of the time. There is side effect of showing app launcher but who cares. Didn't find a way to detect it to cancel swiping yet.

keyup not working on Chrome on Android

I am using bootstrap typeahead.
It depends on this jQuery code to work:
el.on('keyup', doSomething() )
On Chrome on Windows it works fine. On Chrome on Android it doesn't. The keyup event is never fired. The element to which it is bound definitely has the focus.
This appears to be a recent development.
Chrome 28.0.1500.64
Android 4.1.2 SGP321 Build/10.1.1.A.1.307
Thanks
--Justin Wyllie
I came across this same problem earlier today. How can android chrome not support these key events! I assume you've found a workaround by now, but here's a fix that I came up with for now.
function newKeyUpDown(originalFunction, eventType) {
return function() {
if ("ontouchstart" in document.documentElement) { // if it's a touch device, or test here specifically for android chrome
var $element = $(this), $input = null;
if (/input/i.test($element.prop('tagName')))
$input = $element;
else if ($('input', $element).size() > 0)
$input = $($('input', $element).get(0));
if ($input) {
var currentVal = $input.val(), checkInterval = null;
$input.focus(function(e) {
clearInterval(checkInterval);
checkInterval = setInterval(function() {
if ($input.val() != currentVal) {
var event = jQuery.Event(eventType);
currentVal = $input.val();
event.which = event.keyCode = (currentVal && currentVal.length > 0) ? currentVal.charCodeAt(currentVal.length - 1) : '';
$input.trigger(event);
}
}, 30);
});
$input.blur(function() {
clearInterval(checkInterval);
});
}
}
return originalFunction.apply(this, arguments);
}
}
$.fn.keyup = newKeyUpDown($.fn.keyup, 'keyup');
$.fn.keydown = newKeyUpDown($.fn.keydown, 'keydown');
Sorry to say this but keyup/keydown events do not work for chrome browser in android.
There are other people who have reported this issue(Here and Here) from last 1 year and its not fixed yet. so it's better for developers to avoid using these events till it gets fixed.

android emulator restarts itself (ADT)

When i invoke a function which is described below, android emulator restarts from beginning.
The function is like that
int index = 0;
Position myPostion;
Position destPosition = roadInstruction.getInstructionAt(index).getEndAddr();
while(index<roadInstruction.getNumInstruction())
{
myPostion = getMyPosition();
while(!hasArrivedToDestination(myPostion, destPosition ))
{
myPostion = getMyPosition();
}
++index;
}
What is the reason?
It maybe because of the inner while loop, but i am not sure.

Categories

Resources