You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义ImageView属性赋值问题:timeInterval传递异常及动态属性配置

Fixing mTimeInterval Being 0 in onDraw() & Supporting Dynamic Attributes

Let's break down your problem step by step and fix it properly.


Why is mTimeInterval 0 in onDraw()?

The core issue is how your constructors are set up:

  • Your custom ProgressBarView(Context context, int timeInterval) constructor assigns mTimeInterval, but this isn't called by Android's layout inflation system. If you declare the view in XML, the system uses the AttributeSet-enabled constructors, which don't initialize mTimeInterval (so it stays at its default value of 0).
  • Even if you instantiate the view via code, configuration changes (like screen rotation) will trigger the AttributeSet constructor, resetting mTimeInterval to 0.

Correct Ways to Pass & Update timeInterval

First, add the time_interval attribute to your res/values/attrs.xml file:

<resources>
    <declare-styleable name="ProgressBarView">
        <attr name="overlay_color" format="color"/>
        <!-- Add this attribute for time interval (unit: milliseconds) -->
        <attr name="time_interval" format="integer"/>
    </declare-styleable>
</resources>

Update your init() method to read this attribute from XML, and remember to recycle the TypedArray to avoid memory leaks:

private void init(AttributeSet attrs) {
    if (attrs == null) {
        return;
    }
    TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ProgressBarView);
    mColor = typedArray.getColor(R.styleable.ProgressBarView_overlay_color, Color.BLACK);
    // Read time_interval from XML, default to 0 if not specified
    mTimeInterval = typedArray.getInt(R.styleable.ProgressBarView_time_interval, 0);
    typedArray.recycle(); // Critical for memory management
}

Now you can use the view in XML with the attribute (don't forget to add the app namespace to your root layout):

<com.yourpackage.ProgressBarView
    android:layout_width="100dp"
    android:layout_height="100dp"
    app:overlay_color="#FF0000"
    app:time_interval="60000"/> <!-- 60 seconds in milliseconds -->

2. Proper Constructor Chaining for Code Instantiation

Fix your constructors to ensure all paths initialize mTimeInterval correctly, supporting both code and XML use cases:

public ProgressBarView(Context context) {
    this(context, null);
}

// Custom constructor for code instantiation
public ProgressBarView(Context context, int timeInterval) {
    this(context, null);
    mTimeInterval = timeInterval;
}

public ProgressBarView(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public ProgressBarView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(attrs);
}

3. Dynamic Updates with a Setter Method

To change timeInterval after the view is created, add a setter method that triggers a redraw and resets the handler:

public void setTimeInterval(int timeInterval) {
    mTimeInterval = timeInterval;
    invalidate(); // Trigger immediate redraw
    // Cancel existing handler posts to avoid outdated updates
    mHandler.removeCallbacks(this::invalidate);
    updatePainting();
}

Bonus: Optimize Your onDraw() Code

Your current onDraw() creates a new Paint object every time, which is inefficient. Move the Paint initialization to init() and reuse it:

private Paint mPaint;

private void init(AttributeSet attrs) {
    // ... existing code ...
    // Initialize paint once
    mPaint = new Paint(Paint.DITHER_FLAG);
    mPaint.setColor(mColor);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setAlpha(205); // Note: Alpha ranges from 0 (transparent) to 255 (opaque) — -50 is invalid!
}

Then use mPaint in onDraw() instead of creating a new instance each time.


内容的提问来源于stack exchange,提问作者hyhashemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 07:37:30