快速了解Android onMeasure() onLayout()

1 通过继承ViewGroup时一般都要重写onMeasure() onLayout()方法

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取模式和大小,边界参数共有3种模式:UNSPECIFIED一般为0, EXACTLY准确尺寸, AT_MOST自适应尺寸  
int w_mode = MeasureSpec.getMode(widthMeasureSpec);
int w_size = MeasureSpec.getSize(widthMeasureSpec);
int h_mode = MeasureSpec.getMode(heightMeasureSpec);
int h_size = MeasureSpec.getSize(heightMeasureSpec);
//计算自定义的所有子控件的大小  
 measureChildren(widthMeasureSpec, heightMeasureSpec);
//通知父控件,宽高需要多大地方放置子控件
//setMeasuredDimension(resolveSize(size, widthMeasureSpec),resolveSize(size, heightMeasureSpec));
setMeasuredDimension(w_size, h_size);
Log.e("onMeasure","宽mode=" + w_mode + "宽size="+ w_size
+ "高mode=" + h_mode+ "高size=" +h_size);
// super.onMeasure(widthMeasureSpec,heightMeasureSpec);
}

//onLayout是为了指定视图的显示位置,方法执行的前后顺序是在onMeasure之后,因为视图肯定是只有知道大小才能指定位置放置

@Override  
    protected void onLayout(boolean changed, int l, int t, int r, int b) {  
        // 记录总高度  
        int mTotalHeight = 0;  
        // 遍历所有子视图  
        int childCount = getChildCount();  
        for (int i = 0; i < childCount; i++) {  
            View childView = getChildAt(i);  
            // 获取在onMeasure中计算的视图尺寸  
            int measureHeight = childView.getMeasuredHeight();  
            int measuredWidth = childView.getMeasuredWidth();  
  
            childView.layout(l, mTotalHeight, measuredWidth, mTotalHeight   + measureHeight);  
            mTotalHeight += measureHeight;  
        }  
    }

2 获取View控件宽高大小

	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		if (hasFocus){
			int spec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
			view.measure(spec,spec);
			int measuredWidth=view.getMeasuredWidth();int measuredHeight=view.getMeasuredHeight();//原始大小

			int width=view.getWidth();int height=view.getHeight();//真实大小
			LinearLayout.LayoutParams lp=(LinearLayout.LayoutParams)view.getLayoutParams();
			lp.width=width;
			lp.height=width*(measuredHeight / measuredWidth);
			view.setLayoutParams(lp);//设置大小
		}
	}

附:屏幕和控件计算

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.RelativeLayout;

public class DisplayUtils {
	private DisplayUtils(){}
	/**
	 * display widthpixels
	 */
	public static int widthPixels(Context context){
		final float scale = context.getResources().getDisplayMetrics().widthPixels;
		return (int) scale;
	}
	/**
	 * display heightpixels
	 */
	public static int heightPixels(Context context){
		final float scale = context.getResources().getDisplayMetrics().heightPixels;
		return (int) scale;
	}
	/**
	 * dp2px
	 */
    public static int dp2px(Context context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }
    /**
    *自适应listview gridview真实高度
    */
	@SuppressLint("NewApi")
	public static void setViewHeight(final ListView listView, GridView gridView, int gridheight) {
		if (listView!=null&&listView.getAdapter()!=null) {
            listView.post(new Runnable() {
                @Override
                public void run() {
                int totalHeight = 0;
                int widthSpec = View.MeasureSpec.makeMeasureSpec(listView.getWidth(),View.MeasureSpec.AT_MOST);
                for(int i = 0,len = listView.getAdapter().getCount();i<len;i++){//返回数据项的数目
                    View listItem = listView.getAdapter().getView(i, null, listView);
                    listItem.measure(widthSpec,0);//计算子项View 的宽高
                    totalHeight += listItem.getMeasuredHeight();//统计所有子项的总高度
                }
                ViewGroup.LayoutParams params = listView.getLayoutParams();
                params.height =totalHeight +(listView.getDividerHeight()*(listView.getAdapter().getCount()-1));
                //listView.getDividerHeight()获取子项间分隔符占用的高度
			    listView.setLayoutParams(params);
                }
            });
		}

		if (gridView!=null&&gridView.getAdapter()!=null) {
			int totalHeight = 0;
			int columns=gridView.getNumColumns();//每行几个
			int rows;//共几行
			if(gridView.getAdapter().getCount()%columns>0){
				rows=gridView.getAdapter().getCount()/columns+1;
			}else {
				rows=gridView.getAdapter().getCount()/columns;
			}
			for (int i = 0; i < rows; i++) { //只计算每项高度*行数
				View listItem = gridView.getAdapter().getView(i, null, gridView);
				listItem.measure(0, 0); // 计算子项View 的宽高
				totalHeight += listItem.getMeasuredHeight(); // 统计所有子项的总高度
			}
			ViewGroup.LayoutParams params = gridView.getLayoutParams();
			params.height = totalHeight + gridheight*(rows-1);//最后加上分割线总高度
			gridView.setLayoutParams(params);
		}
	}
    /**
     * 横屏竖屏切换
     * @param activity
     * @param vv
     */
	public static void setFull(Activity activity,View vv){
		if (activity.getResources().getConfiguration().orientation==Configuration.ORIENTATION_PORTRAIT){
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);//横屏
			activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
			RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT);
			lp.addRule(RelativeLayout.ALIGN_PARENT_TOP);
			lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
			lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
			lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			lp.addRule(RelativeLayout.CENTER_IN_PARENT);
			vv.setLayoutParams(lp);//!!上级布局RelativeLayout
		}else{
			activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);//竖屏
			activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
			RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,580);
			lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
			lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
			lp.addRule(RelativeLayout.CENTER_IN_PARENT);
			vv.setLayoutParams(lp);//!!上级布局RelativeLayout
		}
	}
	/**
	 * 输入法判断
	 * @param activity
	 * @return isSoftShowing
	 */
	public static boolean isSoftShowing(Activity activity){
		int screenHeight = activity.getWindow().getDecorView().getHeight();
		Rect rect = new Rect();
		activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
		int appHeight = rect.bottom;
		return screenHeight*2/3 > appHeight;
	}

}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值