2011-12-02 117 views
0

下面是我的自定義adapterview的代碼。當我在onLayout方法中放置一個斷點時,它會被調用兩次。同樣在層次結構瀏覽器中,我看到了重複的視圖。onlayout被調用兩次任何想法?

package com.me.practice.widgets;  
import java.util.LinkedList; 
import java.util.Queue; 

import android.content.Context; 
import android.graphics.Rect; 
import android.util.AttributeSet; 
import android.view.GestureDetector; 
import android.view.MotionEvent; 
import android.view.View; 
import android.view.GestureDetector.OnGestureListener; 
import android.view.View.MeasureSpec; 
import android.view.ViewGroup; 
import android.widget.AdapterView; 
import android.widget.Gallery; 
import android.widget.LinearLayout; 
import android.widget.ListAdapter; 
import android.widget.Scroller; 
import android.widget.AdapterView.OnItemClickListener; 
import android.widget.AdapterView.OnItemSelectedListener; 

public class ScrollableAdapterView extends AdapterView<ListAdapter> { 

    public ScrollableAdapterView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     initView(context); 
    } 

      //TO detect gestures 
    private GestureDetector mGesture; 

    protected Scroller mScroller; 
    private OnItemSelectedListener mOnItemSelected; 
    private OnItemClickListener mOnItemClicked; 
    protected int mCurrentX; 
    protected int mNextX; 
    private int mMaxX = Integer.MAX_VALUE; 

    private int mLeftViewIndex = -1; 
    private int mRightViewIndex = 0; 

    protected ListAdapter mAdapter; 
    private Queue<View> mRemovedViewQueue = new LinkedList<View>(); 

    private synchronized void initView(Context mContext) { 
     mScroller = new Scroller(getContext()); 
     mGesture = new GestureDetector(getContext(), mOnGesture); 
    } 

    @Override 
    public ListAdapter getAdapter() { 
     return mAdapter; 
    } 

    @Override 
    public View getSelectedView() { 
     // TODO Auto-generated method stub 
     return null; 
    } 

    @Override 
    public void setAdapter(ListAdapter adapter) { 
     mAdapter = adapter; 
    } 

    @Override 
    public void setSelection(int position) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    protected void onLayout(boolean changed, int left, int top, int right, 
      int bottom) { 

     super.onLayout(changed, left, top, right, bottom); 

     if (mAdapter == null) { 
      return; 
     } 

     renderViews(); 

     if (!mScroller.isFinished()) { 
      post(new Runnable() { 
       @Override 
       public void run() { 
        requestLayout(); 
       } 
      }); 
     } 
    } 

    private void renderViews() { 
     renderFixedColumn(3); 
     renderScrollableViews(); 
    } 

    private void renderScrollableViews() { 
    } 

    //Renders fixed columns... 
    private void renderFixedColumn(int fixedColumnUptoIndex) { 
     //View fixedLayout= findViewById(R.id.fixedviewsLayout); 
     int index=0; 

     LinearLayout fixedViewsLayout = new LinearLayout(getContext()); 
     LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
       ViewGroup.LayoutParams.WRAP_CONTENT, 
       ViewGroup.LayoutParams.MATCH_PARENT); 
     //fixedViewsLayout.setId(R.id.fixedviewsLayout); 

     while (index < fixedColumnUptoIndex) { 
      View child = mAdapter.getView(index, mRemovedViewQueue.poll(), this); 
      fixedViewsLayout.addView(child, index); 
      index++; 
     } 
     addViewInLayout(fixedViewsLayout, 0, params, true); 

     fixedViewsLayout.measure(MeasureSpec.makeMeasureSpec(getWidth(), 
       MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(
       getHeight(), MeasureSpec.AT_MOST)); 

     relayoutMeasuredItem(fixedViewsLayout); 

    } 

    private void relayoutMeasuredItem(View child) { 
     final int w = child.getMeasuredWidth(); 
     final int h = child.getMeasuredHeight(); 
     final int childLeft = getLeft(); 
     final int childRight = childLeft + w; 
     final int childTop = child.getTop(); 
     final int childBottom = childTop + h; 
     child.layout(childLeft, childTop, childRight, childBottom); 
    } 

    //  
    private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { 
     @Override 
     public boolean onDown(MotionEvent e) { 
      return ScrollableAdapterView.this.onDown(e); 
     } 

     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
       float velocityY) { 
      return ScrollableAdapterView.this.onFling(e1, e2, velocityX, 
        velocityY); 
     } 

     @Override 
     public boolean onScroll(MotionEvent e1, MotionEvent e2, 
       float distanceX, float distanceY) { 

      synchronized (ScrollableAdapterView.this) { 
       mNextX += (int) distanceX; 
      } 
      requestLayout(); 

      return true; 
     } 

     @Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
      Rect viewRect = new Rect(); 
      for (int i = 0; i < getChildCount(); i++) { 
       View child = getChildAt(i); 
       int left = child.getLeft(); 
       int right = child.getRight(); 
       int top = child.getTop(); 
       int bottom = child.getBottom(); 
       viewRect.set(left, top, right, bottom); 
       if (viewRect.contains((int) e.getX(), (int) e.getY())) { 
        if (mOnItemClicked != null) { 
         mOnItemClicked.onItemClick(
           ScrollableAdapterView.this, 
           child, mLeftViewIndex + 1 + i, 
           mAdapter.getItemId(mLeftViewIndex + 1 + i) 
         ); 
        } 
        if (mOnItemSelected != null) { 
         mOnItemSelected.onItemSelected(
          ScrollableAdapterView.this, 
          child, 
          mLeftViewIndex + 1 + i, 
          mAdapter.getItemId(mLeftViewIndex + 1 + i) 
         ); 
        } 
        break; 
       } 
      } 
      return true; 
     } 
    }; 

    protected boolean onDown(MotionEvent e) { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 
      float velocityY) { 
     // TODO Auto-generated method stub 
     return false; 
    } 
} 

這裏是我活動的onCreate方法..

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.listviewdemo); 
    listview.setAdapter(mAdapter); 
} 

getView方法,它返回視圖:

public View getView(int position, View convertView, ViewGroup parent) { 
    View retval = LayoutInflater.from(parent.getContext()).inflate(R.layout.viewitem, null); 
    TextView title = (TextView) retval.findViewById(R.id.title); 
    title.setText(dataObjects[position]);  

    return retval; 
} 

回答

-1

我沒有走這麼深層次的,但要回答你的問題在brief-

這是因爲在渲染時,佈局經歷兩次通過,測量通過和佈局通過。這是在第二遍,即佈局通過,父視圖定位兒童的意見。檢查了這一點,在佈局部分 - http://developer.android.com/reference/android/view/View.html

+0

佈局經歷兩遍,這應該等同於一個onMeasure調用和一個onLayout調用。然而,觀察到的行爲是兩個onLayout調用,這是令人困惑的。 – yarian