Android屏幕适配一直都是一个让人头疼的问题,到底要怎么做才能让自己那完美无瑕、惊世骇俗的App在各种机型上看起来都那么优雅、清新、脱俗呢?今天要讲的就是开发中自定义View的适配方式,
大家上车,直接走!
现在很多公司UI设计师切图时都只会给出一套图,一般设计标准都是按照市面上主流分辨率(如 1080x1920)。那么这里我们就以1080x1920屏幕分辨率为例,有个需求来了,有个图片需要其宽度为360px,其高度为200px,那么该肿么做呢?这里还不简单?直接设置ImageView 宽度360px,高度200px不就ok了吗!这样真的可行吗?我们一起来看下。
可以看到,当该图片显示在720x1280和1080x1920手机上时,其显示结果完全不一样,图片并没有因为屏幕宽度的变化而自行调整大小。这样就产生了屏幕适配的问题啊!那么该怎样才能让图片在不同手机上显示的效果一致呢?也就是图片的宽高会根据当前屏幕宽高自动适配呢?仔细想想其实主要原因就是屏幕像素不一致嘛!在1080x1920屏幕上显示的效果就是我想要的,那么在720x1280手机上图片的宽高必须得发生变化,但是这个宽高得设置为多少呢?这里就涉及到一点数学知识了,屏幕宽度从1080至720,这里可以设想为屏幕宽度缩小了,那么缩小的倍数就应该是1080/720(scaleX),同理,屏幕高度也缩小了1920/1280(scaleY)倍。既然屏幕宽高缩小了,为了在720x1280手机上显示出在1080x1920手机上相同的效果,图片宽高的缩小倍数就是对应的1080/720、1920/1280。也就是在720x1280手机上图片宽度应该为360/scaleX,高度应该为200/scaleY,上述图片展示效果是以1080x1920分辨率手机为标准,那么这里我们是不是可以得出一个结论:
在某个手机分辨率(这里以STANDART_WIDTH ,STANDART_HEIGHT分别代表宽高)下,控件(其宽高分别为S_WIDTH,S_HEIGHT)展示出了我们想要的效果,要在其他分辨率(这里以WIDTH,HEIGHT代表宽高)手机中也展示出对应的效果,那么该控件(这里宽高分别为C_WIDTH,C_HEIGHT)的宽高应该满足以下关系:
C_WIDTH= WIDTH/STANDART_WIDTH *S_WIDTH
C_HEIGHT = HEIGHT/STANDART_HEIGHT*S_HEIGHT
一般子View都会存在于父容器中,那么这里带给大家解决适配的方式就是自定义父容器。既然已经得出结论,那么就开始写代码了。
这里以继承RelativeLayout自定义View为例。
//这里为什么会集成RelativeLayout呢?在使用RelativeLayout原有特性的前提下,对其中的子View进行适配
public class CustomRelativeLayout extends RelativeLayout {
private int displayMetricsWidth;//当前屏幕的宽度
private int displayMetricsHeight;//当前屏幕的高度
private float scaleX;//屏幕宽度缩放倍数
private float scaleY;//屏幕高度缩放倍数
private boolean flag;//是否已经测量,该变量是个标识,在RelativeLayout中,当子控件不满足父容器分配的宽高大小时,会再次进行测量。
//标准值 这里以UI设计师给的设计标准为准 目前市面上主流分辨率为 1080x1920
public static float STANDARD_WIDTH = 1080f;
public static float STANDARD_HEIGHT = 1920f;
public CustomRelativeLayout(Context context) {
this(context, null);
public CustomRelativeLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
public CustomRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
WindowManager wm = (WindowManager)
context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
//注意:获取屏幕的高度是除了底部虚拟按键栏的高度
wm.getDefaultDisplay().getMetrics(displayMetrics);//忽略Navigationbar高度
//wm.getDefaultDisplay().getRealMetrics(displayMetrics);//获取整个屏幕宽高
displayMetricsWidth= displayMetrics.widthPixels;
displayMetricsHeight= displayMetrics.heightPixels;
scaleX = displayMetricsWidth/STANDARD_WIDTH ;//计算屏幕宽度缩放因子
scaleY = displayMetricsHeight/STANDARD_HEIGHT;//计算屏幕高度缩放因子
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
if(!flag){
//获取子控件个数
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {//遍历子控件,重新设置子控件宽高以及margin
View child = getChildAt(i);
LayoutParams params = (LayoutParams) child.getLayoutParams();
params.width = (int) (scaleX * params.width);
params.height = (int) (scaleY * params.height);
params.leftMargin = (int) (scaleX * params.leftMargin);
params.rightMargin = (int) (scaleX * params.rightMargin);
params.topMargin = (int) (scaleY * params.topMargin);
params.bottomMargin = (int) (scaleY * params.bottomMargin);
flag = true;
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
上述代码就实现了对RelativeLayout中子View宽高设置,不管在什么分辨率手机上,其子View的宽高都可按照标准值范围内设置。这里有人就提出质疑了,为什么要在onMeasure方法中添加以上逻辑呢?在其他地方该不行吗?好!我来告诉你答案!
因为View的宽高大小就是onMeasure方法决定的,在其他地方不能改变View宽高。
那我们来使用下自定义View?
<?xml version="1.0" encoding="utf-8"?>
<CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
<ImageView
android:layout_width="360px"//设置宽度,这里是以1080x1920分辨率为标准,所以控件宽高值必须在标准值范围内
android:layout_height="200px"//设置高度
android:src="@drawable/pika" />
</CustomRelativeLayout>
这样不管显示在何种分辨率手机中,显示效果都会一致,这样也就完成了对不同手机屏幕分辨率适配的问题。效果图这里就不给出了,具体童鞋们可以去手写测试下,还是挺好用的。
今天的文章就到这里啦!我是你们的小佩琪,下期见!由于佩琪水平有限,若文中存在错误,欢迎指正!
import android.content.Context;
import android.util.DisplayMetrics;
import android.view.WindowManager;
public class ScreenAdaptationUtils {
//设计稿的宽高像素
private static ..
为什么要屏幕适配
同一个界面需要在不同尺寸的屏幕上显示,即使屏幕的尺寸一样,密度也可能不一样。导致App的界面元素在不同屏幕尺寸上显示不一致。所以我们让布局,布局组件,资源,用户界面流程,匹配不同屏幕尺寸。
屏幕适配常见方式
布局适配
避免写死控件尺寸,使用wrap_content, match_parent
LinearLayout xxx:layout_weight=“0.5” //线性布局...
例如:my_view.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/person"
android:orientation="vertical"
android:
自定义View中的适配
自定义view中,使用的单位都是px,那如何去适配屏幕呢?获取屏幕宽度px等数据,然后根据这些去设置 view的宽度px,字体的大小
我们可以把想要显示的大小用dp、sp作为单位,然后在代码中通过工具类转换为px
package com.zhy.utils;import android.content.Context;
import android.util.TypedV
最近遇到一个问题是这样的,App一般自己都会有一个UINavigationController,顶部Table
View如果有tableHeader
View如果设置起始位置是(0,0)是在导航栏的下面的,为了更好地UI希望从
屏幕的(0,0)开始,就遇到了上面的这个问题,简单的看一下效果:
一般在UI
ViewController的基类里面加以下代码:
if (IOS7) {
整理并总结自鸿洋的博客:http://blog.csdn.net/lmj623565791/article/details/24252901
一、不重写onMeasure,在res/layout/activity_main.xml中限定view的高度和宽度
com.cctvjiatao.customview01.act.MainActivity.java
* 自定义View 第一课
根据具体情况选择合适的布局,尽可能的优化布局,使其自
适配分辨率。
1.1. 对于左中右布局,使用相对布局,优先布局左右两边并让其靠近父
view边界,中间
view居于两个
view之间填充全部局。
1.2. 对于左中右布局且
view贴在一起使用线性布局
1.3. 对于横向布局且均分(有规律