I am contributing to an Open Source Project where I am developing Material design for React Native. I am blocked at work,I am unable to make some UI level enhancements w.r.t. padding, alignment etc.,
This is the Official Spec of Material Design for Drawer-
In the above image, the UNIT of measurement is dp.
But, in my React Native code, I see there is no such units mentioned. Considering it is "react native" I am confused whether it is px or dp.
I even went over the Official Docs of React Native for Style component. I don't see a mention anywhere.
My Code looks like-
const styles = {
touchable: {
paddingHorizontal: 16,
marginVertical: 8,
height: 48
},
item: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
},
icon: {
position: 'relative',
},
value: {
flex: 1,
paddingLeft: 34,
top: 2
},
label: {
top: 2
}
},
Please can you tell me, if this is pixels or dp? And also, is 1px = 1dp?
From the docs:
All dimensions in React Native are unitless, and represent
density-independent pixels. Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions.
So yes, units in React Native are in dp. If you want to convert them to pixels, use PixelRatio.getPixelSizeForLayoutSize()
I share your confusion somewhat, not being able to actively inspect with a developer console as we are used to in the browser.
I am not familiar with the 'dp' unit, but from what I gather width: 1 renders differently on each device depending on the pixel density of the screen (see link). The information in the react-native docs say that 1 would render thicker on screens with high pixel density. Which then sounds logical as you have more precision on high density screens than you would have on low density screens and react-native aims at being universal so it would not assume high dpi.
It is my understanding that you can use the below linked PixelRatio API to calculate sizes for detail elements (think borders, icons, etc), that way you can dynamically adjust the rendered size according to the device's screen density.
https://facebook.github.io/react-native/docs/pixelratio.html#content
It is the pixel ratio that you have to consider. pixel represents an absolute value. pixel ratio is a relative value. to make app screen and components responsive you have to use pixel ratio.
i have been using in multiple apps already. and i think that is how you have to do it. hope this answers your question.
From what I know, the javascript styling that we use in react js or react native uses pixels. Pixel ratio is only needed to support different size of mobile device screens.
Related
I thought like if I give width: 10, it will look the same in all devices since it occupied the same amount of area (because in 160dpi, 10dp = 10px, 320dpi 10dp = 20px but occupies same area in an inch)).I think my understanding is wrong. Share your thoughts on Responsive design and how to approach responsive font size as well. Thanks.
Ive been through this phase , and thought similiar , but i was wrong. Sizes are different on different mobile so the best appraoch would be to actually calculate and make it in a percentage.
react-native-responsive this is the library i use for actually making my app responsive and it worked out well. All you need is actually know your testing device height and width , suppose its 360*640.
Now you want to apply height of 200 , so basically you do 200/640 , i.e 31.25 ,
so in your view or whatever image you want you can add height by height:hp('31.25%'), and thats it, it adjust accordingly to devices.
And if you dont want to use any library , you can use Dimensions of react native.
import {Dimensions} from 'react-native';
var {deviceheight, devicewidth} = Dimensions.get('window');
Now similiar approach , you now need to know resolution of your testing device and if its 360 * 640 , then you can do the same , just here suppose again height is 200 , then you have to do height:0.3125*deviceheight
Hope it helps. feel free for doubts
In width: 10,, 10 is equivalent to 10 units. So in such cases, it will always set the with to 10 pixels, no matter which device/screen you use.
Instead, you can use percentage or relative measurements so that it can adapt to different devices, therefore, making your elements 'responsive'
I am currently coding a android application using flutter, dart. I have a settings page that gives the user the ability to change theme. I have created 7 identical Raw Material Button in the shape of a circle. I have been reading around the best way to size the circle base on the users resolution/dpi.
themeButton.dart:
final _themeColour;
final VoidCallback _onPressed;
ThemeButton(this._themeColour, this._onPressed);
#override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
double ratio = width/height;
return RawMaterialButton (
shape: CircleBorder(),
fillColor: _themeColour,
elevation: 0.0,
highlightElevation: 0.0,
onPressed: () => _onPressed(),
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
constraints: BoxConstraints(minHeight: width * ratio * 0.2),
);
}
At the moment I currently take the users device width and then size the button from that. When I try to look this up, everywhere talks about Pixel Density, however we I tried to use the dpi value as a multiplier the circles were extremely large on high dpi devices.
Using the device width works to a certain extent, however I would like to know if there is a preferred standard to completing this task.
Flutter handles high dpi automatically for you; see the devicePixelRatio documentation.
Multiplying by DPI will do it twice (which is why you're seeing them be larger on high dpi devices), whereas if you just set a width that happens automatically. What doesn't happen automatically is resizing to different aspect ratios, but it seems as though you've already come up with a solution to that. I'm not sure if there's anything else you're trying to do that doesn't accomplish - let me know and maybe I can help.
For anyone else dealing with a problem like this, the flutter wiki has an entry that might be helpful.
I was wondering if there is a conscious intention of using even numbers for measurement units when building Android layouts. For example in the Android desgin guidelines there are always multiple of 2 being used as I could see, at least I don't remember Google ever using 3, 5 or so for padding/margin, is there an official reference talking about this somewhere so I could strongly argument that using uneven numbers is wrong?
It is just a coincidence that material design has even numbers for their dp measurements. As you can see here it is not a rule, just a coincidence. Typography has some examples of odd measurements:
Subheading
English: Regular 16sp (device), 15sp (desktop)
Dense: Regular 17sp (device), 16sp (desktop)
Tall: Regular 17sp (device), 16sp (desktop)
Generally, sizes are increased exponentially rather than linearly. Or atleast differences between subsequent sizes increases. (Because human brains think logarithmically instead of linearly: Why In Our Brains The Midpoint Of 1 And 9 Might Be 3)
Like 2dp, 4dp, 8dp, or 160, 240, 320, 480, 640(Image scaling)
So if you start with a 2, you'll get all even numbers but if you start with a 1 or 5, you'll get odd numbers as well.
It could just as well have been 5, 10, 25, 50.
Boostrap has some odd measurements:
#padding-small-vertical: 5px;
#padding-small-horizontal: 10px;
#padding-xs-vertical: 1px;
#padding-xs-horizontal: 5px;
But even here the exponential growth is visible.
When using fancyBox, whether its an image or an iFrame (YouTube), and open this on a mobile device and then rotate (landscape to portrait or vice versa), fancyBox doesn't scale or fit to width of device window?
fancyBox Options:
$(document).ready(function() {
$(".fancybox").fancybox({
helpers : {
media: true,
title: null
},
width : 800,
height : 450,
aspectRatio : true,
scrolling : 'no',
openEffect : 'fade',
closeEffect : 'fade'
});
});
Device: SAM GALXY S3
OS: ANDROID 4.2
Browser: FF / CHRME / DOLPHIN
fancyBox version: 2.1.5 PACK
p.s. this is happening also on the examples, both versions 2 and beta! :/
Your code appears to be setting a static width and height value for your fancy box. That's not a bad thing to do, but it does explain why your fancybox is not fitting the device screen: mobile devices tend to be less than 800px in width.
To fix this, you can easily use css styles to set max-widths for fancybox classes "fancybox-wrap" and "fancybox-inner".
Example:
.fancybox-wrap{max-width: 95%!important;}
.fancybox-inner {max-width: 100%!important;}
These rules use !important because they need to be able to overwrite the html width/height set by the fancybox options.
You can easily set the same styles using a jquery function to set css styles in fancybox's afterLoad option (though there may be more efficient methods to use than afterLoad, it should still get the job done.)
I have added a view to my app defined as follows:
Ti.UI.createView({
top: 0,
left: 0,
width: '50%'
height: '460dp',
backgroundColor: 'red'
});
What I want to find out is whether the above view fits on the screen. I.e. whether the user's screen is tall enough to totally display my entire view. I tried it in the following way:
function getPixels(dp) {
return (dp + (Ti.Platform.displayCaps.dpi / 160));
}
alert(460); // 920
alert(Ti.Platform.displayCaps.platformHeight); // 1136
Which seems about right on the iphone simulator. However when running that exact same code on my android device I get the result:
screenheight: 1200
height of the view: 690
Which doesn't seem correct, because the view with the red background takes almost as much space on the iphone simulator as on my android device.
Is there any way to get consistent results on all devices (ios and android). Or is there some other way to solve my problem?
If you are trying to support all sizes, why don't you set your height to a % value as well?
In answer to your question, the main thing you need to consider is thatTi.Platform.displayCaps.platformHeight returns values in platform-specific units; so pixels on Android and density-independent pixels (dip) on iOS. Since you are setting your view height with density independent pixels, you instead want to convert these platform units to density independent and platform independent units.
I usually just use the measurement library provided by Titanium and Alloy.
var measurement = require('alloy/measurement');
var dpHeight = measurement.pxToDP(Ti.Platform.displayCaps.platformHeight);
if(460 < dpHeight) {
alert('Fits');
} else {
alert("does not fit');
}
But really I find it much easier to just use relative layouts with percentage values.
Another way to figure out if the view is in bounds (after the fact) is to just add a postlayout event listener, when this event is fired it means layout bounds have been calculated in system units and are now accesible:
view.addEventListener('postlayout', function(e) {
if(view.rect.height + view.rect.y > Ti.Platform.displayCaps.platformHeight) {
alert('Does not fit")
}
});
To get constant results of width and height properties between platforms you have to add
<property name="ti.ui.defaultunit" type="string">dip</property>
to tiapp.xml and provide sizes as plain numbers:
Ti.UI.createView({
top: 0,
left: 0,
width: 50,
height: 460,
});