解决自定义View,不执行onDraw方法

描述

在自定义View的时候,发现不执行onDraw方法,在网上查了方法,
1.在构造方法里增加setWillNotDraw(false)方法,发现不起作用.
2.主动的调用invalidate();方法,也不起作用,
经过查找发现了下面的问题.特此记录下来,希望可以帮助到大家.

不执行原因

1.自定义的View所在的布局中,自定义View计算不出位置.
2.确定不了View宽和高
3.在onMeasure()方法中没设置控件的宽和高

自定义View


public class TempView extends View {

    private final String TAG = TempView.class.getSimpleName();

    public TempView(Context context) {
        this(context, null);

    }

    public TempView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        Log.d(TAG, "--TempView--");
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        Log.d(TAG, "--onMeasure--");
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        Log.d(TAG, "--onLayout--");
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.d(TAG, "--onDraw--");
    }

例如

就是自定义View所在的是在NestedScrollView中

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <demo.tx.com.buttondemo.weight.TempView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>


</android.support.v4.widget.NestedScrollView>

打印出日志

2019-02-18 10:40:34.801 17499-17499/demo.tx.com.buttondemo D/TempView: --TempView--
2019-02-18 10:40:34.848 17499-17499/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:40:34.866 17499-17499/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:40:34.868 17499-17499/demo.tx.com.buttondemo D/TempView: --onLayout--

从日志中中可以看出没有执行onDraw方法,原因就是自定义View计算不出位置.

解决办法

办法1

将NestedScrollView改为LinearLayout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <demo.tx.com.buttondemo.weight.TempView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

    </LinearLayout>


</LinearLayout>
2019-02-18 10:44:37.989 17863-17863/demo.tx.com.buttondemo D/TempView: --TempView--
2019-02-18 10:44:38.029 17863-17863/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:44:38.048 17863-17863/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:44:38.050 17863-17863/demo.tx.com.buttondemo D/TempView: --onLayout--
2019-02-18 10:44:38.073 17863-17863/demo.tx.com.buttondemo D/TempView: --onDraw--

办法2

就是给自定义View设置固定的高和宽

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <demo.tx.com.buttondemo.weight.TempView
            android:layout_width="100dp"
            android:layout_height="100dp" />

    </LinearLayout>


</android.support.v4.widget.NestedScrollView>

打印日志

2019-02-18 10:47:05.148 18012-18012/demo.tx.com.buttondemo D/TempView: --TempView--
2019-02-18 10:47:05.193 18012-18012/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:47:05.211 18012-18012/demo.tx.com.buttondemo D/TempView: --onMeasure--
2019-02-18 10:47:05.213 18012-18012/demo.tx.com.buttondemo D/TempView: --onLayout--
2019-02-18 10:47:05.239 18012-18012/demo.tx.com.buttondemo D/TempView: --onDraw--

办法3

在onMeasure方法中设置控件的宽和高


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        setMeasuredDimension(width,height);
        Log.d(TAG, "onMeasure");
    }

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Android中,可以使用`ViewTreeObserver`监听另一个View的位置来设置自己的位置。 具体步骤如下: 1. 在自定义View的构造函数中获取另一个View的引用 ```java public CustomView(Context context, AttributeSet attrs) { super(context, attrs); // 获取另一个View的引用 mTargetView = ((Activity) context).findViewById(R.id.target_view); // 获取ViewTreeObserver ViewTreeObserver observer = mTargetView.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { // 在布局完成后获取另一个View的位置信息 mTargetView.getLocationOnScreen(mTargetLocation); // 移除监听器 mTargetView.getViewTreeObserver().removeOnGlobalLayoutListener(this); } }); } ``` 2. 在`onDraw()`方法中根据另一个View的位置设置自己的位置 ```java @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 根据另一个View的位置设置自己的位置 int x = mTargetLocation[0] + mTargetView.getWidth() / 2 - getWidth() / 2; int y = mTargetLocation[1] + mTargetView.getHeight() / 2 - getHeight() / 2; setX(x); setY(y); } ``` 上面的代码中,我们使用`mTargetView.getLocationOnScreen(mTargetLocation)`方法获取另一个View的位置信息,然后根据这个位置信息设置自己的位置。由于`getLocationOnScreen()`方法返回的是相对于屏幕左上角的位置,因此我们需要将其转换为相对于父容器的位置,这可以通过计算偏移量来实现。 需要注意的是,由于布局可能会发生变化,因此我们需要在`addOnGlobalLayoutListener()`方法中监听布局完成的事件,并在布局完成后获取另一个View的位置信息。此外,在获取完位置信息后,我们需要将监听器从ViewTreeObserver中移除,以免重复执行

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值