onlayout被召唤两次任何想法?

时间:2011-12-02 04:26:01

标签: android android-layout android-widget

以下是我的自定义适配器视图的代码。当我在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 个答案:

答案 0 :(得分:-1)

我没有深入探讨,只是简单地回答你的问题 -

这是因为在渲染时,布局经过两次传递,测量传递和布局传递。它是在第二遍中,即布局传递,父视图定位子视图。在布局部分 - http://developer.android.com/reference/android/view/View.html

中查看此内容