适配完结篇二 - 谷歌小弟的Android多分辨率适配框架

简介: • 切图存放于drawable-nodpi• 抛开系统的dpi并且摒弃dp和sp,统一使用px作为尺寸单位• 按照给定高分辨率(如1920*1080)切图和布局, 其实只有1080px有参考价值• 根据需要, 等比例缩放每个View目前,xxhdpi分辨率的手机占了主流,所以在该框架中采用了drawable-xxhdpi的切图。倘若以后xxxhdpi分辨率的手机占了主导地位,那么就请UI设计师按照该分辨率切图,我们将其放在drawable-nohdpi中,再修改BASE_SCREEN_WIDTH即可。


import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.TextView;
// 版权声明:    https://blog.csdn.net/lfdfhl/article/details/52735103
public class SupportMultipleScreensUtil {
    public static final int BASE_SCREEN_WIDTH = 1080;
    public static float scale = 1.0F;
    private SupportMultipleScreensUtil() {
    }
    public static void init(Context context) {
        Resources resources = context.getResources();
        DisplayMetrics displayMetrics = resources.getDisplayMetrics();
        int widthPixels = displayMetrics.widthPixels;
        scale = (float) widthPixels / BASE_SCREEN_WIDTH;
    }
    public static void scale(View view) {
        if (null != view) {
            if (view instanceof ViewGroup) {
                scaleViewGroup((ViewGroup) view);
            } else {
                scaleView(view);
            }
        }
    }
    public static void scaleViewGroup(ViewGroup viewGroup) {
        for (int i = 0; i < viewGroup.getChildCount(); ++i) {
            View view = viewGroup.getChildAt(i);
            if (view instanceof ViewGroup) {
                scaleViewGroup((ViewGroup) view);
            }
            scaleView(view);
        }
    }
    public static void scaleView(View view) {
        Object isScale = view.getTag(R.id.is_scale_size_tag);
        if (!(isScale instanceof Boolean) || !((Boolean) isScale).booleanValue()) {
            if (view instanceof TextView) {
                scaleTextView((TextView) view);
            } else {
                scaleViewSize(view);
            }
            view.setTag(R.id.is_scale_size_tag, Boolean.valueOf(true));
        }
    }
    // 对于TextView,不但要缩放其尺寸,还需要对其字体进行缩放:
        private static void scaleTextView(TextView textView) {
            if (null != textView) {
                scaleViewSize(textView);
                Object isScale = textView.getTag(R.id.is_scale_font_tag);
                if (!(isScale instanceof Boolean) || !((Boolean) isScale).booleanValue()) {
                    float size = textView.getTextSize();
                    size *= scale;
                    textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, size);
                }
                Drawable[] drawables = textView.getCompoundDrawables();
                Drawable leftDrawable = drawables[0];
                Drawable topDrawable = drawables[1];
                Drawable rightDrawable = drawables[2];
                Drawable bottomDrawable = drawables[3];
                setTextViewCompoundDrawables(textView, leftDrawable, topDrawable, rightDrawable, bottomDrawable);
                int compoundDrawablePadding = getScaleValue(textView.getCompoundDrawablePadding());
                textView.setCompoundDrawablePadding(compoundDrawablePadding);
            }
        }
    /**
     * 等比例缩放: 对每个View的宽高,padding,margin值都按比例缩 放,并且在缩放后重新设置其布局参数。 博客地址:
     */
    private static void scaleViewSize(View view) {
        if (null != view) {
            int paddingLeft = getScaleValue(view.getPaddingLeft());
            int paddingTop = getScaleValue(view.getPaddingTop());
            int paddingRight = getScaleValue(view.getPaddingRight());
            int paddingBottom = getScaleValue(view.getPaddingBottom());
            view.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
            LayoutParams layoutParams = view.getLayoutParams();
            if (null != layoutParams) {
                if (layoutParams.width > 0) {
                    layoutParams.width = getScaleValue(layoutParams.width);
                }
                if (layoutParams.height > 0) {
                    layoutParams.height = getScaleValue(layoutParams.height);
                }
                if (layoutParams instanceof MarginLayoutParams) {
                    MarginLayoutParams marginLayoutParams = (MarginLayoutParams) layoutParams;
                    int topMargin = getScaleValue(marginLayoutParams.topMargin);
                    int leftMargin = getScaleValue(marginLayoutParams.leftMargin);
                    int bottomMargin = getScaleValue(marginLayoutParams.bottomMargin);
                    int rightMargin = getScaleValue(marginLayoutParams.rightMargin);
                    marginLayoutParams.topMargin = topMargin;
                    marginLayoutParams.leftMargin = leftMargin;
                    marginLayoutParams.bottomMargin = bottomMargin;
                    marginLayoutParams.rightMargin = rightMargin;
                }
            }
            view.setLayoutParams(layoutParams);
        }
    }
    private static void setTextViewCompoundDrawables(TextView textView, Drawable leftDrawable, Drawable topDrawable,
            Drawable rightDrawable, Drawable bottomDrawable) {
        if (null != leftDrawable) {
            scaleDrawableBounds(leftDrawable);
        }
        if (null != rightDrawable) {
            scaleDrawableBounds(rightDrawable);
        }
        if (null != topDrawable) {
            scaleDrawableBounds(topDrawable);
        }
        if (null != bottomDrawable) {
            scaleDrawableBounds(bottomDrawable);
        }
        textView.setCompoundDrawables(leftDrawable, topDrawable, rightDrawable, bottomDrawable);
    }
    // 考虑到对TextView的CompoundDrawable进行缩放
    private static Drawable scaleDrawableBounds(Drawable drawable) {
        int right = getScaleValue(drawable.getIntrinsicWidth());
        int bottom = getScaleValue(drawable.getIntrinsicHeight());
        drawable.setBounds(0, 0, right, bottom);
        return drawable;
    }
    private static int getScaleValue(int value) {
        return value <= 4 ? value : (int) Math.ceil((double) (scale * (float) value));
    }
}

图简便, 直接贴了代码, R.id.is_scale_size_tagR.id.is_scale_size_tag报错只需要在\res\values下创建ids.xml文件下定义即可

<?xml version="1.0" encoding="UTF-8"?>
<resources>
  <item type="id" name="test"/>
</resources>


用法

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    View rootView=findViewById(android.R.id.content);
    SupportMultipleScreensUtil.init(getApplication());
    SupportMultipleScreensUtil.scale(rootView);
}


总结


  • 切图存放于drawable-nodpi


  • 抛开系统的dpi并且摒弃dp和sp,统一使用px作为尺寸单位


  • 按照给定高分辨率(如1920*1080)切图和布局, 其实只有1080px有参考价值


  • 根据需要, 等比例缩放每个View


目前,xxhdpi分辨率的手机占了主流,所以在该框架中采用了drawable-xxhdpi的切图。倘若以后xxxhdpi分辨率的手机占了主导地位,那么就请UI设计师按照该分辨率切图,我们将其放在drawable-nohdpi中,再修改BASE_SCREEN_WIDTH即可。


文章来源(References)



Android多分辨率适配框架(1)— 核心基础 - CSDN博客




目录
相关文章
|
3月前
|
物联网 区块链 vr&ar
未来已来:探索区块链、物联网与虚拟现实技术的融合与应用安卓与iOS开发中的跨平台框架选择
【8月更文挑战第30天】在科技的巨轮下,新技术不断涌现,引领着社会进步。本文将聚焦于当前最前沿的技术——区块链、物联网和虚拟现实,探讨它们各自的发展趋势及其在未来可能的应用场景。我们将从这些技术的基本定义出发,逐步深入到它们的相互作用和集成应用,最后展望它们如何共同塑造一个全新的数字生态系统。
|
4月前
|
开发框架 前端开发 Android开发
安卓与iOS开发中的跨平台框架解析
在移动应用开发的广阔舞台上,安卓和iOS一直是两大主角。随着技术的进步,开发者们渴望能有一种方式,让他们的应用能同时在这两大平台上运行,而不必为每一个平台单独编写代码。这就是跨平台框架诞生的背景。本文将探讨几种流行的跨平台框架,包括它们的优势、局限性,以及如何根据项目需求选择合适的框架。我们将从技术的深度和广度两个维度,对这些框架进行比较分析,旨在为开发者提供一个清晰的指南,帮助他们在安卓和iOS的开发旅程中,做出明智的选择。
|
5天前
|
算法 JavaScript Android开发
|
15天前
|
Java 程序员 API
Android|集成 slf4j + logback 作为日志框架
做个简单改造,统一 Android APP 和 Java 后端项目打印日志的体验。
62 1
|
2月前
|
前端开发 Java 数据库
💡Android开发者必看!掌握这5大框架,轻松打造爆款应用不是梦!🏆
在Android开发领域,框架犹如指路明灯,助力开发者加速应用开发并提升品质。本文将介绍五大必备框架:Retrofit简化网络请求,Room优化数据库访问,MVVM架构提高代码可维护性,Dagger 2管理依赖注入,Jetpack Compose革新UI开发。掌握这些框架,助你在竞争激烈的市场中脱颖而出,打造爆款应用。
319 3
|
2月前
|
编译器 Android开发 开发者
带你了解Android Jetpack库中的依赖注入框架:Hilt
本文介绍了Hilt,这是Google为Android开发的依赖注入框架,基于Dagger构建,旨在简化依赖注入过程。Hilt通过自动化的组件和注解减少了DI的样板代码,提高了应用的可测试性和可维护性。文章详细讲解了Hilt的主要概念、基本用法及原理,帮助开发者更好地理解和应用Hilt。
75 8
|
2月前
|
调度 Android开发 UED
Android经典实战之Android 14前台服务适配
本文介绍了在Android 14中适配前台服务的关键步骤与最佳实践,包括指定服务类型、请求权限、优化用户体验及使用WorkManager等。通过遵循这些指南,确保应用在新系统上顺畅运行并提升用户体验。
176 6
|
3月前
|
设计模式 Java Android开发
探索安卓应用开发:从新手到专家的旅程探索iOS开发中的SwiftUI框架
【8月更文挑战第29天】本文旨在通过一个易于理解的旅程比喻,带领读者深入探讨安卓应用开发的各个方面。我们将从基础概念入手,逐步过渡到高级技术,最后讨论如何维护和推广你的应用。无论你是编程新手还是有经验的开发者,这篇文章都将为你提供有价值的见解和实用的代码示例。让我们一起开始这段激动人心的旅程吧!
|
3月前
|
Android开发
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
如何使用Amlogic T972安卓9.0系统上的misc框架来简化驱动程序开发,通过misc框架自动分配设备号并创建设备文件,从而减少代码量并避免设备号冲突。
38 0
基于Amlogic 安卓9.0, 驱动简说(三):使用misc框架,让驱动更简单
|
3月前
|
存储 前端开发 Java
Android MVVM框架详解与应用
在Android开发中,随着应用复杂度的增加,如何有效地组织和管理代码成为了一个重要的问题。MVVM(Model-View-ViewModel)架构模式因其清晰的结构和高效的开发效率,逐渐成为Android开发者们青睐的架构模式之一。本文将详细介绍Android MVVM框架的基本概念、优势、实现流程以及一个实际案例。
下一篇
无影云桌面