Skip to content

Instantly share code, notes, and snippets.

@slaviboy
Created March 13, 2022 14:35
Show Gist options
  • Save slaviboy/a640477c6e02c5f92b947feace45f5b6 to your computer and use it in GitHub Desktop.
Save slaviboy/a640477c6e02c5f92b947feace45f5b6 to your computer and use it in GitHub Desktop.
Use device width and height as percentage units for Jetpack Compose
package com.slaviboy.e_commerce_app_ui_compose.ui.theme
import android.app.Activity
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.ExperimentalUnitApi
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.window.layout.WindowMetricsCalculator
import com.slaviboy.e_commerce_app_ui_compose.MainActivity
// scale factors that are used when we want to scale all composable for landscape or tablets
var ScaleFactor = 1f
var ActualScaleFactor = 1f
// device width, height as px
var DeviceWidth = 0f
var DeviceHeight = 0f
// density and scale density to convert from px to sp, dp
var Density = 0f
var ScaleDensity = 0f
inline val Number.PxToSp get() = this.toFloat() / ScaleDensity
inline val Number.SpToPx get() = this.toFloat() * ScaleDensity
inline val Number.PxToDp get() = this.toFloat() / Density
inline val Number.DpToPx get() = this.toFloat() * Density
fun Activity.initSize() {
WindowMetricsCalculator
.getOrCreate()
.computeCurrentWindowMetrics(this)
.bounds.let {
DeviceWidth = it.width().toFloat()
DeviceHeight = it.height().toFloat()
}
Density = this.resources.displayMetrics.density
ScaleDensity = this.resources.displayMetrics.scaledDensity
}
/**
* The actual device width, so when phone is rotated in landscape mode it uses the
* bigger side as width, and when phone is in portrait mode it uses the smalled side as width
*/
inline val Number.adw: Dp
get() = Dp(value = (ActualScaleFactor * this.toFloat() * DeviceWidth).PxToDp)
/**
* The actual device height, so when phone is rotated in landscape mode it uses the
* bigger side as height, and when phone is in portrait mode it uses the smalled side as height
*/
inline val Number.adh: Dp
get() = Dp(value = (ActualScaleFactor * this.toFloat() * DeviceHeight).PxToDp)
/**
* This extension method converts a double value set as percentage of device width to Dp object
* @example (0.1.dw) 10% of the device width
*/
inline val Number.dw: Dp
get() = Dp(value = (ScaleFactor * this.toFloat() * Math.min(DeviceWidth, DeviceHeight)).PxToDp)
/**
* This extension method converts a double value set as percentage of device height to Dp object
* @example (0.1.dh) 10% of the device height
*/
inline val Number.dh: Dp
get() = Dp(value = (ScaleFactor * this.toFloat() * Math.max(DeviceWidth, DeviceHeight)).PxToDp)
/**
* This extension method converts a double value set as percentage of device width to TextUnit object
* @example (0.1.sw) 10% of the device width
*/
@OptIn(ExperimentalUnitApi::class)
inline val Double.sw: TextUnit
get() = TextUnit((ScaleFactor * this.toFloat() * Math.min(DeviceWidth, DeviceHeight)).PxToSp, TextUnitType.Sp)
/**
* This extension method converts a double value set as percentage of device width to TextUnit object
* @example (0.1.sh) 10% of the device height
*/
@OptIn(ExperimentalUnitApi::class)
inline val Double.sh: TextUnit
get() = TextUnit((ScaleFactor * this.toFloat() * Math.min(DeviceWidth, DeviceHeight)).PxToSp, TextUnitType.Sp)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment