1. 程式人生 > 其它 >android 仿今日頭條_Android今日頭條UI適配完善版

android 仿今日頭條_Android今日頭條UI適配完善版

技術標籤:android 仿今日頭條今日頭條適配方案在android中旋轉90度後調整寬度和高度

作者:xcheng_
連結:https://www.jianshu.com/p/41930fde7aac

前言

眾所周知 android的碎片化一直困擾著開發者,我們要花很多的時間去做UI適配的工作。主流的適配方案有兩種 1、今日頭條適配 2、smallestWidth適配https://www.jianshu.com/p/a4b8e4c5d9b0。具體的實現點選上述連線檢視。

這裡主要講的是今日頭條的適配方案。他的邏輯很簡單,就是更具設計圖稿的寬度去動態的修改android執行裝置DisplayMetrics的density、scaledDensity、densityDpi。但是今日頭條只是貼出了示例程式碼。執行到正常開發的時候會遇到UI佈局錯亂的問題。主要是因為app在執行過程螢幕旋轉、重力感應、切換字型等因素導致onConfigurationChanged 改變導致的 DisplayMetrics的值被恢復。故在此基礎上做了修改保證執行中的穩定性

原理

通過閱讀原始碼,我們可以得知,density 是 DisplayMetrics 中的成員變數,而 DisplayMetrics 例項通過 Resources#getDisplayMetrics 可以獲得,而Resources通過Activity或者Application的Context獲得。我們只需要包裝Resources物件,重寫其

getDisplayMetrics方法,修改其原始值

packagecom.xcheng.view.autosize;

importandroid.content.res.Resources;
importandroid.util.DisplayMetrics;

/**
*今日頭條的適配方案
*/
publicclassResourcesWrapperextendsResources{
privatefinalAutoSizeautoSize;
privatefloattargetDensity;
privatefloattargetScaledDensity;
privateinttargetDensityDpi;

publicResourcesWrapper(Resourcesresources,AutoSizeautoSize){
super(resources.getAssets(),resources.getDisplayMetrics(),resources.getConfiguration());
this.autoSize=autoSize;
}

@Override
publicDisplayMetricsgetDisplayMetrics(){
DisplayMetricsdisplayMetrics=super.getDisplayMetrics();
initValue(displayMetrics);
autoSize(displayMetrics);
returndisplayMetrics;
}

privatevoidinitValue(DisplayMetricsdisplayMetrics){
if(targetDensity==0){
floatnonCompatDensity=displayMetrics.density;
floatnonCompatScaledDensity=displayMetrics.scaledDensity;
floatdesignSizeInDp=autoSize.designSizeInDp;
if(designSizeInDp>0){
targetDensity=displayMetrics.widthPixels/designSizeInDp;
}else{
targetDensity=displayMetrics.heightPixels/-designSizeInDp;
}
targetScaledDensity=targetDensity*(nonCompatScaledDensity/nonCompatDensity);
targetDensityDpi=(int)(160*targetDensity);
}
}

privatevoidautoSize(DisplayMetricsdisplayMetrics){
displayMetrics.density=targetDensity;
displayMetrics.densityDpi=targetDensityDpi;
if(autoSize.isSupportSp){
displayMetrics.scaledDensity=targetScaledDensity;
}
}
}

AutoSize原始碼

packagecom.xcheng.view.autosize;

/**
*建立時間:2018/11/12
*編寫人:chengxin
*功能描述:適配實體類
*/
publicclassAutoSize{
/**
*預設的設計尺寸
*>0設定寬度
*<0設定高度
*/
publicfinalfloatdesignSizeInDp;
publicfinalbooleanisSupportSp;

/**
*@paramdesignSizeInDp設計寬度貨高度
*@paramisSupportSp是否支援sp
*/
publicAutoSize(floatdesignSizeInDp,booleanisSupportSp){
if(designSizeInDp==0){
thrownewIllegalArgumentException("designSizeInDp==0");
}
this.designSizeInDp=designSizeInDp;
this.isSupportSp=isSupportSp;
}
}

在Activity基類中重寫getResources方法

@Override
publicResourcesgetResources(){
if(mResources==null){
finalAutoSizeautoSize=getAutoSize();
if(autoSize!=null){
mResources=newResourcesWrapper(super.getResources(),autoSize);
}
}
returnmResources!=null?mResources:super.getResources();
}

/**
*子類可重寫適配
**/
@Nullable
protectedAutoSizegetAutoSize(){
returnEasyView.AUTOSIZE;
}

子類activiy根據需要重寫getAutoSize即可,如:
返回null表示不適配

@Nullable
@Override
protectedAutoSizegetAutoSize(){
returnnewAutoSize(360/*設計的寬度dp*/,true);
}

核心程式碼只有這麼多,開發者根據需要提取即可。

tips:

1、該實現核心思想是通過攔截Resources#getDisplayMetrics()方法,讀者可根據其原理自動擴充套件支援 PT、IN、MM。
2、該適配思想最大的優點是穩定性,不會隨著onConfigurationChanged導致其值被恢復為原始值,因為每次呼叫Resources#getDisplayMetrics()都會重新賦值適配(僅為簡單的賦值,不會影響執行效率)。

github地址:https://github.com/xchengDroid/EasyView

推薦

1、Android超級好用的CheckViewhttps://www.jianshu.com/p/c6e57ce563d5
2、Retrofit 最簡潔易用的封裝,優雅的取消請求,不依賴任何第三方框架https://www.jianshu.com/p/aeea4fe91102


●編號427,輸入編號直達本文

●輸入m獲取到文章目錄

推薦↓↓↓

9f8bdc12878cb69180d663ee54b8c846.png

Java程式設計

更多推薦25個技術類公眾微信

涵蓋:程式人生、演算法與資料結構、黑客技術與網路安全、大資料技術、前端開發、Java、Python、Web開發、安卓開發、iOS開發、C/C++、.NET、Linux、資料庫、運維等。