对于wrap_content形式的宽高,App需要测量它们的实际长度,需要测量的实体主要有3种:
(1)文本尺寸测量文本尺寸分为文本的宽度和高度,需根据文本大小分别计算。
(2)图形尺寸测量如果图形是Bitmap格式,就调用getWidth和getHeight方法;如果图形是Drawable格式,就调用getIntrinsicWidth和getIntrinsicHeight方法。
(3)布局尺寸测量调用measure方法按照测量规格进行测量操
===========================================================================================
文本尺寸的测量
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:padding="5dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp" >
<TextView
android:id="@+id/tv_size"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:gravity="center"
android:text="字体大小:"
android:textColor="@color/black"
android:textSize="17sp" />
<Spinner
android:id="@+id/sp_size"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="@+id/tv_size"
android:gravity="left|center"
android:spinnerMode="dialog" />
</RelativeLayout>
<TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/tv_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="10dp"
android:gravity="center"
android:text="每逢佳节倍思亲"
android:textColor="@color/black" />
</LinearLayout>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="40dp"
android:singleLine="true"
android:gravity="center"
android:textSize="17sp"
android:textColor="#0000ff" />
代码:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
import com.example.myapplication.util.MeasureUtil;
public class MainActivity extends AppCompatActivity
{
private TextView tv_desc, tv_text;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv_desc = findViewById(R.id.tv_desc);
tv_text = findViewById(R.id.tv_text);
initSizeSpinner(); // 初始化文字大小的下拉框
}
// 初始化文字大小的下拉框
private void initSizeSpinner()
{
ArrayAdapter<String> sizeAdapter = new ArrayAdapter<String>(this, R.layout.item_select, descArray);
Spinner sp_size = findViewById(R.id.sp_size);
sp_size.setPrompt("请选择文字大小");
sp_size.setAdapter(sizeAdapter);
sp_size.setOnItemSelectedListener(new SizeSelectedListener());
sp_size.setSelection(0);
}
private String[] descArray = {"12sp", "15sp", "17sp", "20sp", "22sp", "25sp", "27sp", "30sp"};
private int[] sizeArray = {12, 15, 17, 20, 22, 25, 27, 30};
class SizeSelectedListener implements AdapterView.OnItemSelectedListener
{
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3)
{
String text = tv_text.getText().toString();
int textSize = sizeArray[arg2];
tv_text.setTextSize(TypedValue.COMPLEX_UNIT_SP, textSize);
// 计算获取指定文本的宽度(其实就是长度)
int width = (int) MeasureUtil.getTextWidth(text, textSize);
// 计算获取指定文本的高度
int height = (int) MeasureUtil.getTextHeight(text, textSize);
String desc = String.format("下面文字的宽度是%d,高度是%d", width, height);
tv_desc.setText(desc);
}
public void onNothingSelected(AdapterView<?> arg0) {}
}
}
MeasureUtil
package com.example.myapplication.util;
import android.app.Activity;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.text.TextUtils;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
public class MeasureUtil
{
// 获取指定文本的宽度(其实就是长度)
public static float getTextWidth(String text, float textSize)
{
if (TextUtils.isEmpty(text))
{
return 0;
}
Paint paint = new Paint(); // 创建一个画笔对象
paint.setTextSize(textSize); // 设置画笔的文本大小
return paint.measureText(text); // 利用画笔丈量指定文本的宽度
}
// 获取指定文本的高度
public static float getTextHeight(String text, float textSize)
{
Paint paint = new Paint(); // 创建一个画笔对象
paint.setTextSize(textSize); // 设置画笔的文本大小
FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
return fm.descent - fm.ascent; // 返回文本自身的高度
//return fm.bottom - fm.top + fm.leading; // 返回文本所在行的行高
}
// 根据资源编号获得线性布局的实际高度(页面来源)
public static float getRealHeight(Activity act, int resid)
{
LinearLayout llayout = act.findViewById(resid);
return getRealHeight(llayout);
}
// 根据资源编号获得线性布局的实际高度(视图来源)
public static float getRealHeight(View parent, int resid)
{
LinearLayout llayout = parent.findViewById(resid);
return getRealHeight(llayout);
}
// 计算指定线性布局的实际高度
public static float getRealHeight(View child)
{
LinearLayout llayout = (LinearLayout) child;
// 获得线性布局的布局参数
LayoutParams params = llayout.getLayoutParams();
if (params == null)
{
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
// 获得布局参数里面的宽度规格
int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
int htSpec;
if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
// 按照精确数值的情况计算高度规格
htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
} else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
// 按照不确定的情况计算高度规则
htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
// 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
return llayout.getMeasuredHeight();
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<include layout="@layout/drag_drop_header" />
<TextView
android:id="@+id/tv_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:gravity="left"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#eeeeee"
android:gravity="center_horizontal"
android:orientation="vertical"
android:paddingBottom="15dp"
android:paddingTop="15dp" >
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_header" />
<LinearLayout
android:id="@+id/ll_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ImageView
android:id="@+id/iv_arrow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:src="@drawable/ic_arrow" />
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:gravity="center_horizontal"
android:orientation="vertical" >
<TextView
android:id="@+id/tv_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="轻轻下拉,刷新精彩..."
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
代码:
package com.example.myapplication;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.example.myapplication.util.MeasureUtil;
public class MainActivity extends AppCompatActivity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout ll_header = findViewById(R.id.ll_header);
TextView tv_desc = findViewById(R.id.tv_desc);
// 计算获取线性布局的实际高度
float height = MeasureUtil.getRealHeight(ll_header);
String desc = String.format("上面下拉刷新头部的高度是%f", height);
tv_desc.setText(desc);
}
}
MeasureUtil
package com.example.myapplication.util;
import android.app.Activity;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.text.TextUtils;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
public class MeasureUtil
{
// 获取指定文本的宽度(其实就是长度)
public static float getTextWidth(String text, float textSize)
{
if (TextUtils.isEmpty(text))
{
return 0;
}
Paint paint = new Paint(); // 创建一个画笔对象
paint.setTextSize(textSize); // 设置画笔的文本大小
return paint.measureText(text); // 利用画笔丈量指定文本的宽度
}
// 获取指定文本的高度
public static float getTextHeight(String text, float textSize)
{
Paint paint = new Paint(); // 创建一个画笔对象
paint.setTextSize(textSize); // 设置画笔的文本大小
FontMetrics fm = paint.getFontMetrics(); // 获取画笔默认字体的度量衡
return fm.descent - fm.ascent; // 返回文本自身的高度
//return fm.bottom - fm.top + fm.leading; // 返回文本所在行的行高
}
// 根据资源编号获得线性布局的实际高度(页面来源)
public static float getRealHeight(Activity act, int resid)
{
LinearLayout llayout = act.findViewById(resid);
return getRealHeight(llayout);
}
// 根据资源编号获得线性布局的实际高度(视图来源)
public static float getRealHeight(View parent, int resid)
{
LinearLayout llayout = parent.findViewById(resid);
return getRealHeight(llayout);
}
// 计算指定线性布局的实际高度
public static float getRealHeight(View child)
{
LinearLayout llayout = (LinearLayout) child;
// 获得线性布局的布局参数
LayoutParams params = llayout.getLayoutParams();
if (params == null)
{
params = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
}
// 获得布局参数里面的宽度规格
int wdSpec = ViewGroup.getChildMeasureSpec(0, 0, params.width);
int htSpec;
if (params.height > 0) { // 高度大于0,说明这是明确的dp数值
// 按照精确数值的情况计算高度规格
htSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY);
} else { // MATCH_PARENT=-1,WRAP_CONTENT=-2,所以二者都进入该分支
// 按照不确定的情况计算高度规则
htSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
llayout.measure(wdSpec, htSpec); // 重新丈量线性布局的宽高
// 获得并返回线性布局丈量之后的高度。调用getMeasuredWidth方法可获得宽度
return llayout.getMeasuredHeight();
}
}