Button.setTextPosition(Label.LEFT); render wrong - android

My NetBeans recently updated new CodenameOne plugin and it looks like the Button.setTextPosition(Label.LEFT); renders wrong position of the icon on Android and iOS, the icon always overlaps with the text. It still renders with the simulator correctly and the function still renders with Label.RIGHT, Label.TOP and Label.BOTTOM parameters correctly. Do you have any idea?
Thanks,
William

Shai, I think the problem is that the icon was scaled to font.getHeight() of the button.
public void start() {
if(current != null){
current.show();
return;
}
Form hi = new Form("Test", new BoxLayout(BoxLayout.Y_AXIS));
Font font = new Button("Test").getUnselectedStyle().getFont();
Image t = pictures.getImage("Play.png").scaled(font.getHeight(), font.getHeight());
hi.add(b(Button.LEFT, " Left 123", t))
.add(b(Button.RIGHT, " Right ", t))
.add(b(Button.TOP, " Top ", t))
.add(b(Button.BOTTOM, " Bottom ", t));
hi.add(b(Button.LEFT, " Left ", t))
.add(b(Button.RIGHT, " Right ", t))
.add(b(Button.TOP, " Top ", t))
.add(b(Button.BOTTOM, " Bottom ", t));
hi.show();
}
private Button b(int pos, String txt, Image t) {
Button btn = new Button(txt, t);
btn.setTextPosition(pos);
return btn;
}
Here is the screenshots:
Simulator:
Nexus (android):

I see the issue there, its a regression that only occurs with smaller icons since the width of the icon is used instead of the width of the text only in the case of left aligned text which is more rare.
We'll fix this in the next server update.

Related

Disable contextual Action bar in android webview on text selection

How to disable contextual action bar in web view? I Want text selection feature to remain as it is , but i don't want the Contextual action bar to come, how can i disable it ?
Using this code hides the contextual action bar but it is looking bad(whole screen is shaking ) and also text selection is not retaining.
#Override
public void onSupportActionModeStarted(ActionMode mode) {
super.onSupportActionModeStarted(mode);
mode.finish();
}
How can i disable the contextual actionbar ? Is there any other way?
I know it is late to answer question but i just found it and it works fine.(I tested it on 5.0.1 and it works fine)(Following code will only clear copy , paste and select all option from menu.)
inject folliwing code in your html code which you will be loading in webview,
"<script src=\"https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\"></script>\n" +
"<script>\n" +
"$(function() {\n" +
" $(document.body).bind('touchstart', function(e) {\n" +
" var selection;\n" +
"\n" +
" if (window.getSelection) {\n" +
" selection = window.getSelection();\n" +
" } else if (document.selection) {\n" +
" selection = document.selection.createRange();\n" +
" }\n" +
"\n" +
" selection.toString() !== '' && ReaderJavaScript.onTextselectionEnded(true)\n" +
" });\n" +
"});\n" +
"</script>"
see in code i used ReaderJavaScript interface which will act as bridge between js code and activity to carry information on call of ReaderJavaScript.onTextselectionEnded(true).
so whenever user end selection it will indicate and at that time you just have to add following code to clear menus in your activity,
readerView.setTextSelectionFinishedListener(new ReaderView.TextSelectionFinishedListener() {
#Override
public void onTextSelectionEnded(boolean textSelectionEnded) {
if (mActionMode != null){
if (mActionMode.getMenu() != null){
mActionMode.getMenu().clear();
}
}
}
});
Simply remove it manually.
When the legacy action mode bar is triggered, the view hierachy would be:
So just fix the unwanted hierachy by the following code:
View p2th = Utils.getNthParent(root, 2);
if (p2th!=null && p2th.getId()==R.id.action_bar_root) {
Utils.replaceView(Utils.getNthParent(root, 1), p2th);
}
where Utils.getNthParent returns N-th parent of the root view, and Utils.replaceView just replace the action bar root with our content view .
(tested on android 4.4 and 5 sucessfully, without flicker or crash.)
What a genius solution, so simple and so stupid……

How to Swipe and Scroll to the Last in Appium

I am getting some Images from the API and i don't know the number and now i want to test the UI in Android through Appium and i want to scroll down to the Last image. How can I do this and also I don't know the what the title from the API is coming so that I can ScrollTo("Title") and also i am not able to swipe to the last. Is there anyway?
There is no way to know for sure whether you've scrolled to the last using appium because there is no UI reporting for the edges of a scrollview.
One way to know that you've reached the end of a scroll view without relying on devs is to compare the list of all children of the scrollview every time you swipe. If all children are exactly the same, you've reached the end. An example xpath for this would look like //android.widget.View[#content-desc="Your scrollview]//*, which would grab all children and descendants. Once you have a list to compare, check the content of all children nodes. This will only work if there's something unique in these items. If all items are completely general, there will be nothing to compare and this won't be reliable. Ask devs to add content descriptions or accessibility data to the items if possible.
Another option would be to have the devs embed a uniquely id'd invisible view at the top and bottom of the scrollview. That way, if it can be found by the driver, you know that you've reached the very edge of the view. If there are already unique elements at the edges of your scrollview, you can use those.
In the end, the devs of the application can really help out the process of scrolling, but hopefully the trick of comparing the current scrollview's children can help you.
You can use the screen dimensions to scroll down:
public void scrollDown() {
Dimension size = driver.manage().window().getSize();
int x = size.getWidth() / 2;
int starty = (int) (size.getHeight() * 0.60);
int endy = (int) (size.getHeight() * 0.10);
driver.swipe(x, starty, x, endy, 2000);
}
You can store all the images into a list using its available locator. Then use driver.scrollToExact(list.get(list.size()).getAttribute("name"));
Example:
List<mobileElement> images = driver.findElementsByClass("<locator>");
driver.scrollToExact(images.get(images.size()).getAttribute("name"));
or
driver.scrollToExact(images.get(images.size()).getText());
#Test
public void testScroll()throws Exception
{
for(int i=0;i<4;i++)
{
Thread.sleep(2000);
if (driver.findElement(By.name("end_item")).isDisplayed())
{
driver.findElement(By.name("end_item")).click();
break;
}
else
{
horizontalScroll();
}
}
}
public void verticalScroll()
{
size=driver.manage().window().getSize();
int y_start=(int)(size.height*0.60);
int y_end=(int)(size.height*0.30);
int x=size.width/2;
driver.swipe(x,y_start,x,y_end,4000);
}
The above example works with vertical scroll and it is based on the example given at this blog for horizontal scroll
http://qaautomated.blogspot.in/2016/02/how-to-do-horizontal-scroll-in-appium.html
I hope this works for you.
To do this you must know resource id or cont-desc of scrollable element. You also need to know className of your scrollable element.
If you have cont-desc in scrollable list
try {
String scrollableList="your con-desc of scrollable List";
String elementClassName="android.something.something";
String anyText="any text";
driver.findElement(MobileBy.AndroidUIAutomator(
"new UiScrollable(new UiSelector().description(\"" + scrollableList + "\")).getChildByText("
+ "new UiSelector().className(\"" + elementClassName + "\"), \"" + anytext + "\")"));
}catch (Exception e){
System.out.println("Cannot scroll further");
}
If you have resource-id in scrollable list
try {
String scrollableList="your con-desc of scrollable List";
String elementClassName="android.something.something";
String anyText="any text";
driver.findElement(MobileBy.AndroidUIAutomator(
"new UiScrollable(new UiSelector().resourceId(\"" + scrollableList + "\")).getChildByText("
+ "new UiSelector().className(\"" + elementClassName + "\"), \"" + anytext + "\")"));
}catch (Exception e){
System.out.println("Cannot scroll further");
}
If the screen cannot be scroll further it will throw error which will be catched by catch block.

Managing data in android cache?

I'm trying to finish the 'backbone' of my app in the next 3 weeks, however, one of the few obstacles I stutter at is saving data. I've had a look at saving data internally, but there is limited tutorials from what I can find of reading and writing multiple lines to files in the apps cache directory.
Basically what I'm trying to do is save the values stored inside a fragment. This fragment resets all its values when the user clicks a button and changes text to match a page number. (A number of duplicates that contain various values.) I would do multiple fragments, however, thought it would be beneficial to use just one fragment to minimize storage space needed.
I've only got round to writing to the files, and created two methods to manage this which are then called on the click of a button. One creates these files and the other writes to them. Unfortunately I'm inexperienced using adb and could only find that the files are created, but don't know if they are being correctly written to. Is there any chance someone could review this and possibly assist with re-reading the files? Help is much appreciated.
The two methods (Warning: A great number of lines ahead):
public void createEmptyFiles() {
try {
outputTempExerciseFileE1 = File.createTempFile("temp_exercise_1",
".txt", outputTempExerciseDir);
outputTempExerciseFileE2 = File.createTempFile("temp_exercise_2",
".txt", outputTempExerciseDir);
outputTempExerciseFileE3 = File.createTempFile("temp_exercise_3",
".txt", outputTempExerciseDir);
} catch (IOException e) {
e.printStackTrace();
Log.w("rscReporter", "Encountered an error when creating empty files!");
}
}
public void writeTemporaryFiles() {
try {
if (counterAnotherExercise == 1) {
writerTemp = new FileWriter(outputTempExerciseFileE1);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
} else if (counterAnotherExercise == 2) {
writerTemp = new FileWriter(outputTempExerciseFileE2);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
} else if (counterAnotherExercise == 3) {
writerTemp = new FileWriter(outputTempExerciseFileE3);
writerTemp
.write(editTextExerciseName.getText().toString() + "\n"
+ counterNoSets + "\n" + counterRepsPerSet
+ "\n" + counterMeanRepTime + "\n"
+ counterMeanRepTimeRefined + "\n"
+ counterSetInterval);
writerTemp.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
Any of the text files should look like:
editTextExerciseName
counterNoSets
counterRepsPerSet
counterMeanRepTime
counterMeanRepTimeRefined
counterSetInterval
Where the two methods are called:
// In a switch statement as there are around 15 buttons
case R.id.button_another_exercise_foreground:
// Increases page number in fragment
counterAnotherExercise++;
// This then checks the page number and changes text
checkPageNo();
// Writing to files is called, files were created in onCreateView()
writeTemporaryFiles();
// Resets all the counters, giving the imitation it is a completely new fragment
counterReset();
// default array exercise is then set to the page number which is then displayed as title
// For example: Exercise 1, Exercise 2, Exercise 3...
textViewExerciseTitle.setText(defaultArrayExercise);
break;
I only know the basics of Java and Android, for myself this is ambitious, however, you gotta learn somewhere! Additional suggestion for saving values are welcomed.
You don't really need files as you are only writing and then reading a handful of fixed data. Use SharedPreferences like this:
to write:
PreferenceManager.getDefaultSharedPreferences(YourActivity.this).edit().putString("editTextExerciseName", "my exercise").commit();
to read:|
PreferenceManager.getDefaultSharedPreferences(YourActivity.this).getString("editTextExerciseName");

Update "Log.i" in TextView with ScrollBar

I have in my layout.xml a TextView with "id = txtLog".
Where do the test results from my application using:
Log.i("Result:", "Value of x = " + x);
for show result in LogCat.
It is possible to show these results "Log.i" within the TextView?
Note: I left a space at the bottom of my application to show the TextView.
Like a console.
I would like to display these messages on TextView.
If possible create a scroll bar and display every time I use Log.i
I am a beginner, do not know if it is possible. Yet thanks.
I would think
myTextView.setText(myTextView.getText() + "Value of x = " + x + "\n");
would work.
EDIT:
Also, to make the TextView scrollable, you need to set a movement method like so:
myTextView.setMovementMethod(new ScrollingMovementMethod());
EDIT 2:
If you want the information to go to both Log.i and a TextView, then you need a method that holds a reference to the TextView you want to update.
public static void LogToView(TextView myTextView, String title, String message) {
Log.i(title, message);
myTextView.setText(myTextView.getText() + title + ": Value of x = " + x + "\n");
}
Put that in whatever class or in your Activity class. Use it instead of Log.i and the message will be passed to both.

Attempting to remove an object off screen moves all the objects in play?! - Android. Please Help!

I am building an android game where objects randomly come in from either side of the screen towards a sprite in the middle of the screen. When one passes the tripwire on the central sprite it is dealt with by my collision detection which sets the enemy objects co-ordinates to somewhere off the screen, thats desired but as this happens in my updatePhysics() method when we loop back to the doDraw() method the canvas has redrawn to an empty state (ie. without any enemy objects on it). Any objects that were on screen and not colliding with the sprite are erased too and new ones regenerated. Why is it removing all the enemy objects rather than just updating the position of the ones left in play at that point???
I will include my code to make this simpler to understand. This is the collision detection part of my updatePhysics():
// COLLISION DETECTION
int n = 0,haveHidden = 0; //haveHidden is number of objects that are hidden in this current pass of CD
while(n < mCurrentDistractionsOnScreen){
switch(DistractionsArray[n].dGeneralDirection){
case LEFT_ORIGIN:
// If the X co-ordinate is past the edge of the performer sprite
if((DistractionsArray[n].ObjmX2 > LEFT_TRIPWIRE) && (DistractionsArray[n].ObjmX2 < RIGHT_TRIPWIRE))
{
mConcentration -= DistractionsArray[n].dDamageToInflict;
Log.w(this.getClass().getName(), "Object: " + n + "LEFT Damage: " + DistractionsArray[n].dDamageToInflict + " leaves " + mConcentration);
DistractionsArray[n].hideDistraction();
haveHidden++;
}
break;
case RIGHT_ORIGIN:
// If the X co-ordinate is past the edge of the performer sprite
if((DistractionsArray[n].ObjmX > LEFT_TRIPWIRE) && (DistractionsArray[n].ObjmX < RIGHT_TRIPWIRE))
{
mConcentration -= DistractionsArray[n].dDamageToInflict;
Log.w(this.getClass().getName(), "Object: " + n + "RIGHT Damage: " + DistractionsArray[n].dDamageToInflict + " leaves " + mConcentration);
DistractionsArray[n].hideDistraction();
haveHidden++;
}
break;
}
n++;
mCurrentDistractionsOnScreen -= haveHidden;
}
This is the hideDistraction() method that is a method defined in the DistractionObjects inner class in this thread (DistractionsArray consists of these objects):
public void hideDistraction(){
// Set attributes to default
this.dName = "Default";
this.dVelocity = 0;
this.dMaxPoints = 10;
this.dDamageToInflict = 0;
this.dOrigin = 100;
this.dGestureRequired = "";
// Can be reused again
this.isUseable = true;
Log.w(getClass().getName(), "HIDING FROM: " + this.ObjmX + " " + this.ObjmY + " " + this.ObjmX2 + " " + this.ObjmY2 + " ");
// Position it off-screen
this.ObjmX = -150;
this.ObjmX2 = -150 + this.dDistractionObjectSprite1.getIntrinsicWidth();
this.ObjmY = -150;
this.ObjmY2 = -150 + this.dDistractionObjectSprite1.getIntrinsicHeight();
Log.w(getClass().getName(), "HIDING TO: " + this.ObjmX + " " + this.ObjmY + " " + this.ObjmX2 + " " + this.ObjmY2 + " ");
}
And the doDraw method starts by canvas.save() and at the end does a canvas.restore. To render my objects at their new position it does this:
// For each object in play, draw its new co-ordinates on the canvas
int n = 0;
while(n < mCurrentDistractionsOnScreen){
DistractionsArray[n].dDistractionObjectSprite1.setBounds((int)DistractionsArray[n].ObjmX,
(int)DistractionsArray[n].ObjmY,
(int)DistractionsArray[n].ObjmX2,
(int)DistractionsArray[n].ObjmY2);
DistractionsArray[n].dDistractionObjectSprite1.draw(canvas);
n++;
}
I am literally devoid of any ideas now after trying so many different fixes, even attempted to serialize the position of those other enemy objects on screen in an integer array that is rebuilt in the physics method but nothing!!
To summarise, I need a way of hiding the enemy object off-screen like in hideDistraction() when it passes the tripwire, but I want all the other objects to still continue on course as they are without being moved off screen and re-rendered from scratch.
If you need more details please ask....and if you can, pleaseeee help!
Many thanks
Greenhouse,
You are controlling your loop using the mCurrentDistractionsOnScreen, but you are also resetting the mCurrentDistractionsOnScreen inside of the loop. You likely don't want to be doing this. The exact reason it is removing everything is likely very difficult to pin down (i'm not surprised you couldn't figure it out!). Try re-factoring that main while loop to something like this:
for (Distraction distraction: DistractionsArray) {
switch(distraction.dGeneralDirection) {
case LEFT_ORIGIN:
// Your code goes here ...
break;
case RIGHT_ORIGIN:
// Your code goes here ...
break;
}
}
When pasting your code, remove all references to DistractionsArray[n] and replace them with distraction
EDIT:
If this helps you, then please consider 1) accepting more answers on your questions and 2) Not putting stuff like 'please help' in your titles. It's a site geared towards help, we know what you are looking for ;)
Your hideDistraction() and doDraw code is likely fine.

Categories

Resources