自定义view在xml文件中wrap_content无法展现?只有设置高宽值才出现?

自定义view在xml文件中wrap_content无法展现?只有设置高宽值才出现?

老师:你好!

我的自定义BlockView  高宽设置为wrap_content,background设红色方块图,但是运行时无法出现这个BlockView,只有在布局文件中,设置具体高宽运行才能看见BlockView?

这个xml布局文件:

<com.example.animationhomework.BlockView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   hyman:test_dimension="100dp"
   android:background="@drawable/red" />


这是自定义BlockView   attrs 和类:

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <!--属性申明,可以使用系统自带的设置,加上Android:-->
   <declare-styleable name="BlockView">
       <attr name="test_dimension" format="dimension" />
   </declare-styleable>

</resources>


自定义类:

public class BlockView extends View {

   private Paint mPaint;//画笔对象

     public BlockView(Context context) {
      super(context);
  }
   public BlockView(Context context, @Nullable AttributeSet attrs) {
       super(context, attrs);
       initPaint();//初始化画笔属性
//        获取属性文件
       TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.BlockView);
       /*属性赋值,赋予默认值*/
       float dimensionTest = ta.getDimension(R.styleable.BlockView_test_dimension, 0);
       ta.recycle();//回收ta 属性文件
   }

   //设置画笔属性
   private void initPaint() {
       mPaint = new Paint();//画笔对象
       mPaint.setStyle(Paint.Style.STROKE);//FiLL实心,STROKE空心
       mPaint.setStrokeWidth(6);//画笔粗细
       mPaint.setColor(0xFFFF0000);//画笔颜色
       mPaint.setAntiAlias(true);//画笔平滑
   }


//测量控件大小
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       int widthMode = MeasureSpec.getMode(widthMeasureSpec);//获取测量宽度模式:MeasureSpec.EXACTLY  MeasureSpec.AT_MOST  MeasureSpec.UNSPECIFIED
       int widthSize = MeasureSpec.getSize(widthMeasureSpec);//获取测量宽度尺寸

       int width = 0;
       if (widthMode == MeasureSpec.EXACTLY)//用户自定义宽度大小
       {
           width = widthSize;
       } else {
           int needWidth = getMeasuredWidth() + getPaddingLeft() + getPaddingRight();//需要的宽度尺寸
           if (widthMode == MeasureSpec.AT_MOST)//如果测量宽度模式限制了最大值
           {
               width = Math.min(needWidth, widthSize);//测量宽度取 (需要值、测量值 ) 的最小值
           } else {
               width = needWidth;//没有设置最大值限制,宽度取需要值
           }
       }
       int heightMode = MeasureSpec.getMode(heightMeasureSpec);//获取测量高度模式
       int heightSize = MeasureSpec.getSize(heightMeasureSpec);//测量高度尺寸
       int height = 0;
       if (heightMode == MeasureSpec.EXACTLY)//用户自定义高度值
       {
           height = heightSize;//取测量高度
       } else {
           int needHeight = getMeasuredHeight() + getPaddingTop() + getPaddingBottom();//需要的高度尺寸
           if (heightMode == MeasureSpec.AT_MOST) {
               height = Math.min(needHeight, heightSize);//最大值限制,取需要高度和测量高度的最小值
           } else {
               height = needHeight;
           }//无限制高度,取需要高度尺寸
       }
       setMeasuredDimension(width, height);//设置宽高尺寸
   }
//获取屏幕尺寸 减去paddiing后的1/6
   private float measureDisplayMetricOneSixth() {
       WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
       DisplayMetrics dm = new DisplayMetrics();
       wm.getDefaultDisplay().getMetrics(dm);
       return ( dm.widthPixels-getPaddingLeft()-getPaddingRight())*1f/6;
   }
//正方形图形,宽高一致
   private float measureHeight() {
       return measureDisplayMetricOneSixth();
   }
//六个方块铺底,每块宽度是 1/6*屏宽
   private float measureWidth() {
       return measureDisplayMetricOneSixth();
   }

   //TextView触屏(包含屏幕翻转)事件.屏幕回转后会恢复到原来的mStringTest="imooc"的值,通过保存和恢复函数实现才能保存"8888"值
   @Override
   public boolean onTouchEvent(MotionEvent event) {

       invalidate();//其内部实际是调用invalidate(true)。是完全重绘自身TextView,本例中重绘后把文字变成"8888"
       return true;
   }

}

正在回答

登陆购买课程后可参与讨论,去登陆

1回答

onMeasure()里直接固定好宽和高就可以了。例如手机需要放6个控件,再去掉间距,平均一下。祝:学习愉快

  • 慕运维0750787 提问者 #1
    现在这么写的,但是屏幕闪退,也不报错: //测量控件大小 @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // int widthMode = MeasureSpec.getMode(widthMeasureSpec);//获取测量宽度模式:MeasureSpec.EXACTLY MeasureSpec.AT_MOST MeasureSpec.UNSPECIFIED // int widthSize = MeasureSpec.getSize(widthMeasureSpec);//获取测量宽度尺寸 int width = 0; width= (int) measureWidth(); // int heightMode = MeasureSpec.getMode(heightMeasureSpec);//获取测量高度模式 // int heightSize = MeasureSpec.getSize(heightMeasureSpec);//测量高度尺寸 int height = 0; height= (int) measureHeight(); setMeasuredDimension(width, height);//设置宽高尺寸 } //获取屏幕尺寸 减去paddiing后的1/6 private float measureDisplayMetricOneSixth() { WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(dm); return (dm.widthPixels - getPaddingLeft() - getPaddingRight()) * 1f / 6; } //正方形图形,宽高一致 private float measureHeight() { return measureDisplayMetricOneSixth(); } //六个方块铺底,每块宽度是 1/6*屏宽 private float measureWidth() { return measureDisplayMetricOneSixth(); }
    2020-09-26 10:32:20
问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师