为什么我们不能在自定义视图初始化时将视图扩展到customview?

时间:2016-08-04 07:35:35

标签: android android-view android-custom-view layout-inflater

我创建了一个自定义视图,名为从RelativeLayout扩展的PinView。 在构造函数中,我调用我的init()方法,并从布局中扩展视图。

inflate(getContext(), R.layout.layout_pin_view, this);

在这个膨胀流之后,我需要通过请求addView()在这个膨胀的视图中添加我的其他视图(Imageview)。并抛出:

catch (NoSuchMethodException e) {
            InflateException ie = new InflateException(attrs.getPositionDescription()
                    + ": Error inflating class "
                    + (prefix != null ? (prefix + name) : name));
            ie.initCause(e);
            throw ie; 

我可以通过以下方式成功膨胀:

mLlPins.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                mLlPins.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                ....
                ....
                addView(...)



            }
        }); 

您是否知道为什么我们无法同步充气来创建动态视图?

我的代码部分:

private void init() {
    View view = inflate(getContext(), R.layout.layout_pin_view, this);
    mEtPin = (PinEditText) view.findViewById(R.id.etPin);
    mLlPins = (LinearLayout) view.findViewById(R.id.llPins);
    mEtPin.setVisibility(View.VISIBLE);
    mEtPin.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)});
    mEtPin.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            return false;
        }
    });
    mEtPin.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            if (mImageViews != null) {
                for (int i = 0; i < mImageViews.length; i++)
                    mImageViews[i].setEnabled(i < s.length());
                if (s.length() == mMaxLength) {
                    InputMethodManager imm = (InputMethodManager) mEtPin.getContext().getSystemService(
                            Context.INPUT_METHOD_SERVICE);
                    imm.hideSoftInputFromWindow(mEtPin.getWindowToken(), 0);
                }
            }
        }
    });
    mLlPins.setClickable(false);
    mEtPin.setText(mEtPin.getText());

    mEtPin.addTextChangedListener(new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {

        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

        }

        @Override
        public void afterTextChanged(Editable s) {
            if (mImageViews == null) return;
            for (int i = 0; i < mMaxLength; i++) {
                if (mImageViews[i] != null) {
                    if (i < s.length()) {
                        mImageViews[i].setImageAlpha(255);
                        continue;
                    }
                }
                mImageViews[i].setImageAlpha(0);
            }

        }
    });

    setMaxLength(4);
}
private void setMaxLength(int maxLength) {
    LayoutInflater inflater = LayoutInflater.from(mLlPins.getContext());
    mMaxLength = maxLength;
    mEtPin.setFilters(new InputFilter[]{new InputFilter.LengthFilter(maxLength)});
    mImageViews = new ImageView[maxLength];
    mLlPins.removeAllViews();
    int totalContentLenght = mLlPins.getMeasuredWidth() - dpToPx((maxLength - 1) * mMargin);
    int itemWidthHeight = totalContentLenght / maxLength;
    int itemMargin = dpToPx(mMargin / 2);
    int itemPadding = (int) (itemWidthHeight * srcRatio);
    for (int i = 0; i < maxLength; i++) {
        mImageViews[i] = (ImageView) inflater.inflate(mPinImage, null);
        mImageViews[i].setEnabled(false);
        mImageViews[i].setPadding(itemPadding, itemPadding, itemPadding, itemPadding);
        LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(itemWidthHeight, itemWidthHeight);
        if (i == 0) {
            params.setMargins(0, 0, itemMargin, 0);
        } else if (i < maxLength - 1) {
            params.setMargins(itemMargin, 0, itemMargin, 0);
        } else {
            params.setMargins(itemMargin, 0, 0, 0);

        }
        mImageViews[i].setImageAlpha(0);
        mLlPins.addView(mImageViews[i], params);

    }

}

1 个答案:

答案 0 :(得分:1)

在我的理解中,你不能膨胀视图,因为父视图(表示为容器)没有绘制,这意味着它的所有布局参数都没有解决,当你添加一个视图时,你的视图无法计算自己的视图参数到期容器尚未启动。 如果要在容器onCreate方法中使用启动子视图方法,可以在容器创建方法中尝试以下内容:

containerVariable.post(new Runnable(){
    @Override
    public void run(){
      // initiate your child view and add child view here 
    }
});