Amazon Developer

as

Settings
Sign out
Notifications
Alexa
Amazonアプリストア
Ring
AWS
ドキュメント
Support
Contact Us
My Cases
開発
設計と開発
公開
リファレンス
サポート
アクセスいただきありがとうございます。こちらのページは現在英語のみのご用意となっております。順次日本語化を進めてまいりますので、ご理解のほどよろしくお願いいたします。

Density-Independent Pixels

React Native 0.83 on Vega renders in density-independent pixels (dp) by default. This page explains the unit change and how to update layout values, input handling, custom native interfaces, and images in your app. It expands on Step 4.9 of the code migration.

In RN 0.83, layout values, component dimensions, transforms, scroll offsets, and pointer coordinates are all logical dp. Vega converts those logical values to physical pixels once, at the rendering boundary. If your app was tuned against the physical output of RN 0.72, review every numeric layout value before you ship.

About density-independent pixels

A dp is a logical UI unit. Vega maps it to physical pixels using the display scale factor:

physical pixels = dp × scale factor
dp = physical pixels ÷ scale factor

Prior to React Native 0.83, an app with dp rendering disabled drew width: 100 as 100 physical pixels. Starting with React Native 0.83 and beyond, the same value means 100 dp. Vega draws it as 200 physical pixels at a scale factor of 2, or 266 physical pixels at a scale factor of 2.66. This is the main layout impact to evaluate.

The Vega canvas reference size is 960x540 dp, which is a scale factor of 2 on a 1080p display.

What the unit change covers

RN 0.83 applies the dp mapping across the full UI path:

  • Vega scales the final drawing canvas and the damage regions.
  • Window sizes and positions cross the graphics boundary in physical pixels, but stay in dp in your app code.
  • Pointer, touch, resize, window-position, and occlusion events arrive back in React Native as dp.
  • Child windows, pop-ups, modals, texture-cached layers, and virtual surfaces use the same scale.
  • Dimensions and useWindowDimensions() report logical dimensions. PixelRatio.get() reports the ratio of physical pixels to dp.

What the unit change doesn't cover

Two things keep their existing behavior:

  • Bitmap data. dp rendering doesn't scale bitmap data or change image metadata. Image decoders, bitmaps, pixmaps, and textures continue to use physical pixel dimensions.
  • Font scaling. dp rendering doesn't replace accessibility font scaling. Keep using React Native text APIs and fontScale for user-selected text size.

PixelRatio and the DeviceInfo TurboModule

PixelRatio is a React Native JavaScript utility, not a standalone TurboModule. PixelRatio.get() reads Dimensions.get('window').scale. The native DeviceInfo TurboModule supplies width, height, scale, and fontScale to Dimensions.

In RN 0.83, DeviceInfo reports logical window dimensions along with the active physical-pixel-to-dp scale. It also publishes per-surface dimension updates through didUpdateDimensions.

Why Vega uses density-independent pixels

React Native on Android and iOS uses logical units by default. Vega adopts the same default coordinate model for RN 0.83 apps, so geometry behaves the same way on all three targets.

One unit contract now covers standard React Native components, custom native components, TurboModules, third-party libraries, window APIs, rendering, and input events. Your app describes UI geometry in logical units, and Vega converts that geometry at the graphics boundary. UI proportions stay stable across devices with different canvas resolutions, and Scalable UI can select a higher-resolution canvas without a separate pixel layout.

Changes in your app

The following table maps common RN 0.72 patterns to their RN 0.83 behavior.

Pattern in your app RN 0.83 behavior What to do
Numeric length styles and Yoga constants, such as width: 100, margins, padding, borders, and offsets A value of 100 renders as 100 × scaleFactor physical pixels Convert pixel-tuned values with logicalValue = legacyPixelValue ÷ baselineScaleFactor
Flexbox and percentage-based sizing Values stay relative to the logical viewport No unit conversion. Validate the resulting layout.
Hardcoded 1920 × 1080 screen geometry Layout no longer matches the current logical viewport Use useWindowDimensions(), Flexbox, or percentages
Pointer or scroll coordinates divided by PixelRatio.get() Events already arrive in dp Remove the manual division
Custom native component that calls Vega UI APIs Vega UI APIs interpret geometry as dp Pass React Native values through without conversion
One raster asset for every density The compositor upscales an insufficient source Add density variants, or request a larger remote image

Convert pixel-tuned values

Numeric length values are dp in RN 0.83. Convert the values you tuned as physical pixels, using the scale factor of your pre-migration baseline:

logical value = legacy physical-pixel value ÷ baseline scale factor

For an app previously tuned for a scale factor of 2:

// ❌ BEFORE (RN 0.72) — values tuned against physical output
const legacyStyles = StyleSheet.create({
  card: {
    width: 320,
    height: 180,
    borderRadius: 12,
  },
});

// ✅ AFTER (RN 0.83) — same physical size, expressed in dp
const styles = StyleSheet.create({
  card: {
    width: 160,
    height: 90,
    borderRadius: 6,
  },
});

Apply the same conversion to margins, padding, borders, transforms, shadows, animation distances, SVG dimensions, and custom canvas coordinates that you calibrated as physical pixels. Leave a value unchanged when it already came from a density-independent UX specification.

Replace fixed screen dimensions

Hardcoded screen constants no longer describe the logical viewport. Read the dimensions at runtime instead.

// ❌ BEFORE (RN 0.72)
const screenWidth = 1920;
const panelWidth = screenWidth / 3;

// ✅ AFTER (RN 0.83)
function Panel() {
  const {width} = useWindowDimensions();
  return <View style={{width: width / 3, height: '100%'}} />;
}

useWindowDimensions() returns logical dimensions. Don't convert them to physical pixels before you assign React Native styles.

Use logical input coordinates

RN 0.83 reports pointer and touch coordinates in dp:

const {pageX: x, pageY: y} = event.nativeEvent;

Pass these values directly to your layout, gesture, focus, hit-testing, scroll, and animation code. If your app converts a coordinate that already arrives in dp, remove that conversion — otherwise the value is scaled twice.

Keep custom native interfaces in dp

Define custom component and TurboModule geometry as dp at the React Native boundary.

NativeCardModule.setBounds({x, y, width, height}); // All values are dp.

Forward these values unchanged when the native implementation calls Vega window, view, layer, or canvas APIs. Convert with the active scale factor only when you call an API documented in physical pixels, such as a bitmap decoder or a lower-level graphics API. When both units appear in one module, put the unit in the name, for example widthDp and targetWidthPx.

Handle images

Image layout and image data use different units:

  • <Image style={{width, height}}> uses dp.
  • Source bitmap dimensions, decoded image dimensions, row bytes, and texture dimensions use physical pixels.
  • When React Native supplies a preferred logical decode size, the Vega image pipeline multiplies it by the active scale factor before decoding. Don't multiply the <Image> style or the preferred layout size in your own code.
  • A source needs enough physical pixels for its rendered dp size. An image rendered at 320x180 dp at a scale factor of 2 needs at least 640x360 source pixels to avoid upscaling.

Local assets

Provide density variants in the same directory. Metro and React Native select the asset that matches the active density.

assets/
  icon.png
  icon@2x.png
  icon@3x.png
<Image source={require('./assets/icon.png')} style={{width: 48, height: 48}} />

For a fractional density such as 2.66, provide @3x data. React Native selects the next higher-resolution asset instead of upscaling a lower-resolution source. For icons and other non-photographic artwork, prefer SVG.

Migration checklist

To complete the dp migration, work through the following steps:

  1. Upgrade the app to RN 0.83 and remove any RN 0.72 dp experiment flags that duplicate the new default behavior.
  2. Inventory numeric length values, fixed canvas constants such as 1920 and 1080, and any coordinate conversion helpers in your app.
  3. Convert values tuned as physical pixels with logicalValue = legacyPixelValue ÷ baselineScaleFactor, and leave values from a density-independent UX specification unchanged.
  4. Treat pointer, gesture, scroll, resize, and window coordinates reported by RN 0.83 as dp.
  5. Change custom React-Native-to-native geometry contracts to dp, and keep pixel conversion only at documented pixel APIs.
  6. Replace fixed screen dimensions with Flexbox, percentages, Dimensions, or useWindowDimensions().
  7. Add local raster density variants and confirm each image has enough physical pixels for its rendered logical size.
  8. Test the main window, modals, pop-ups, alerts, child windows, scrolling, gestures, focus, accessibility, localization, and right-to-left layouts at each supported density.

External resources


Last updated: Aug 19, 2026