2015-04-07 102 views
0

概述: 我有不同類型的行的列表視圖,包括不同高度的圖像和文本。在運行時,我試圖根據行的寬度動態設置包含圖像的佈局的高度。所以行的寬度設置爲match_parent(因爲我們希望它填充設備的寬度),但高度必須在運行時計算以獲得幀的特定長寬比。動態調整列表視圖行的大小

下面是來自適配器的代碼片段,我使用:

@Override 
public View getView(View convertView) { 
    if (convertView == null) { 
     convertView = LayoutInflater.from(mContext).inflate(
       R.layout.chat_row_image, null); 
     holder = new ViewHolder(convertView); 

     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    ViewTreeObserver observer = holder.videoFrame.getViewTreeObserver(); 
    observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 

     @Override 
     public void onGlobalLayout() { 
      // TODO Auto-generated method stub 
      frameWidth = holder.container.getWidth(); 
      int width = frameWidth; 
      int height = (int) (frameWidth/Utilities.MEDIA_CELL_ASPECT_RATIO); 

      Log.d(TAG, "Calculated : " + width + "," + height); 

      FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height); 
      holder.messageImage.setLayoutParams(params); 
      holder.videoFrame.getViewTreeObserver().removeGlobalOnLayoutListener(
        this); 
      Log.d(TAG, "Imageview : " + holder.messageImage.getWidth() + "," + holder.messageImage.getHeight()); 
     } 
    }); 
    return convertView; 
} 

問題:此代碼的工作很好,但通過滾動的ListView中,但是也有一些容易察覺UI毛刺。主要的UI錯誤是行從XML文件中有一個預先定義的高​​度,並且在圖像加載完成後立即過渡到我們計算出的新高度。這會導致該行下方的整個內容在該行出現在屏幕上時突然移位。此外,我們從底部滾動到頂部(這是一個聊天線程)。

事情我已經嘗試:

  1. 我們試圖通過「爲setSelection」的方法(從ListView中)到用戶看到他們「預加載」內容之前通過整個ListView的滾動。這不起作用,它似乎不像圖像在我們滾過它們的短暫時間內加載。

  2. 我們已經嘗試設置靜態XML文件的寬度和高度,並解決了問題,但沒有考慮到不同的屏幕尺寸。

我需要什麼幫助:我們要保持滾動平滑甚至在動態調整佈局。最後的辦法是爲每個屏幕尺寸類別創建不同的XML文件,並對高度進行硬編碼,但這並不能保證我們的幀長寬比符合我們的要求。

請讓我知道是否有任何澄清你想要的。提前致謝!

+0

它看起來像你可以直接設置你的佈局參數,沒有你的全局佈局偵聽器,並調用convertView.requestLayout() –

+0

謝謝!這當然激發了我一個想法,即不使用全局佈局偵聽器,並在膨脹視圖之後立即設置值。我將在下面的答案中對此進行擴展 –

回答

3

答案是設置幀的尺寸的構造適配器而不是getView()方法。根據Nannuo Lei的建議,我們沒有使用ViewTreeObserver.OnGlobalLayoutListener(),而是根據顯示器的寬度和其他佈局元素的填充/邊距來計算幀的尺寸。

public ImageChatRow(Context context) { 
     this.mContext = context; 
     WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 
     Display display = wm.getDefaultDisplay(); 
     Point size = new Point(); 
     display.getSize(size); 
     displayWidth = size.x - 40; //padding is 40 in our case 
     displayHeight = (int) (displayWidth/Utilities.MEDIA_CELL_ASPECT_RATIO); 
    } 

然後在getView()方法,我們只是在充氣後視圖直接設置在框架的尺寸。

public View getView(View convertView) { 
     if (convertView == null) { 
      convertView = LayoutInflater.from(mContext).inflate(
        R.layout.chat_row, null); 
      holder = new ViewHolder(convertView); 

      LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(displayWidth, displayHeight); 
      layoutParams.gravity = Gravity.CENTER; 
      holder.frame.setLayoutParams(layoutParams); 

      convertView.setTag(holder); 
     } else 
      holder = (ViewHolder) convertView.getTag(); 

這樣可以解決加載行和動態設置高度時的毛刺問題。自實施此代碼以來,我們沒有在ScrollView中觀察到任何跳動!

0

您可以外面添加的LinearLayout在chat_row_image.xml,這樣

<RelativeLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content"> 
    <LinearLayout 
     android:id="@+id/layout_ll 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content"> 
     [...] 
    </LinearLayout> 
</RelativeLayout> 

在Adapter.java

@Override 
public View getView(View convertView) { 
    if (convertView == null) { 
     convertView = LayoutInflater.from(mContext).inflate(
      R.layout.chat_row_image, null); 
     holder = new ViewHolder(convertView); 
     LinearLayout ll = (LinearLayout) view.findViewById(R.id.layout_ll); 
     LayoutParams linearParams = (LayoutParams) ll.getLayoutParams(); 
     linearParams.width = width; 
     linearParams.height = height; 
     ll.setLayoutParams(linearParams); 

     convertView.setTag(holder); 
    } else { 
     holder = (ViewHolder) convertView.getTag(); 
    } 

    return convertView; 
}