2013-04-02 70 views
2

我正在創建一個自定義佈局(視圖組子類),它將自身劃分爲單元格,然後根據單元格位置和單元格寬度/高度來定位子佈局。自定義視圖組中的子視圖不在邊界

想想它是如何組織小部件。

我添加了一堆框架佈局與不同的背景顏色,他們似乎正確定位。但是,當我放入文本視圖時,它會在垂直方向上擴展得更遠,並保持水平方向的固定寬度。該位置正常工作。

代碼:

import android.content.Context; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.View; 
import android.view.ViewGroup; 

public class DynamicLayout extends ViewGroup { 

int numCellsX = 6, numCellsY = 8; 
int cellSize; 

int blockMap[]; 

public DynamicLayout(Context context) { 
    super(context); 

    init(); 
} 

public DynamicLayout(Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(); 
} 

public DynamicLayout(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
    init(); 
} 

private void init() 
{ 
    blockMap = new int[numCellsX * numCellsY]; 
    clearBlockMap(); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

    cellSize = getMeasuredWidth()/numCellsX; 

    int specWidth = MeasureSpec.getSize(widthMeasureSpec); 
    int specHeight = MeasureSpec.getSize(heightMeasureSpec); 

    this.setMeasuredDimension(specWidth, specHeight); 

    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 

    if (getChildCount() > 0) { 
     int wspec = MeasureSpec.makeMeasureSpec(getMeasuredWidth() 
       /getChildCount(), MeasureSpec.EXACTLY); 
     int hspec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), 
       MeasureSpec.EXACTLY); 
     for (int i = 0; i < getChildCount(); i++) { 
      View v = getChildAt(i); 
      v.measure(wspec, hspec); 
     } 
    } 
    Log.i("DYNA", "Measured"); 
} 

@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    Log.i("DYNA", "On Layout"); 

    clearBlockMap(); 

    for (int i = 0; i < getChildCount(); i++) { 
     View v = getChildAt(i); 

     if (v instanceof DynaServiceView) { 
      DynaServiceView serviceView = (DynaServiceView) v; 

      if (serviceView.getVisibility() == GONE) 
       continue; 


      int x = serviceView.getXPos(); 
      int y = serviceView.getYPos(); 
      int width = serviceView.getXCells(); 
      int height = serviceView.getYCells(); 

      //Is the thing too big? 
      if (width > numCellsX) 
      { 
       Log.i("DYNA", "Warning, service too big, shrinking to size"); 
       width = numCellsX; 
       serviceView.setWidth(width); 
      } 

      //Is there space? 
      if (checkBlockMap(x, y, width, height)) 
      { 
       Log.i("DYNA", "Found collision at child " + i +", resolving..."); 
       //Find somewhere to put this 
       boolean foundSpot = false; 
       for (int j = y; j <= numCellsY - height; j++) 
       { 
        for (int k = x; k <= numCellsX - width; k++) 
        { 
         if (!checkBlockMap(k, j, width, height)) 
         { 
          x = k; 
          y = j;        
          foundSpot = true; 
          break; 
         } 
        } 

        if (foundSpot) 
         break; 
       } 

       if (!foundSpot)     
        Log.i("DYNA", "No spot for child at: " + i + ", skipping!"); 
       else 
        Log.i("DYNA", "Resolved! New X/Y: " + x + ", " + y); 
      } 

      setBlockMap(x, y, width, height); 

      //Has spot now, set layout 
      serviceView.layout(l + (x * cellSize), t + (y * cellSize), (x * cellSize) 
        + (width * cellSize), (y * cellSize) 
        + (height * cellSize)); 
     } 

    }  
} 

private boolean checkBlockMap(int x, int y, int width, int height) 
{ 
    for (int j= y; j < y + height; j++) 
    { 
     for (int k = x; k < x + width; k++)      
      if (blockMap[(j * numCellsX) + k] == 1) 
       return true; 
    } 
    return false; 
} 

private void setBlockMap(int x, int y, int width, int height) 
{ 
    for (int j= y; j < y + height; j++) 
    { 
     for (int k = x; k < x + width; k++)      
      blockMap[(j * numCellsX) + k] = 1; 
    } 
} 

private void clearBlockMap() 
{ 
    for (int i = 0; i < blockMap.length;i++) 
     blockMap[i] = 0; 
} 
} 

這裏是說明問題的圖片。在右側,您可以看到佈局的邊框正確排列,但是在左側顯然,子文本視圖沒有跟隨它。

enter image description here

回答

1

發現了問題.... onMeasure沒有正確設置。愚蠢的錯誤。

+0

我正在研究做一些非常相似的事情。出於好奇,當使用這個時,XML佈局是什麼樣子的,還是以編程方式使用這個ViewGroup? – frenziedherring

+0

他們的佈局都是在程序中,但你可以使用佈局,如線性或相對佈局,圖片是從哪裏獲取的。 Android GUI編輯器足夠先進,它將及時運行代碼並顯示它的外觀。 – Ioncannon

+0

感謝您的信息。我決定在RelativeLayout中使用在運行時爲項目計算的邊距。這可能效率較低,但直到我找到換出佈局的理由之後,我現在可能會採用它。 – frenziedherring