I am new to xamarin.forms. I want to get height,width and resolution of my mobile programmatically in xamarin.forms. Please help to resolve this.
Recently Xamarin.Essentials NuGet pakage was released and there is a useful class DeviceDisplay in there that should handle this task for you.
The documentation can be found here.
Usage example:
// Get Metrics
var metrics = DeviceDisplay.ScreenMetrics;
// Orientation (Landscape, Portrait, Square, Unknown)
var orientation = metrics.Orientation;
// Rotation (0, 90, 180, 270)
var rotation = metrics.Rotation;
// Width (in pixels)
var width = metrics.Width;
// Height (in pixels)
var height = metrics.Height;
// Screen density
var density = metrics.Density;
Related
Hey guys im using const {width,height} = Dimensions.get('window');
to adjust my font based on screen width size.
using like this....
fontSize:width/24
its looks good in iPhone and android device like 5.5 inch device but in my Galaxy s9 it looks horrible I want to set my font based on screen which can be adjust by itself..
how can I do it
Then the best option is to use vmax and vmin units.
vmin: 1/100th of the smallest side,
vmax: 1/100th of the largest side
take a look at it here
Use a responsive ilibrary like this that will handle things better.
react-native-size-matters
Eg:
import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
const Component = props =>
<View style={{
width: scale(30),
height: verticalScale(50),
padding: moderateScale(5)
}}/>;
Thus things will look better in all devices. Use verticalScale for defining things relative to height of the device. scale can be used for normal things .. then there is a custom option moderateScale where u can manually define the scaling ratio as well.
For more details refer : Scaling React Native apps
PS: there are other options as well where u can manually define a custom class to get the PixelRatio and everything. but this is a straight forward approach.
Refer PixelRatio Approach
In order to get access to the device's pixel density and font scale, you can benefit from PixelRatio according to the docs.
As indicated in the docs, PixelRatio.get() provides you with the device pixel density:
var dynamic_fontSize = 20;
if(PixelRatio.get() === 1) { // mdpi Android devices
dynamic_fontSize = 12;
} else if(PixelRatio.get() === 1.5) { // hdpi Android devices
...
}
else { ...
Another idea is to make use of the layout size using roundToNearestPixel().
Let's imagine you want to adjust the size of an element to take over 98% of the screen’s width in dp and 10% of the screen’s height in dp:
export const widthPercentageToDP = widthPercent => {
const screenWidth = Dimensions.get('window').width;
// Convert string input to decimal number
const elemWidth = parseFloat(widthPercent);
return PixelRatio.roundToNearestPixel(screenWidth * elemWidth / 100);
};
export const heightPercentageToDP = heightPercent => {
const screenHeight = Dimensions.get('window').height;
// Convert string input to decimal number
const elemHeight = parseFloat(heightPercent);
return PixelRatio.roundToNearestPixel(screenHeight * elemHeight / 100);
};
This thread provides you with a clear example: https://stackoverflow.com/a/35074379/4687359
I followed the tutorial on creating a popup for an add-on in Firefox, and it worked great.
The issue I'm having now is that the popup it creates doesn't change size to fit the content I add to it. Instead, it adds scroll bars.
So, how do I change the size of a Firefox Add-on SDK popup to show all content?
You do have to deal with that yourself.
If you already know the desired size when creating the panel, you can pass the height and width as properties of the object to the Panel() constructor.
After a panel is created, its size can be changed by setting the height and width properties on it.
height and width values are numbers in pixels.
See https://developer.mozilla.org/en-US/Add-ons/SDK/High-Level_APIs/panel for a full documentation of how to use panels.
Though the tutorial and docs never say it, the height and width of a panel always defaults to the same small size.
To change it you can use the height and width parameters for the panel class.
If you want it to change automatically you can use this code:
//index.js
var panel = require("sdk/panel").Panel({
height: 200, //choose your default
width: 200,
contentURL: data.url("popup.html"),
contentScriptFile: data.url("auto_resize_popup.js")
});
panel.port.on("resize", function (size) {
console.log(size);
panel.resize(size.width, size.height);
});
...
//auto_resize_popup.js
var content = document.body;
var size = {};
size.width = content.offsetWidth + 2; //2 extra pixels get rid of scroll bars
size.height = content.offsetHeight + 2;
self.port.emit("resize", size);
Working on allowing the upload of images which can range in a variety of size, then allowing to crop a predefined area of the image for a thumbnail.
The thumbnail size is predefined to 150x150. Using the Jcrop.js tool to select a section of the image.
Problem:
When displaying the uploaded image in a smaller size than the original image by implementing set height/width on the image rendered, then there is a scale factor that comes into play when selecting an area to crop.
You either have to scale down the cropping area proportionately or you have to scale the image in relation to the actual image's size in comparison to its displayed size.
Question:
How do I figure out the scale of the browser displayed image vs. original image? I am currently using the following code to save the image, but how would I take into consideration the scaling?
public static Image CropImage(Image originalImage, int x, int y, int width, int height)
{
var bmp = new Bitmap(width, height);
bmp.SetResolution(originalImage.HorizontalResolution, originalImage.VerticalResolution);
using (var graphic = Graphics.FromImage(bmp))
{
graphic.SmoothingMode = SmoothingMode.AntiAlias;
graphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
graphic.PixelOffsetMode = PixelOffsetMode.HighSpeed;
graphic.DrawImage(originalImage, new Rectangle(0, 0, width, height), x, y, width, height, GraphicsUnit.Pixel);
return bmp;
}
}
Bonus Question:
Another problem I discovered, is that there seems to be no efficient way to transfer the original file's ImageFormat when creating a new Bitmap which creates a ImageFormatMemoryBMP and when you attempt to call Bitmap.Save(memorystream, original rawformat) it will blow up. And bitmap RawFormat has no setter.
So how can you set the format on a new bitmap?
I think perhaps that this problem is solved purely on the front end, no need to use any server side for this.
Jcrop has a built in scale factor handler.
http://deepliquid.com/content/Jcrop_Sizing_Issues.html
Now you can use this in two ways, as I understand it. Either to 'resize' the image for you on the front end using 'box sizing', or you can tell it the 'truesize' of the image and it will work out the scale factor and handle the coordinates for you on it's own.
Box sizing
$('#cropbox').Jcrop({ boxWidth: 450, boxHeight: 400 });
True Size
$.Jcrop('#cropbox',{ trueSize: [500,370] });
Using the true size method you will need to invoke jcrop using the api method:
http://deepliquid.com/content/Jcrop_API.html#API_Invocation_Method
var jcrop_api,
options = { trueSize: [500,370] };
$('#target').Jcrop(options,function(){
jcrop_api = this;
});
Good luck!
I need to find a way to "upsample" text from 72dpi (screen) to 300dpi (print) for rendered client generated text. This is a true WYSIWYG application and we're expecting a ton of traffic so client side rendering is a requirement. Our application has several fonts, font sizes, colors, alignments the user can modify in a textarea. The question is how to convert 72dpi to 300dpi. We have the editior complete, we just need to make 300dpi versions of the textarea.
MY IDEA
1) Get textarea and increase the height, width, and font size by 300/72. (if ints are needed on font size I may need to increase the font then down-sample to the height/width)
2) use BitmapUtil.getSnapshot on the textarea to get a rendered version of the text
THE QUESTION
How can I render text inside of a textarea without the component lifecycle? Imagine:
var textArea:TextArea = new TextArea();
textArea.text = "This is a test";
var bmd:BitmapData = textArea.render();
Like Flextras said, width/height has nothing to do with DPI, unless you actually zoom into the application by 4.16X. If your application all has vector based graphics, it shouldn't be a problem. Plus, the concept of DPI is lost in any web application until you're trying to save/print a bitmap.
It's definitely possible, but you'll have to figure it on your own.
To ask a question another way, it is possible to create a TextArea in
memory which I can use the BitmapUtil.getSnapshot() function to
generate a BitmapData object
Technically, all components are in memory. What you want to do, I believe, is render a component without adding it to a container.
We do exactly this for the watermark on Flextras components. Conceptually we created a method to render the instance; like this:
public function render(argInheritingStyles : Object):void{
this.createChildren();
this.childrenCreated();
this.initializationComplete();
this.inheritingStyles = argInheritingStyles;
this.commitProperties();
this.measure();
this.height = this.measuredHeight;
this.width = this.measuredWidth;
this.updateDisplayList(this.unscaledWidth,this.unscaledHeight);
}
The method must be explicitly called. Then you can use the 'standard' procedure for turning the component into a bitmap. I think we use a Label; but the same approach should work on any given component.
Here is the final method I used to solve the problem of creating a printable version of the text and style of a Spark TextArea component. I ended up placing the custom component TextAreaRenderer (see below) in the MXML and setting the visibility to false. Then using the reference to this component to process any text field (renderObject) and get back a BitmapData object.
public class TextAreaRenderer extends TextArea implements IAssetRenderer
{
public function render(renderObject:Object, dpi:int = 300):BitmapData{
// CAST THE OBJECT
//.................
var userTextArea:TextArea = TextArea(renderObject);
// SCALE IS THE DIVISION OF THE NEW DPI OVER THE SCREEN DPI 72
//............................................................
var scale:Number = dpi / 72;
// COPY THE USER'S TEXT AREA INTO THE OFFSCREEN TEXT AREA
//.......................................................
this.text = userTextArea.text; // the actual text
this.height = Math.floor(userTextArea.height * scale); // scaled height
this.width = Math.floor(userTextArea.width * scale); // scaled width
// GET THE LAYOUT FORMATS AND COPY TO OFFSCREEN
// - the user's format = userTextAreaLayoutFormat
// - the hidden format = thisLayoutFormat
//...............................................
var editableLayoutProperties:Array = ['fontSize', 'fontFamily', 'fontWeight', 'fontStyle', 'textAlign', 'textDecoration', 'color']
userTextArea.selectAll();
var userTextAreaLayoutFormat:TextLayoutFormat = userTextArea.getFormatOfRange();
this.selectAll();
var thisLayoutFormat:TextLayoutFormat = this.getFormatOfRange();
for each(var prop:String in editableLayoutProperties){
thisLayoutFormat[prop] = userTextAreaLayoutFormat[prop];
}
// SCALE THE FONT SIZE
//....................
thisLayoutFormat.fontSize = thisLayoutFormat.fontSize * scale;
// SET THE FORMAT BACK IN THE TEXT BOX
//...................................
this.setFormatOfRange(thisLayoutFormat);
// REDRAW THE OFFSCREEN
// RETURN THE BITMAP DATA
//.......................
this.validateNow();
return BitmapUtil.getSnapshot(this);
}
}
Then calling the TextAreaRenderer after the text area is changed to get a scaled up bitmap.
// COPY THE DATA INTO THE OFFSCREEN COMPONENT
//............................................
var renderableComponent:IAssetRenderer = view.offScreenTextArea;
return renderableComponent.render(userTextArea, 300);
Thanks to the advice from www.Flextras.com for working through the issue with me.
In a drag+drop situation using Flex, I am trying to get the object center aligned to the point of drop- somehow, irrespective of the adjustments to height and width, it is always positioning drop point to left top.
here is the code..
imageX = SkinnableContainer(event.currentTarget).mouseX;
imageY = SkinnableContainer(event.currentTarget).mouseY;
// Error checks if imageX/imageY dont satisfy certain conditions- move to a default position
// img.width and img.height are both defined and traced to be 10- idea to center image to drop point
Image(event.dragInitiator).x = imageX-(img.width)/2;
Image(event.dragInitiator).y = imageY-(img.height)/2
The last 2 lines don't seem to have any effect. Any ideas why-must be something straightforward, that I am missing...
You can use the following snippet:
private function on_drag_start(event:MouseEvent):void
{
var drag_source:DragSource = new DragSource();
var drag_initiator:UIComponent = event.currentTarget as UIComponent;
var thumbnail:Image = new Image();
// Thumbnail initialization code goes here
var offset:Point = this.localToGlobal(new Point(0, 0));
offset.x -= event.stageX;
offset.y -= event.stageY;
DragManager.doDrag(drag_initiator, drag_source, event, thumbnail, offset.x + thumbnail.width / 2, offset.y + thumbnail.height / 2, 1.0);
}
Here is one important detail. The snippet uses stage coordinate system.
If you use event.localX and event.localY, this approach will fail in some cases. For example, you click-and-drag a movie clip. If you use localX and localY instead of stage coordinates, localX and localY will define coordinates in currently clicked part of the movie clip, not in the whole movie clip.
Use the xOffset and yOffset properties in the doDrag method of DragManager.
Look here for an example.