代码之家  ›  专栏  ›  技术社区  ›  Tydax

自定义视图打乱布局

  •  1
  • Tydax  · 技术社区  · 12 年前

    我一直面临一个我编码的自定义视图的问题。基本上,我有一个自定义视图,它处理座椅的不同部分,具有不同的状态。我设法编码了它,它工作得很好。
    由于应用程序的速度有点慢,我决定裁剪图像:它只需要屏幕的一部分(我没有做图形),而不是透明地拍摄整个屏幕。

    但由于我已经裁剪了图像 messing up my layout 。我不知道为什么,因为当我用ImageView替换自定义视图时,它非常适合!
    我的观点似乎忽略了wrap_content,它需要的远远超过它所需要的。将值设置为match_parent也不起作用。

    我再次尝试裁剪我的图像,我认为这是因为尺寸,但事实并非如此。我尝试重写onMeasure方法,但没有更改。我不想硬编码尺寸,因为我觉得这样做很糟糕。

    为什么会发生这种情况,我该如何解决?

    下面是我的一些代码片段。

    碎片_lumbar.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <!-- Main screen -->
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/background_logo">
    
        <!-- Left menu with control buttons -->
    
        <RelativeLayout
            android:id="@+id/lumbar_control"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="61dp">
    
            <ImageButton
                android:id="@+id/button_arrowup"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:layout_marginTop="40dp"
                android:background="@drawable/arrowup_button"
                android:contentDescription="@string/moveup_lumbar" />
    
            <!-- Plus/minus buttons -->
    
            <ImageButton
                android:id="@+id/button_plus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/button_arrowup"
                android:layout_centerVertical="true"
                android:background="@drawable/plus_button"
                android:contentDescription="@string/inflate_lumbar" />
    
            <ImageButton
                android:id="@+id/button_minus"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/button_arrowup"
                android:layout_toRightOf="@id/button_plus"
                android:layout_marginLeft="90dp"
                android:background="@drawable/minus_button"
                android:contentDescription="@string/deflate_back" />
    
            <!-- Arrown down button -->
    
            <ImageButton
                android:id="@+id/button_arrowdown"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@id/button_plus"
                android:layout_centerHorizontal="true"
                android:background="@drawable/arrowdown_button"
                android:contentDescription="@string/movedown_lumbar" />
    
            <!-- Home button -->
    
    
        </RelativeLayout>
    
        <!-- Right panel -->
    
        <!-- Screen -->
    
        <FrameLayout
            android:id="@+id/center_frame"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="20dp"
            android:layout_marginTop="7dp"
            android:layout_toRightOf="@id/lumbar_control"
            android:background="@drawable/screen" >
    
           <TextView
            android:id="@+id/text_state"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_margin="10dp"
            android:textSize="32sp"
            android:gravity="center"
            android:textColor="@color/white"
            android:text="hello"/>
    
            <!-- Seat screen -->
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/seat"
                android:src="@drawable/lumbar_control_seat"/>
    
            <com.SeatStateView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@drawable/lumbar_seat_state"
                android:id="@+id/lumbar_seat_state" />
    
        </FrameLayout>
    
        <!-- Home button -->
        <Button
            android:id="@+id/button_home"
            android:layout_width="332dp"
            android:layout_height="44dp"
            android:layout_centerHorizontal="true"
            android:background="@android:color/transparent"
            android:layout_alignParentBottom="true"
            android:contentDescription="@string/home_button"/>
    </RelativeLayout>
    

    腰痛状态:

    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
        <item android:drawable="@drawable/lumbar_seat_state_1" />
        <item android:drawable="@drawable/lumbar_seat_state_2" />
        <item android:drawable="@drawable/lumbar_seat_state_3" />
    </layer-list>
    

    腰部_位置_状态1:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com">
    
        <item android:drawable="@drawable/lumbar_inflate_1"
            app:state_inflating="true" />
        <item android:drawable="@drawable/lumbar_deflate_1"
            app:state_deflating="true" />
        <item android:drawable="@drawable/lumbar_idle_1" />
    </selector>
    

    SeatStateView.java:

    public class SeatStateView extends View {
    
        /* Custom states */
        private static final int[] INFLATING_STATE_SET = {
            R.attr.state_inflating
        };
    
        private static final int[] DEFLATING_STATE_SET = {
            R.attr.state_deflating
        };
    
        private static final int[] HEATING_STATE_SET = {
            R.attr.state_heating
        };
    
        private static final int[] COOLING_STATE_SET = {
            R.attr.state_cooling
        };
    
        /* Inflate/Deflate state */
        private boolean isInflating = false;
        private boolean isDeflating = false;
    
        /* Heating state */
        private boolean isHeating = false;
        private boolean isCooling = false;
    
        public SeatStateView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        // Overrides the onCreateDrawable to add our custom states
        @Override
        protected int[] onCreateDrawableState(int extraSpace) {
            final int[] drawableState = super.onCreateDrawableState(extraSpace + 2);
    
            // Checking the states
            if(isInflating) {
                mergeDrawableStates(drawableState, INFLATING_STATE_SET);
            }
    
            if(isDeflating) {
                mergeDrawableStates(drawableState, DEFLATING_STATE_SET);
            }
    
            if(isHeating) {
                mergeDrawableStates(drawableState, HEATING_STATE_SET);
            }
    
            if(isCooling) {
                mergeDrawableStates(drawableState, COOLING_STATE_SET);
            }
    
            return drawableState;
        }
    
        @Override
        protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){
           super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
           int parentWidth = MeasureSpec.getSize(widthMeasureSpec);
           int parentHeight = MeasureSpec.getSize(heightMeasureSpec);
           this.setMeasuredDimension(parentWidth, parentHeight);
        }
    
        /**
         * Clears all the states and set to idle.
         */
    
        public void setIdle() {
            isInflating = isDeflating = false;
    
            // Refresh view
            refreshDrawableState();
        }
    
        public void setInflating(boolean state) {
            if(isInflating != state) {
                // Update all the states
                isInflating = state;
    
                if(isInflating) {
                    isDeflating = false;
                }
    
                // Refresh view
                refreshDrawableState();
            }
        }
    
        public void setDeflating(boolean state) {
            if(isDeflating != state) {
                // Update all the states
                isDeflating = state;
    
                if(isDeflating) {
                    isInflating = false;
                }
    
                // Refresh view
                refreshDrawableState();
            }
        }
    
        public void setHeating(boolean state) {
            if(isHeating != state) {
                isHeating = state;
    
                if(state) {
                    isCooling = false;
                }
    
                // Refresh view
                refreshDrawableState();
            }
        }
    
        public void setCooling(boolean state) {
            if(isCooling != state) {
                isCooling = state;
    
                if(state) {
                    isHeating = false;
                }
    
                // Refresh view
                refreshDrawableState();
            }
        }
    }
    
    1 回复  |  直到 12 年前
        1
  •  0
  •   Community Mohan Dere    9 年前

    嗯,只是搜索了更多。发现我没有正确重写onMeasure方法。如果有人偶然发现了这个问题,下面是我的新实现:

    SeatStateView.java:

    @Override
    protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec){
    
        // Background image’s size
        int desiredWidth = getBackground().getIntrinsicWidth();
        int desiredHeight = getBackground().getIntrinsicHeight();
    
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
        // Final size
        int width, height;
    
        // Set width depending on mode
        if(widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        }
        else if(widthMode == MeasureSpec.AT_MOST) {
            width = Math.min(desiredWidth, widthSize);
        }
        else {
            width = desiredWidth;
        }
    
        // Set height depending on mode
        if(heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        }
        else if(widthMode == MeasureSpec.AT_MOST) {
            height = Math.min(desiredHeight, heightSize);
        }
        else {
            height = desiredHeight;
        }
    
        // Finally, set dimension
        setMeasuredDimension(width, height);
    }
    

    有关详细信息,请查看此页面: onMeasure custom view explanation .

    很抱歉打扰你。