0

我做了一個「GraphBar」自定義視圖,該視圖的底部爲TextView,而ImageView爲高度不等,高度爲的RelativeLayout。下面是代碼:我的自定義視圖只在添加到onCreate時繪製

public class GraphBar extends RelativeLayout { 

    private int mAvailHeight; // space for the bar (component minus label) 
    private float mBarHeight; // 0.0-1.0 value 

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

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

    public GraphBar(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     LayoutInflater.from(context).inflate(R.layout.graphbar, this, true); 
     setId(R.id.graphBar); // defined in <merge> but not assigned (?) 
    } 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 
     mAvailHeight = getHeight()-findViewById(R.id.label).getHeight(); 
    } 

    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) { 
     super.onLayout(changed, l, t, r, b); 

     View bar2 = findViewById(R.id.smallBar); 
     RelativeLayout.LayoutParams llp2 = (RelativeLayout.LayoutParams) bar2.getLayoutParams(); 
     llp2.height = Math.round((float)mAvailHeight * mBarHeight); 
    } 

    public void setBarHeight(float value, float max) { 
     mBarHeight = value/max; 
     findViewById(R.id.smallBar).requestLayout(); 
    } 

    public void setLabel(CharSequence c) { 
     ((TextView) findViewById(R.id.label)).setText(c); 
    } 
} 

雖然加入這些GraphBars並設置其onCreate()作品高度的優勢,如果我創建它們onClickSomething或再次呼籲創建條setBarHeight(),看到變化的唯一途徑是加載視圖層次。我被告知here這意味着我需要致電requestLayout()。在修改mBarHeight後還有什麼地方?任何幫助?我到處嘗試,也有invalidate()

謝謝 安德烈

(如果你需要我可以張貼與我做我的測試活動和graphbar.xml)


我發現它可能a bug。解決方法應該是,再次呼叫requestLayout()。我仍然不明白我可以打電話的地方。

回答

0

我終於找到了一種方式再次打電話給requestLayout()。我在構造函數中調用了setWillNotDraw(false),以便在onDraw()(即在onLayout()之後)我可以調用額外的requestLayout()。這產生了一個愚蠢的週期,但美學上解決了這個問題。

如果有人知道一個更好的解決方案,讓我知道...這裏的新代碼(修改是旁邊註釋):

//... 
    public GraphBar(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     LayoutInflater.from(context).inflate(R.layout.graphbar, this, true); 
     setWillNotDraw(false); // WORKAROUND: onDraw will be used to make the 
           // redundant requestLayout() call 
     setId(R.id.graphBar); 
    } 
//... 
    @Override 
    protected void onDraw(Canvas canvas) { 
     super.onDraw(canvas); 

     // i think it's one of the worst workaround one could think of. 
     // luckily android is smart enough to stop the cycle... 
     findViewById(R.id.smallBar).requestLayout(); 
    } 

    public void setBarHeight(float value, float max) { 
     mBarHeight = value/max; 
     View bar = findViewById(R.id.smallBar); 

     bar.requestLayout(); // because when we create this view onDraw is called... 
     bar.invalidate(); // ...but not when we modify it!!! 
          //so we need to invalidate too 
    } 
//...