├── README.md └── ScreenUtil.js /README.md: -------------------------------------------------------------------------------- 1 | # ReactNativeScreenUtil 2 | ReactNative屏幕工具适配类 3 | 直接导入引用即可.
4 | 新增iPhoneX适配, 让你不用升级ReactNative即可适配iPhoneX.
5 | 此设计类以iPhone6为基准,可自行修改.
6 | 如果各位有更好的适配或者其他适合作为工具的方法,欢迎提issue分享给大家。 7 | 8 | 个人也已经添加了一些其他常用方法,比如判断字符串(对象,数组)是否为空,时间戳转换 , AsyncStorage 的增删改查等, 觉得有的方法用不上可以手动删除,在此只做整理,方便日后使用 9 | 10 | 相关链接: 11 | 12 | 适配iPhoneX的效果及相关方法: http://blog.csdn.net/u011272795/article/details/78592605 13 | 14 | 屏幕适配工具类使用方法: http://blog.csdn.net/u011272795/article/details/73824558 15 | 16 | #### 2018/8/15更新: 17 | 字体适配添加了是否根据手机文字缩放系数来缩放字体,避免在每个text都写相应的设置方法,详情请查看setSptext方法 18 | 19 | #### 2018/8/15更新: 20 | 优化了适配方法setSptext和scaleSize,
21 | 添加了scaleHeight方法,根据不同手机的高度不同来进行适配,使尺寸更加合适
22 | 23 | #### 2018/7/12更新: 24 | 调整了适配方法setSptext和scaleSize,
25 | 最新的屏幕适配方法在android上的效果非常好,iOS未测试,如果iOS上效果不好,请使用最初的版本。
26 | 添加了判断目标是否为空的方法,详情请查阅工具中的isEmpty方法.
27 | -------------------------------------------------------------------------------- /ScreenUtil.js: -------------------------------------------------------------------------------- 1 | /** 2 | * zhuoyuan93@gmail.com 3 | * 屏幕工具类 以及一些常用的工具类封装 4 | * ui设计基准,iphone 6 2倍图 5 | * width:750px 6 | * height:1334px 7 | * @2x 8 | */ 9 | import { 10 | PixelRatio, 11 | Dimensions, 12 | Platform, 13 | AsyncStorage 14 | } from 'react-native'; 15 | 16 | export let screenW = Dimensions.get('window').width; 17 | export let screenH = Dimensions.get('window').height; 18 | const fontScale = PixelRatio.getFontScale(); 19 | export let pixelRatio = PixelRatio.get(); 20 | //像素密度 21 | export const DEFAULT_DENSITY = 2; 22 | //px转换成dp 23 | //以iphone6为基准,如果以其他尺寸为基准的话,请修改下面的defaultWidth和defaultHeight为对应尺寸即可. 以下为1倍图时 24 | const defaultWidth = 375; 25 | const defaultHeight = 667; 26 | const w2 = defaultWidth / DEFAULT_DENSITY; 27 | //px转换成dp 28 | const h2 = defaultHeight / DEFAULT_DENSITY; 29 | 30 | //缩放比例 31 | const _scaleWidth = screenW / defaultWidth; 32 | const _scaleHeight = screenH / defaultHeight; 33 | 34 | // iPhoneX 35 | const X_WIDTH = 375; 36 | const X_HEIGHT = 812; 37 | 38 | /** 39 | * 屏幕适配,缩放size , 默认根据宽度适配,纵向也可以使用此方法 40 | * 横向的尺寸直接使用此方法 41 | * 如:width ,paddingHorizontal ,paddingLeft ,paddingRight ,marginHorizontal ,marginLeft ,marginRight 42 | * @param size 设计图的尺寸 43 | * @returns {number} 44 | */ 45 | export function scaleSize(size: Number) { 46 | return size * _scaleWidth; 47 | } 48 | 49 | /** 50 | * 屏幕适配 , 纵向的尺寸使用此方法应该会更趋近于设计稿 51 | * 如:height ,paddingVertical ,paddingTop ,paddingBottom ,marginVertical ,marginTop ,marginBottom 52 | * @param size 设计图的尺寸 53 | * @returns {number} 54 | */ 55 | export function scaleHeight(size: Number) { 56 | return size * _scaleHeight; 57 | } 58 | 59 | /* 最初版本尺寸适配方案 也许你会更喜欢这个 60 | export function scaleSize(size: Number) { 61 | let scaleWidth = screenW / w2; 62 | let scaleHeight = screenH / h2; 63 | let scale = Math.min(scaleWidth, scaleHeight); 64 | size = Math.round((size * scale + 0.5)); 65 | return size / DEFAULT_DENSITY; 66 | }*/ 67 | 68 | /** 69 | * 设置字体的size(单位px) 70 | * @param size 传入设计稿上的px , allowFontScaling 是否根据设备文字缩放比例调整,默认不会 71 | * @returns {Number} 返回实际sp 72 | */ 73 | function setSpText(size: Number, allowFontScaling = false) { 74 | const scale = Math.min(_scaleWidth, _scaleHeight); 75 | const fontSize = allowFontScaling ? 1 : fontScale; 76 | return size * scale / fontSize; 77 | } 78 | 79 | export function setSpText2(size: Number) { 80 | let scaleWidth = screenW / w2; 81 | let scaleHeight = screenH / h2; 82 | let scale = Math.min(scaleWidth, scaleHeight); 83 | size = Math.round((size * scale + 0.5)); 84 | 85 | return size / DEFAULT_DENSITY * fontScale; 86 | } 87 | 88 | /** 89 | * 判断是否为iphoneX 90 | * @returns {boolean} 91 | */ 92 | export function isIphoneX() { 93 | return ( 94 | Platform.OS === 'ios' && 95 | ((screenH === X_HEIGHT && screenW === X_WIDTH) || 96 | (screenH === X_WIDTH && screenW === X_HEIGHT)) 97 | ) 98 | } 99 | 100 | /** 101 | * 根据是否是iPhoneX返回不同的样式 102 | * @param iphoneXStyle 103 | * @param iosStyle 104 | * @param androidStyle 105 | * @returns {*} 106 | */ 107 | export function ifIphoneX(iphoneXStyle, iosStyle = {}, androidStyle) { 108 | if (isIphoneX()) { 109 | return iphoneXStyle; 110 | } else if (Platform.OS === 'ios') { 111 | return iosStyle 112 | } else { 113 | if (androidStyle) return androidStyle; 114 | return iosStyle 115 | } 116 | } 117 | 118 | 119 | /** 120 | * 判断对象,数组,字符串是否为空 121 | * @param str (null|undefined|''|' '|[]|{}) 均判断为空,返回true 122 | * @returns {boolean} 123 | */ 124 | export function isEmpty(str) { 125 | if (!str) { 126 | return true; 127 | } else if (typeof str === 'object' && Object.keys(str).length === 0) { 128 | return true; 129 | } else if (str.replace(/(^\s*)|(\s*$)/g, "").length === 0) { 130 | return true; 131 | } 132 | return false; 133 | } 134 | 135 | //时间处理 136 | Date.prototype.format = function (format) { 137 | let date = { 138 | "M+": this.getMonth() + 1, 139 | "d+": this.getDate(), 140 | "h+": this.getHours(), 141 | "m+": this.getMinutes(), 142 | "s+": this.getSeconds(), 143 | "q+": Math.floor((this.getMonth() + 3) / 3), 144 | "S+": this.getMilliseconds() 145 | }; 146 | if (/(y+)/i.test(format)) { 147 | format = format.replace(RegExp.$1, (this.getFullYear() + '').substr(4 - RegExp.$1.length)); 148 | } 149 | for (let k in date) { 150 | if (new RegExp("(" + k + ")").test(format)) { 151 | format = format.replace(RegExp.$1, RegExp.$1.length === 1 152 | ? date[k] : ("00" + date[k]).substr(("" + date[k]).length)); 153 | } 154 | } 155 | return format; 156 | }; 157 | 158 | //获取时间差 current:1497235409744 当前时间 start:1497235419744 开始时间 159 | export function getRemainingime(current: Number, start: Number) { 160 | 161 | let time = start - current; 162 | if (time < 0) { 163 | return ["0", "0", "0", "0", "0", "0"]; 164 | } 165 | let year = Math.floor(time / (365 * 30 * 24 * 3600 * 1000));//年 166 | 167 | let month = Math.floor(time / (30 * 24 * 3600 * 1000));//月 168 | 169 | let days = Math.floor(time / (24 * 3600 * 1000));//日 170 | let temp1 = time % (24 * 3600 * 1000); 171 | let temp2 = temp1 % (3600 * 1000); 172 | let minutes = Math.floor(temp2 / (60 * 1000));//分 173 | let hours = Math.floor(temp1 / (3600 * 1000));//时 174 | let temp3 = temp2 % (60 * 1000); 175 | let seconds = Math.round(temp3 / 1000);//秒 176 | 177 | let strs = [year, toNormal(month), toNormal(days), toNormal(hours), toNormal(minutes), toNormal(seconds)]; 178 | return strs;//["0", "0", "2", "7", "33", "30"]0年0月2日 7时33分30秒 179 | } 180 | 181 | //1497235419 182 | export function getRemainingimeDistance(distance: Number) { 183 | let time = distance * 1000; 184 | if (time < 0) { 185 | return ["0", "0", "0", "0", "0", "0"]; 186 | } 187 | 188 | let year = Math.floor(time / (365 * 30 * 24 * 3600 * 1000));//年 189 | 190 | let month = Math.floor(time / (30 * 24 * 3600 * 1000));//月 191 | 192 | let days = Math.floor(time / (24 * 3600 * 1000));//日 193 | let temp1 = time % (24 * 3600 * 1000); 194 | let hours = Math.floor(temp1 / (3600 * 1000));//时 195 | let temp2 = temp1 % (3600 * 1000); 196 | let minutes = Math.floor(temp2 / (60 * 1000));//分 197 | let temp3 = temp2 % (60 * 1000); 198 | let seconds = Math.round(temp3 / 1000);//秒 199 | 200 | let strs = [year, toNormal(month), toNormal(days), toNormal(hours), toNormal(minutes), toNormal(seconds)]; 201 | // strs.splice(0, 1, String(Number(strs[0]) - 1970));//年 202 | // strs.splice(1, 1, String(Number(strs[1]) - 1)); 203 | // strs.splice(2, 1, (Number(strs[2]) - 1) < 10 ? '0' + (Number(strs[2]) - 1) : String(Number(strs[2]) - 1)); 204 | // strs.splice(3, 1, (Number(strs[3]) - 8) < 10 ? '0' + (Number(strs[3]) - 8) : String(Number(strs[3]) - 8)); 205 | // strs.splice(4, 1, Number(strs[4]) < 10 ? '0' + Number(strs[4]) : String(Number(strs[4]))); 206 | // strs.splice(5, 1, Number(strs[5]) < 10 ? '0' + Number(strs[5]) : String(Number(strs[5]))); 207 | return strs;//["0", "0", "2", "7", "33", "30"]0年0月2日 7时33分30秒 208 | } 209 | 210 | export function toNormal(time: Number) { 211 | return time >= 10 ? time : '0' + time; 212 | } 213 | 214 | //转换成日期 215 | export function toDate(timestamp: Number, format1 = 'yyyy-MM-dd hh:mm:ss') { 216 | try { 217 | if (timestamp > 10000) { 218 | let date = new Date(); 219 | date.setTime(timestamp); 220 | return date.format(format1);//2014-07-10 10:21:12 221 | } else { 222 | return ''; 223 | } 224 | } catch (erro) { 225 | return ''; 226 | } 227 | return ''; 228 | } 229 | 230 | //转换成时间搓 231 | export function toTimestamp(date: String) { 232 | let timestamp = Date.parse(date); 233 | return timestamp / 1000; // 1497233827569/1000 234 | } 235 | 236 | //CST时间=>转换成日期yyyy-MM-dd hh:mm:ss 237 | export function getTaskTime(strDate) { 238 | if (null == strDate || "" == strDate) { 239 | return ""; 240 | } 241 | let dateStr = strDate.trim().split(" "); 242 | let strGMT = dateStr[0] + " " + dateStr[1] + " " + dateStr[2] + " " + dateStr[5] + " " + dateStr[3] + " GMT+0800"; 243 | let date = new Date(Date.parse(strGMT)); 244 | let y = date.getFullYear(); 245 | let m = date.getMonth() + 1; 246 | m = m < 10 ? ('0' + m) : m; 247 | let d = date.getDate(); 248 | d = d < 10 ? ('0' + d) : d; 249 | let h = date.getHours(); 250 | let minute = date.getMinutes(); 251 | minute = minute < 10 ? ('0' + minute) : minute; 252 | let second = date.getSeconds(); 253 | second = second < 10 ? ('0' + second) : second; 254 | 255 | return y + "-" + m + "-" + d + " " + h + ":" + minute + ":" + second; 256 | }; 257 | 258 | //1497235419 259 | export function getRemainingimeDistance2(distance: Number) { 260 | let time = distance; 261 | let days = Math.floor(time / (24 * 3600 * 1000)); 262 | let temp1 = time % (24 * 3600 * 1000); 263 | let hours = Math.floor(temp1 / (3600 * 1000)); 264 | let temp2 = temp1 % (3600 * 1000); 265 | let minutes = Math.floor(temp2 / (60 * 1000)); 266 | if (time <= 60 * 1000) { 267 | minutes = 1; 268 | } 269 | let temp3 = temp2 % (60 * 1000); 270 | let seconds = Math.round(temp3 / 1000); 271 | return [hours, minutes];//["0", "0", "2", "7", "33", "30"]0年0月2日 7时33分30秒 272 | } 273 | 274 | 275 | /** 276 | * 存储 277 | * @param key 278 | * @param value 279 | * @param successCallback 280 | * @param errorCallback 281 | */ 282 | export function saveAsyncStorage(key, value, successCallback, errorCallback) { 283 | AsyncStorage.setItem(key, value, error => { 284 | if (error) { 285 | errorCallback(error); 286 | } 287 | else { 288 | successCallback(); 289 | } 290 | }) 291 | } 292 | 293 | /** 294 | * 取值 295 | * @param key 296 | * @param successCallback 297 | * @param errorCallback 298 | */ 299 | export function getAsyncStorage(key, successCallback, errorCallback) { 300 | AsyncStorage.getItem(key, (error, result) => { 301 | if (error) { 302 | errorCallback(error); 303 | } 304 | else { 305 | successCallback(result); 306 | } 307 | }) 308 | } 309 | 310 | /** 311 | * 删除对应key的 312 | * @param key 313 | * @param successCallback 314 | * @param errorCallback 315 | */ 316 | export function removeAsyncStorage(key, successCallback, errorCallback) { 317 | AsyncStorage.getItem(key, error => { 318 | if (error) { 319 | errorCallback(error); 320 | } 321 | else { 322 | successCallback(); 323 | } 324 | }) 325 | } 326 | 327 | // 328 | // // 将当前时间换成时间格式字符串 329 | // var timestamp3 = 1403058804; 330 | // var newDate = new Date(); 331 | // newDate.setTime(timestamp3); 332 | // // Wed Jun 18 2014 333 | // console.log(newDate.toDateString()); 334 | // // 2014-06-18T02:33:24.000Z 335 | // console.log(newDate.toISOString()); 336 | // // 2014-06-18T02:33:24.000Z 337 | // console.log(newDate.toJSON()); 338 | // // 2014年6月18日 339 | // console.log(newDate.toLocaleDateString()); 340 | // // 2014年6月18日 上午10:33:24 341 | // console.log(newDate.toLocaleString()); 342 | // // 上午10:33:24 343 | // console.log(newDate.toLocaleTimeString()); 344 | // // Wed Jun 18 2014 10:33:24 GMT+0800 (中国标准时间) 345 | // console.log(newDate.toString()); 346 | // // 10:33:24 GMT+0800 (中国标准时间) 347 | // console.log(newDate.toTimeString()); 348 | // // Wed, 18 Jun 2014 02:33:24 GMT 349 | // console.log(newDate.toUTCString()); 350 | // // 2014-07-10 10:21:12 351 | // console.log(newDate.format('yyyy-MM-dd h:m:s')) 352 | --------------------------------------------------------------------------------