读书人

移植自定义View过程中遇到的有关问题及

发布时间: 2013-02-28 11:33:09 作者: rapoo

移植自定义View过程中遇到的问题及解决方法

移植自定义View过程中遇到的问题及解决方法

2012-01-12

问题背景:最近在做camera界面调整的时候,界面需要参考2.3.5的switcher控件,如下:

移植自定义View过程中遇到的有关问题及解决办法

功能是相机和摄像机相互切换,在移植到SP8825平台上时,发现布局出现颠倒现象,变为:

移植自定义View过程中遇到的有关问题及解决办法

跟踪到相应布局文件,发现最外层LinearLayout的orientation是vertical即垂直布局,改成水平的horizontal后布局变成:

移植自定义View过程中遇到的有关问题及解决办法

再次查看图片,发现图片是垂直的,再次把图片旋转,这次布局正常了,但是发现里面小圆圈开关滑动到右侧的时候就消失了,怎么调也调不出来,在这里卡住了很久,今天终于完美解决,问题现象如下:

移植自定义View过程中遇到的有关问题及解决办法滑动小圆圈开关-->移植自定义View过程中遇到的有关问题及解决办法 继续滑动-->移植自定义View过程中遇到的有关问题及解决办法

再滑动-->移植自定义View过程中遇到的有关问题及解决办法 再往右滑就变成-->移植自定义View过程中遇到的有关问题及解决办法 小圆圈开关消失

期间加了很多Log跟踪调试,定位问题在自定义view的Switcher.java文件中,发现控件的getWidth()值和getHeight()的值均是57,这里发现就是小圆圈的长宽,getWidth()这个是View.java中的方法,布局代码如下:

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/camera_switch_set"

android:orientation="horizontal"

android:layout_alignParentRight="true"

android:layout_marginBottom="30dp"

android:layout_centerInParent="true"

android:layout_height="wrap_content"

android:layout_width="wrap_content">

<com.android.camera.RotateImageViewandroid:id="@+id/video_switch_icon"

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:src="@drawable/btn_ic_mode_switch_video"/>

<LinearLayout

android:orientation="horizontal"

android:layout_width="70dp"

android:layout_height="35dp"

android:background="@drawable/btn_mode_switch_bg">

<com.android.camera.Switcher>切换控件

android:id="@+id/camera_switch"

android:layout_width="wrap_content"

android:layout_height="match_parent"

android:src="@drawable/btn_mode_switch_knob" />

</LinearLayout>

<com.android.camera.RotateImageView

android:id="@+id/camera_switch_icon"

android:layout_height="wrap_content"

android:layout_width="wrap_content"

android:layout_marginBottom="3dp"

android:src="@drawable/btn_ic_mode_switch_camera"/>

</LinearLayout>

Switcher继承的是ImageView类,如果在Switcher.java文件中调用getWidth()方法,得到的应该是上述代码中标记为浅蓝色LinearLayout的背景的宽度,也即btn_mode_switch_bg这张图片的宽度,而实际结果并不是如此。

于是重新看了一下自定义View的一些事项:

发现自定义view中有一个onMeasure()方法,查看该方法的作用:

onMeasure方法在控件的父元素正要放置它的子控件时调用。它会问一个问题,“你想要用多大地方啊?”,然后传入两个参数——widthMeasureSpec和heightMeasureSpec。

它们指明控件可获得的空间以及关于这个空间描述的元数据。

比返回一个结果要好的方法是你传递View的高度和宽度到setMeasuredDimension方法里。

接下来的代码片段给出了如何重写onMeasure。注意,调用的本地空方法是来计算高度和宽度的。它们会译解widthHeightSpec和heightMeasureSpec值,并计算出合适的高度和宽度值。

查看后明白:要解决此问题,必须要重写这个方法:

@Override

protectedvoid onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

setMeasuredDimension(getMeasuredLength(widthMeasureSpec,true),getMeasuredLength(heightMeasureSpec, false));

}

private int getMeasuredLength(int length,boolean isWidth) {

intspecMode = MeasureSpec.getMode(length);

intspecSize = MeasureSpec.getSize(length);

intsize;

intpadding = isWidth ? getPaddingLeft() + getPaddingRight()

:getPaddingTop() + getPaddingBottom();

if(specMode == MeasureSpec.EXACTLY) {

size= specSize;

}else {

size = isWidth ? padding + getDrawable().getIntrinsicWidth()* 2 : getDrawable().getIntrinsicHeight() + padding;//这里指定相应的宽度和高度

if(specMode == MeasureSpec.AT_MOST) {

size= Math.min(size, specSize);

}

}

returnsize;

}

至此,这个问题终于解决完成了~

读书人网 >移动开发

热点推荐