当前位置: 首页 > java >正文

Android屏幕适配利器:Kotlin动态尺寸计算工具类完整封装

Kotlin 动态计算尺寸工具类封装

以下是使用 Kotlin 实现的动态计算尺寸工具类,包含基础版和增强版功能。

1. 基础工具类封装

import android.content.Context
import android.util.DisplayMetrics
import android.view.View
import android.view.ViewGroupobject ViewSizeUtils {/*** 按屏幕宽度百分比设置View的宽度* @param view 需要设置的View* @param widthPercent 宽度百分比 (0.0 - 1.0)*/fun setWidthByScreenPercent(view: View, widthPercent: Float) {if (widthPercent <= 0 || widthPercent > 1) returnval displayMetrics = getDisplayMetrics(view.context)view.updateLayoutParams {width = (displayMetrics.widthPixels * widthPercent).toInt()}}/*** 按屏幕高度百分比设置View的高度* @param view 需要设置的View* @param heightPercent 高度百分比 (0.0 - 1.0)*/fun setHeightByScreenPercent(view: View, heightPercent: Float) {if (heightPercent <= 0 || heightPercent > 1) returnval displayMetrics = getDisplayMetrics(view.context)view.updateLayoutParams {height = (displayMetrics.heightPixels * heightPercent).toInt()}}/*** 按屏幕宽高百分比同时设置View的宽高* @param view 需要设置的View* @param widthPercent 宽度百分比 (0.0 - 1.0)* @param heightPercent 高度百分比 (0.0 - 1.0)*/fun setSizeByScreenPercent(view: View, widthPercent: Float, heightPercent: Float) {if (widthPercent <= 0 || widthPercent > 1 || heightPercent <= 0 || heightPercent > 1) returnval displayMetrics = getDisplayMetrics(view.context)view.updateLayoutParams {width = (displayMetrics.widthPixels * widthPercent).toInt()height = (displayMetrics.heightPixels * heightPercent).toInt()}}/*** 按父容器宽度百分比设置View的宽度* @param view 需要设置的View* @param widthPercent 宽度百分比 (0.0 - 1.0)*/fun setWidthByParentPercent(view: View, widthPercent: Float) {if (widthPercent <= 0 || widthPercent > 1 || view.parent !is View) returnval parent = view.parent as Viewval parentWidth = parent.widthif (parentWidth <= 0) {parent.post {setViewWidth(view, (parent.width * widthPercent).toInt())}} else {setViewWidth(view, (parentWidth * widthPercent).toInt())}}private fun setViewWidth(view: View, width: Int) {view.updateLayoutParams {this.width = width}}private fun getDisplayMetrics(context: Context): DisplayMetrics {return context.resources.displayMetrics}private inline fun View.updateLayoutParams(block: ViewGroup.LayoutParams.() -> Unit) {val params = layoutParams ?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT).also { layoutParams = it }params.block()layoutParams = params}
}

2. 增强版工具类(支持更多功能)

import android.content.Context
import android.view.View
import android.view.ViewGroup
import kotlin.math.roundToIntobject ViewSizeHelper {/*** 设置View的宽高比(基于宽度计算高度)* @param view 目标View* @param aspectRatio 宽高比(宽度/高度)*/fun setAspectRatio(view: View, aspectRatio: Float) {if (aspectRatio <= 0) returnview.addOnLayoutChangeListener(object : View.OnLayoutChangeListener {override fun onLayoutChange(v: View,left: Int, top: Int, right: Int, bottom: Int,oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {val width = right - leftif (width > 0) {v.updateLayoutParams {height = (width / aspectRatio).roundToInt()}v.removeOnLayoutChangeListener(this)}}})}/*** 设置View的最小高度(单位:dp)*/fun setMinHeightDp(view: View, minHeightDp: Int) {view.minimumHeight = dpToPx(view.context, minHeightDp)}/*** 设置View的最小宽度(单位:dp)*/fun setMinWidthDp(view: View, minWidthDp: Int) {view.minimumWidth = dpToPx(view.context, minWidthDp)}/*** 设置View的固定尺寸(单位:dp)*/fun setFixedSizeDp(view: View, widthDp: Int, heightDp: Int) {view.updateLayoutParams {width = dpToPx(view.context, widthDp)height = dpToPx(view.context, heightDp)}}/*** 设置View的宽度(单位:dp)*/fun setWidthDp(view: View, widthDp: Int) {view.updateLayoutParams {width = dpToPx(view.context, widthDp)}}/*** 设置View的高度(单位:dp)*/fun setHeightDp(view: View, heightDp: Int) {view.updateLayoutParams {height = dpToPx(view.context, heightDp)}}/*** 设置View的margin(单位:dp)*/fun setMarginsDp(view: View,leftDp: Int = Int.MIN_VALUE,topDp: Int = Int.MIN_VALUE,rightDp: Int = Int.MIN_VALUE,bottomDp: Int = Int.MIN_VALUE) {val params = view.layoutParams as? ViewGroup.MarginLayoutParams ?: returnif (leftDp != Int.MIN_VALUE) params.leftMargin = dpToPx(view.context, leftDp)if (topDp != Int.MIN_VALUE) params.topMargin = dpToPx(view.context, topDp)if (rightDp != Int.MIN_VALUE) params.rightMargin = dpToPx(view.context, rightDp)if (bottomDp != Int.MIN_VALUE) params.bottomMargin = dpToPx(view.context, bottomDp)view.layoutParams = params}private fun dpToPx(context: Context, dp: Int): Int {return (dp * context.resources.displayMetrics.density).roundToInt()}private inline fun View.updateLayoutParams(block: ViewGroup.LayoutParams.() -> Unit) {val params = layoutParams ?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT).also { layoutParams = it }params.block()layoutParams = params}
}

3. 扩展函数版本(更 Kotlin 化的实现)

import android.content.Context
import android.util.DisplayMetrics
import android.view.View
import android.view.ViewGroup
import kotlin.math.roundToInt// 扩展属性:获取屏幕宽度
val Context.screenWidth: Intget() = resources.displayMetrics.widthPixels// 扩展属性:获取屏幕高度
val Context.screenHeight: Intget() = resources.displayMetrics.heightPixels// 扩展函数:dp转px
fun Context.dpToPx(dp: Int): Int = (dp * resources.displayMetrics.density).roundToInt()// 扩展函数:更新LayoutParams
inline fun View.updateLayoutParams(block: ViewGroup.LayoutParams.() -> Unit) {val params = layoutParams ?: ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT).also { layoutParams = it }params.block()layoutParams = params
}// 基础功能扩展函数
fun View.setWidthByScreenPercent(widthPercent: Float) {if (widthPercent <= 0 || widthPercent > 1) returnupdateLayoutParams {width = (context.screenWidth * widthPercent).toInt()}
}fun View.setHeightByScreenPercent(heightPercent: Float) {if (heightPercent <= 0 || heightPercent > 1) returnupdateLayoutParams {height = (context.screenHeight * heightPercent).toInt()}
}fun View.setSizeByScreenPercent(widthPercent: Float, heightPercent: Float) {if (widthPercent <= 0 || widthPercent > 1 || heightPercent <= 0 || heightPercent > 1) returnupdateLayoutParams {width = (context.screenWidth * widthPercent).toInt()height = (context.screenHeight * heightPercent).toInt()}
}// 增强功能扩展函数
fun View.setAspectRatio(aspectRatio: Float) {if (aspectRatio <= 0) returnaddOnLayoutChangeListener(object : View.OnLayoutChangeListener {override fun onLayoutChange(v: View,left: Int, top: Int, right: Int, bottom: Int,oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {val width = right - leftif (width > 0) {v.updateLayoutParams {height = (width / aspectRatio).roundToInt()}v.removeOnLayoutChangeListener(this)}}})
}fun View.setMinHeightDp(minHeightDp: Int) {minimumHeight = context.dpToPx(minHeightDp)
}fun View.setMinWidthDp(minWidthDp: Int) {minimumWidth = context.dpToPx(minWidthDp)
}fun View.setFixedSizeDp(widthDp: Int, heightDp: Int) {updateLayoutParams {width = context.dpToPx(widthDp)height = context.dpToPx(heightDp)}
}

4. 使用示例

基础工具类使用

// 设置按钮宽度为屏幕的50%
ViewSizeUtils.setWidthByScreenPercent(myButton, 0.5f)// 设置图片高度为屏幕的30%
ViewSizeUtils.setHeightByScreenPercent(myImageView, 0.3f)// 设置TextView宽高分别为屏幕的80%和20%
ViewSizeUtils.setSizeByScreenPercent(myTextView, 0.8f, 0.2f)// 设置RecyclerView宽度为父容器的70%
ViewSizeUtils.setWidthByParentPercent(recyclerView, 0.7f)

增强工具类使用

// 设置图片16:9的宽高比
ViewSizeHelper.setAspectRatio(myImageView, 16f/9f)// 设置按钮最小高度为48dp
ViewSizeHelper.setMinHeightDp(myButton, 48)// 设置固定尺寸为100dp×50dp
ViewSizeHelper.setFixedSizeDp(iconView, 100, 50)// 设置margin
ViewSizeHelper.setMarginsDp(view = myView,leftDp = 16,topDp = 8,rightDp = 16,bottomDp = 8
)

扩展函数版本使用

// 使用扩展函数更简洁
myButton.setWidthByScreenPercent(0.5f)
myImageView.setHeightByScreenPercent(0.3f)
myTextView.setSizeByScreenPercent(0.8f, 0.2f)// 设置宽高比
myVideoView.setAspectRatio(16f/9f)// 设置最小尺寸
floatingButton.setMinWidthDp(48)
floatingButton.setMinHeightDp(48)// 设置固定尺寸
iconView.setFixedSizeDp(100, 50)

这些 Kotlin 实现充分利用了语言特性,如扩展函数、属性、lambda 表达式等,使代码更加简洁易用。根据项目需求,可以选择工具类形式或扩展函数形式来实现动态尺寸计算。

http://www.xdnf.cn/news/8359.html

相关文章:

  • C++高频面试考点 -- 智能指针
  • Dify1.RAG学习(未完待续)
  • 2025电工杯A题电工杯数学建模思路代码文章教学:光伏电站发电功率日前预测问题
  • 从乳制品行业转型看智能化升级新机遇——兼谈R²AIN SUITE的赋能实践
  • 关于flutter中Scaffold.of(context).openEndDrawer();不生效问题
  • Git全流程操作指南
  • 《Cesium全生态解析:从入门到精通的3D地理空间开发指南》
  • Flink集成资源管理器
  • 数据可视化利器 - Grafana 与 Prometheus 联手打造监控仪表盘
  • HTTP 与 HTTPS 深度解析:原理、实践与大型项目应用
  • 【昇腾开发者训练营:Dify大模型部署实战】MindIE + Dify + DeepSeek + Embedding模型 + Rerank模型
  • 跟Gemini制作PPT:图标的搜索
  • 静默战场:eBay瑞士站如何用“黄金用户”策略改写跨境电商价值逻辑
  • 怎么判断一个Android APP使用了Cocos 这个跨端框架
  • 图解深度学习 - 人工智能、机器学习和深度学习
  • 如何设置名称服务器
  • 字节跳动旗下火山引擎都覆盖哪些领域
  • IP 地址反向解析(IP反查域名)的原理详解
  • 【黑马JavaWeb+AI知识梳理】后端Web基础03 - MySQL概述
  • Mybatis-入门程序、 数据库连接池、XML映射配置文件、MybatisX
  • springboot集成日志配置文件
  • rac-rac dg 用role自动启动service
  • 青少年编程与数学 02-020 C#程序设计基础 03课题、开始编程
  • 【Python正则表达式终极指南】从零到工程级实战
  • Spring Boot与Kafka集成实践:从入门到精通
  • AOP的代理模式
  • 非关系型数据库NoSQL
  • CMA软件实验室体系建设中的测试方法部分
  • 【计网】五六章习题测试
  • arcgis js统计FeatureLayer的椭球面积、平面面积