I've got a page that has an action bar and a layout that takes the rest of the page. I'd like to know the height of the rest of the page - that's SCREEN_HEIGHT - STATUS_BAR_HEIGHT - ACTION_BAR_HEIGHT.
I can get SCREEN_HEIGHT via platform.screen.mainScreen.heightDIPs.
How can I get the height of the STATUS_BAR and ACTION_BAR.
When I try to do a height or getMeasuredHeight(), I get 0.
Using the answer from Brad, here's the ts code
let resource_id = application.android.foregroundActivity.getResources().getIdentifier("status_bar_height", "dimen", "android");
if ( resource_id > 0 )
console.log( "status_bar_height=" + application.android.foregroundActivity.getResources().getDimensionPixelSize(resource_id) );
// android.content.res.TypedArray
let array = application.android.foregroundActivity.getTheme().obtainStyledAttributes( [ android.R.attr.actionBarSize ] );
console.log( "actionBarHeight=" + array.getDimension(0,0) );
Looks like the values returned is the actual pixels.
If you want the DIP values - divide by platformModule.screen.mainScreen.scale.
Related
I know how to render an JPEG image on the screen in a Vaadin 14.1 app.
In particular, the 3 lines:
imageReader.setInput( imageInputStream ); // Render the image from the data provided by the `ImageInputStream`.
imageWidget.setWidth( imageReader.getWidth( 0 ) + "px" ); // Get the pixel size of the rendered image.
imageWidget.setHeight( imageReader.getHeight( 0 ) + "px" );
…of this:
private Image createImageWidget ( String mimeType , String fileName , InputStream inputStreamOfImageData )
{
if ( mimeType.startsWith( "image" ) )
{
Image imageWidget = new Image();
try (
inputStreamOfImageData ;
// Auto-close.
)
{
// Get the octets of the image data.
final byte[] bytes = IOUtils.toByteArray( inputStreamOfImageData );
// Make the image widget for Vaadin.
imageWidget.getElement().setAttribute( "src" , new StreamResource( fileName , ( ) -> new ByteArrayInputStream( bytes ) ) );
imageWidget.setAlt( "File name: " + fileName );
// Size the image for display in the HTML/CSS for faster rendering without the page layout jumping around in front of user.
try (
ImageInputStream imageInputStream = ImageIO.createImageInputStream( new ByteArrayInputStream( bytes ) ) ;
// Auto-close.
)
{
// Apparently, image readers (parsers/decoders) are detected at runtime and loaded via the "Java Service Provider Interface (SPI)" facility.
final Iterator < ImageReader > imageReaders = ImageIO.getImageReadersByMIMEType( UploadView.MIME_TYPE_JPEG ); // OR, for multiple image types, call `ImageIO.getImageReaders( in )`.
if ( imageReaders.hasNext() )
{
ImageReader imageReader = imageReaders.next();
try
{
imageReader.setInput( imageInputStream ); // Render the image from the data provided by the `ImageInputStream`.
imageWidget.setWidth( imageReader.getWidth( 0 ) + "px" ); // Get the pixel size of the rendered image.
imageWidget.setHeight( imageReader.getHeight( 0 ) + "px" );
}
finally
{
imageReader.dispose();
}
} else
{
throw new IllegalStateException( "Failed to find any image readers for JPEG. " + "Message # e91ce8e4-0bd3-424d-8f7c-b3f51c7ef827." );
}
}
}
catch ( IOException e )
{
e.printStackTrace();
}
return imageWidget;
}
// TODO: Log error. Should not reach this point.
System.out.println( "BASIL - ERROR - Ended up with a null `imageWidget`. " + "Message # 415bd917-67e2-49c3-b39a-164b0f900a3a." );
return null;
}
I understand that in those 3 lines, we are informing the web page of the width and hight of the image rather than letting the web page discover the images’ size as they load. This makes layout faster, and avoids the annoyance of a web page jumping around in front of the user.
➥ My question is: What about modern monitors with a high density of pixels, Retina displays as Apple calls them?
How can I get an image to effectively display all its pixels, but taking up the least space on the screen?
If the monitor has old-fashioned low pixel density, the image should display with more centimeters of physical screen space than on a high-density Retina display where the image can take fewer centimeters of screen while still technically displaying all the image's pixels.
A quick search online didn't find any native browser feature for giving different dimensions to an <img> element depending on the native pixel density. What we do have is the window.devicePixelRatio property that can be read using JavaScript. See guide by Mozilla.
You can use this together with executeJs in two different ways - either to set the size of each element dynamically or to fetch the value to the server and then do the calculation on the server for each Image component.
The first alternative would look something like this:
imageWidget.getElement().executeJs("this.style.width = ($0 / window.devicePixelRatio) + 'px';" +
"this.style.height = ($1 / window.devicePixelRatio) + 'px';",
imageWidth, imageHeight);
The second alternative to fetch the ratio and use it would be like this:
ui.getPage().executeJs("return window.devicePixelRatio;")
.then(Double.class, ratio -> this.devicePixelRatio = ratio.doubleValue());
// Later, in some other location
imageWidget.setWidth((imageWidth / this.devicePixelRatio) + "px");
imageWidget.setHeight((imageHeight / this.devicePixelRatio) + "px");
EDIT: A variant of the second approach that uses retrieveExtendedClientDetails instead of executeJs:
ui.getPage().retrieveExtendedClientDetails(details -> this.devicePixelRatio = details.getDevicePixelRatio());
// Later, in some other location
imageWidget.setWidth((imageWidth / this.devicePixelRatio) + "px");
imageWidget.setHeight((imageHeight / this.devicePixelRatio) + "px");
In Vaadin 14 the Image component is just representation of HTML img tag. This should mean that size units like em or relative percentages should be applicable. These should work better when you do not want to make assumptions about the screen size. General rule of thumb in creating responsive designs is to avoid pixel sizes and use e.g. em or percentages instead.
But if you want to perform relative size calculations your self for some reason, you can obtain the size of the browser window this way:
getUI().ifPresent(ui -> ui.getPage().retrieveExtendedClientDetails(receiver -> {
int bodyWidth = receiver.getBodyClientWidth();
System.out.println("Width "+bodyWidth);
}));
I have created an animated faceted map using tmap:: tm_facets along with custom panel labels. How do I avoid that the argument that is used to facet is shown as additional title? I only want the custom label in the panel.
Minimum example:
rm(list=ls(all=TRUE))
library(tmap)
library(spData)
urb_anim = tm_shape(world) + tm_polygons() +
tm_shape(urban_agglomerations) + tm_dots(size = "population_millions") +
tm_facets(along = "year", free.coords = FALSE) +
tm_layout(panel.labels = c("custom label1", "custom label2"))
That gives me the following result:
When I try to reproduce the example for an animated map from here: https://geocompr.robinlovelace.net/adv-map.html I also don't get the titles in a panel as in the example but outside the plot in the top left corner.
I found the answer myself:
Using the by instead of the along argument with tm_facets worked for me when setting ncol =1 and nrow = 1 and saving the the created map using tmap_animation. So the code should be:
urb_anim = tm_shape(world) + tm_polygons() +
tm_shape(urban_agglomerations) + tm_dots(size = "population_millions") +
tm_facets(by = "year", free.coords = FALSE, ncol=1, nrow=1) +
tm_layout(panel.labels = c("custom label1", "custom label2"))
I am working on a drawing application in HTML5 canvas, using Easeljs. So far I am able to drag and drop objects into the field, but I only want them within certain bounds.
To illustrate:
Objects 1, 2, 4 and 5 should get deleted, but object 3 should be kept.
I have tried using hitTest(), but that didn't work properly (I probably did something wrong). I would love to post the code I used, but my PC froze while working on it... Thought I'd better ask while unfreezing, haha.
Here is a quick drag and drop sample with bounds constraining:
http://jsfiddle.net/xrqatyLs/8/
The secret sauce is just in constraining the drag position to your own values.
clip.x = Math.max(bounds.x, Math.min(bounds.x + bounds.width - clipWidth, evt.stageX));
clip.y = Math.max(bounds.y, Math.min(bounds.y + bounds.height-clipHeight, evt.stageY));
Here is another more complex example that manually checks if one rectangle intersects another rectangle:
http://jsfiddle.net/lannymcnie/yvfLwdzn/
Hope that helps!
Solution:
var obj1 = obj.getBounds().clone(); // obj = a pylon
var e = obj1.getTransformedBounds();
var obj2 = bg.getBounds().clone(); // bg = the big green field
var f = obj2.getTransformedBounds();
if(e.x < f.x || e.x + e.width > f.x + f.width) return false;
if(e.y < f.y || e.y + e.height > f.y + f.height) return false;
return true;
After all it's so simple, but I guess I was working on it for so long that I started to think too hard...
How to access urls of images and xy coordinates from the DOM.
I have a div with multiple image gifs in it.
The gifs represent electronic components on stripboard or protoboard.
The img gifs are generated using this code.
function createDiv(img)//img here original code was for creating new divs
{
alert(divnumber);//an incrementing or decrementing image array position counter
{
var divTag = document.createElement("img");
divTag.id ='part'+divnumber;
imageArray[divnumber+1]=200;//arbitrary inital x placement
imageArray[divnumber+2]=200;//arbitrary initial y placment
divTag.className ="dragme";
divTag.src = imageArray[divnumber];//gif;//imageArray[i];
document.body.appendChild(divTag);
}
divnumber=divnumber+3;//offset between gif url in image array
}
The gifs are draggable using this code. I don't fully understand drag code but it was the simplest I could find and make work.
//<script language="JavaScript1.2">
<!--
var ie=document.all;//if using explorer
var nn6=document.getElementById&&!document.all;//if using netscape
var isdrag=false;//are we dragging??
var x,y;
var dobj;//drag object
function movemouse(e)
{
if (isdrag) //if drag istrue
{
dobj.style.left = nn6 ? tx + e.clientX - x : tx + event.clientX - x;
//alert(dobj.style.left);
dobj.style.top = nn6 ? ty + e.clientY - y : ty + event.clientY - y;
return false;
}
}
function selectmouse(e)
{
var fobj = nn6 ? e.target : event.srcElement;
var topelement = nn6 ? "HTML" : "BODY";
while (fobj.tagName != topelement && fobj.className != "dragme")
{
fobj = nn6 ? fobj.parentNode : fobj.parentElement;
}
if (fobj.className=="dragme")
{
isdrag = true;
dobj = fobj;
tx = parseInt(dobj.style.left+0);
//alert(tx);
ty = parseInt(dobj.style.top+0);
x = nn6 ? e.clientX : event.clientX;
//alert(x +' "=y);
y = nn6 ? e.clientY : event.clientY;
document.onmousemove=movemouse;
return false;
}
}
document.onmousedown=selectmouse;//go to selectmouse when mouse down in document
document.onmouseup=new Function("isdrag=false");
//-->
I need to put all the gifs and x y coordinates into an array that I can save with html5 local storage.
I can save an array and recall it ok.
But I need to fill the array with urls and xy coords of draggable items.
I can't figure how to get that info from either the dragging code or the DOM.
I think I can get that info from the dom image list but I still cant get up to speeds on all the dom details.
Can anyone tell me how to identify the gif url and xy coordinates from either the drag code or the DOM.
This is basically my last hurdle before I can comnplete the prrogram.
Many Thanks. I am mainly a cut and paste and hacking found scripts in my programming level.
Oh!! I am almost 70 and this IS NOT a homework problem!!
Thanks markE for last help.
TiMathis
After further thought I can probably dig the xy's out of the drag code but how can I determine which gif is being dragged?
OK I can get the objects id ...alert(dobj.id)
I should be able to use that to get other info for immage array info I need.
if (fobj.className=="dragme")
{
isdrag = true;
dobj = fobj;
alert(dobj.id);
tx = parseInt(dobj.style.left+0);
//alert(tx);
ty = parseInt(dobj.style.top+0);
x = nn6 ? e.clientX : event.clientX;
//alert(x +' "=y);
y = nn6 ? e.clientY : event.clientY;
document.onmousemove=movemouse;
return false;
}
}
I tried this:
#IBAction func test(sender : AnyObject){
let height:CGFloat = 44
var tableFrame:CGRect = tableView.frame;
var fieldFrame = CGRect()
fieldFrame.origin = tableFrame.origin
fieldFrame.size.height = height
fieldFrame.size.width = tableFrame.size.width
var textField = UITextField(frame: fieldFrame)
textField.backgroundColor = UIColor(white: 0, alpha: 1)
view.addSubview(textField)
tableFrame.size.height = tableFrame.size.height - height
tableFrame.origin.y = tableFrame.origin.y + height
tableView.frame = tableFrame
}
When running, black field appears, but table won't move nor change size. Removing line
view.addSubview(textField)
allows table to change size and move, but, obviously, no field appears. What is the problem?
your textfield is actually on top of tableview. Your touch actions are probably going to the text fieldview and not to the tableview