【问题标题】:Android layout not aligned parent as instructed in java codeAndroid布局未按照java代码中的说明对齐父级
【发布时间】:2013-07-16 07:04:12
【问题描述】:

我在以编程方式从我指定的 XML 布局中扩展我的 CustomView 时遇到问题。

我有一个CustomView,它扩展RelativeLayout 并包含另一个RelativeLayout,而RelativeLayout 又包含2 个ImageView 和1 个LinearLayout。 ImageViews 是箭头图标,我分别通过 android:layout_alignParentLeft="true" 和 android:layout_alignParentRight="true" 放在父级的左侧和右侧,LinearLayout 用于填充其间的所有空间。

为了清楚起见,这里是 Eclipse 布局设计器中的 xml 布局视图,这正是我想要的......

如果我 setContentView(R.layout.my_xml_layout);直接从 Activity 中,一切都显示在 Eclipse Layout Designer 中,但是,如果我从 CustomView 的构造函数中对 R.layout.my_xml_layout 进行膨胀,则 ImageView 的左右有一个无法消失的顽固边距。

这是在java代码中完成的,有问题:

任何帮助将不胜感激!提前致谢!

my_xml_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

  <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <ImageView
            android:id="@+id/imageLeftArrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:src="@drawable/dock_leftarrow" />

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" >

        </LinearLayout>

        <ImageView
            android:id="@+id/imageRightArrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:src="@drawable/dock_rightarrow" />

    </RelativeLayout>

</RelativeLayout>

我通过这一行在CustomView的构造函数中给它充气:

View.inflate( mContext, R.layout.my_xml_layout, this );

我的 CustomView 的 onLayout:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    // Do nothing. Do not call the superclass method--that would start a layout pass
    // on this view's children. PieChart lays out its children in onSizeChanged().
    Log.e("DrawView", "DrawView.onLayout: " + l + ", " + t + ", " + r + ", " + b);

    int iChildCount = this.getChildCount();
    for ( int i = 0; i < iChildCount; i++ ) {
        View pChild = this.getChildAt(i);
        pChild.layout(0, 0, pChild.getMeasuredWidth(), pChild.getMeasuredHeight());
    }
}

我的 CustomView 的 onMeasure:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // Try for a width based on our minimum
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    Log.d("DockView", "DockView.onMeasure: width: " + widthMeasureSpec + " getWidth: " + MeasureSpec.getSize(widthMeasureSpec));
    Log.d("DockView", "DockView.onMeasure: height: " + heightMeasureSpec + " getHeight: " + MeasureSpec.getSize(heightMeasureSpec));
    Log.d("DockView", "DockView.onMeasure: getPaddingLeft: " + getPaddingLeft() + " getPaddingRight: " + getPaddingRight());
    Log.d("DockView", "DockView.onMeasure: getPaddingTop: " + getPaddingTop() + " getPaddingBottom: " + getPaddingBottom());

    // http://stackoverflow.com/a/17545273/474330
    int iParentWidth = MeasureSpec.getSize(widthMeasureSpec);
    int iParentHeight = MeasureSpec.getSize(heightMeasureSpec);
    this.setMeasuredDimension(iParentWidth, iParentHeight);

    int iChildCount = this.getChildCount();
    for ( int i = 0; i < iChildCount; i++ ) {
        View pChild = this.getChildAt(i);
        this.measureChild( pChild, 
                MeasureSpec.makeMeasureSpec(iParentWidth, MeasureSpec.EXACTLY), 
                MeasureSpec.makeMeasureSpec(iParentHeight, MeasureSpec.EXACTLY)
        );
    }
}

【问题讨论】:

  • 你有任何填充或其他东西吗?
  • 不,没有填充,根本没有边距......我怀疑它是 onMeasure,因为如果我将其注释掉,ImageView 将根本不会显示......我从另一个得到代码StackOverflow 中的问题,并没有真正理解它(MeasureSpec 等)的工作方式......
  • 从你的第二个RelativeLayout中删除这行xmlns:android="http://schemas.android.com/apk/res/android"
  • 我删除了它,它没有任何区别:(

标签: android android-layout layout


【解决方案1】:

目前,我正在使用 hack。

我只将 LinearLayout 添加为我的 CustomView 的子视图。然后我在 onDraw(Canvas c); 中手动渲染两个 ImageViews;我的自定义视图的功能。为了让 LinearLayout 适合两个 ImageView 之间的剩余空间,我在 CustomView 的 onLayout 中计算了 LinearLayout 的边距。

horizo​​ntal_dock_view.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="@android:color/white" >

            <ImageView 
                android:id="@+id/imageLauncher"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:src="@drawable/ic_launcher"/>

        </LinearLayout>

</RelativeLayout>

CustomView.java

    /**
     * Initialize the control. This code is in a separate method so that it can be
     * called from both constructors.
     */
    private void init() {
        setWillNotDraw( false );

        // Load the arrow bitmap
        mArrowBitmap = ((BitmapDrawable)mContext.getResources().getDrawable(R.drawable.dock_leftarrow)).getBitmap();

        ViewGroup pRootView = (ViewGroup) View.inflate( mContext, R.layout.horizontal_dock_view, this );
        Log.d("DockView", "DockView.init: " + pRootView.getClass().getCanonicalName());
        mIconContainerView = (LinearLayout) ((RelativeLayout)pRootView.getChildAt(0)).getChildAt(0);

        Log.d("DockView", "DockView.init: " + mIconContainerView.getClass().getCanonicalName());

//      if ( mArrowBitmap != null ) {
//          // set the icon container margin        
//          float fWidth = this.getWidth();     // View's width
//          float fHeight = this.getHeight();   // View's height
//          float fScale = fHeight / mArrowBitmap.getHeight();
//          float fArrowWidth = mArrowBitmap.getWidth() * fScale;
//          float fArrowHeight = mArrowBitmap.getHeight() * fScale;
//          Log.d("DockView", "DockView.init: " + fArrowWidth + ", " + fArrowHeight );
//          ((RelativeLayout.LayoutParams)mIconContainerView.getLayoutParams()).setMargins((int)fArrowWidth, 0, (int)fArrowWidth, 0);
//      }
    }

CustomView.onLayout:

    @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    // Do nothing. Do not call the superclass method--that would start a layout pass
    // on this view's children. PieChart lays out its children in onSizeChanged().
    Log.e("DrawView", "DrawView.onLayout: " + l + ", " + t + ", " + r + ", " + b);

    if ( mIconContainerView != null && mArrowBitmap != null ) {
        // set the icon container margin    
        float fHeight = this.getHeight();
        float fScale = fHeight / mArrowBitmap.getHeight();
        float fArrowWidth = mArrowBitmap.getWidth() * fScale;
        float fArrowHeight = mArrowBitmap.getHeight() * fScale;
        Log.d("DockView", "DockView.init: " + fArrowWidth + ", " + fArrowHeight );
        ((RelativeLayout.LayoutParams)mIconContainerView.getLayoutParams()).setMargins((int)fArrowWidth, 0, (int)fArrowWidth, 0);
        this.requestLayout();
    }

    int iChildCount = this.getChildCount();
    for ( int i = 0; i < iChildCount; i++ ) {
        View pChild = this.getChildAt(i);
        pChild.layout(0, 0, pChild.getMeasuredWidth(), pChild.getMeasuredHeight());
    }
}

CustomView.onDraw

    @Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

//      mBgColor = Color.CYAN;
//      Log.e("DockView", "DockView.onDraw: " + mBgColor);
    Log.e("DockView", "DockView.onDraw: width: " + this.getWidth() + " height: " + this.getHeight());

//      debugChildren( (RelativeLayout) ((RelativeLayout)this.getChildAt(0)).getChildAt(0) );
    debugChildren( ((RelativeLayout)this.getChildAt(0)) );

    // draw the background
    canvas.drawColor( mBgColor );

    float fWidth = this.getWidth();     // View's width
    float fHeight = this.getHeight();   // View's height

    {
        // draw the dock
        float fTop = (2 * fHeight) / 3.0f;
        Shader shader = new LinearGradient( 0, fTop, 0, fHeight, mDockTopGradientColor, mDockBottomGradientColor, TileMode.CLAMP );
        Paint paint = new Paint();
        paint.setShader(shader);
        canvas.drawRect( new RectF( 0, fTop, fWidth, fHeight ), paint );
    }

// moved to onLayout
//      if ( mIconContainerView != null && mArrowBitmap != null ) {
//          // set the icon container margin        
//          float fScale = fHeight / mArrowBitmap.getHeight();
//          float fArrowWidth = mArrowBitmap.getWidth() * fScale;
//          float fArrowHeight = mArrowBitmap.getHeight() * fScale;
//          Log.d("DockView", "DockView.init: " + fArrowWidth + ", " + fArrowHeight );
//              ((RelativeLayout.LayoutParams)mIconContainerView.getLayoutParams()).setMargins((int)fArrowWidth, 0, (int)fArrowWidth, 0);
//          this.requestLayout();
//      }

    if ( mArrowBitmap != null ) {
        // draw the arrow
//          canvas.drawBitmap(mArrowBitmap, 0, 0, null);
        float fScale = fHeight / mArrowBitmap.getHeight();
        float fDrawnWidth = mArrowBitmap.getWidth() * fScale;
        float fDrawnHeight = mArrowBitmap.getHeight() * fScale;
//          float fLeft = fWidth - fDrawnWidth;
//          float fTop = 0.0f;
//          float fRight = fWidth;
//          float fBottom = fDrawnHeight;
//          Log.d("DockView", "DockView.onDraw: (" + fLeft + ", " + fTop + ", " + fRight + ", " + fBottom + ")");
        canvas.drawBitmap(mArrowBitmap, null, new RectF(0, 0, fDrawnWidth, fDrawnHeight), null);    // Left arrow
        Log.d("DockView", "DockView.onDraw: (" + 0 + ", " + 0 + ", " + fDrawnWidth + ", " + fDrawnHeight + ")");
        canvas.save();
        canvas.scale(-1,1);
        canvas.translate(-fWidth, 0);
//          canvas.drawBitmap(mArrowBitmap, null, new RectF(fLeft, fTop, fRight, fBottom), null);
        canvas.drawBitmap(mArrowBitmap, null, new RectF(0, 0, fDrawnWidth, fDrawnHeight), null);    // Right arrow, flipped
        canvas.restore();
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-21
    相关资源
    最近更新 更多