android中的自定义视图

Posted

技术标签:

【中文标题】android中的自定义视图【英文标题】:Custom views in android 【发布时间】:2013-08-17 10:03:15 【问题描述】:

我刚开始学习如何制作自定义视图。我在屏幕底部创建了一个可绘制对象,并在其中创建了一个小圆圈。布局工作得很好,但有一个小问题,不同分辨率的可绘制对象被裁剪。它在 S3 中运行良好,但在其他设备中情况有所不同。

这是我的代码:

 @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) 


    int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
            MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
            MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);


    setMeasuredDimension(childWidthMeasureSpec,childHeightMeasureSpec);





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

    Drawable outer_ring = getResources().getDrawable(R.drawable.outer_ring);

    System.out.println("Height now is : "+(canvas.getHeight()));

    Rect r1 = new Rect();
    r1.top = (canvas.getHeight()-outer_ring.getIntrinsicHeight());
    r1.bottom = canvas.getHeight();
    r1.left = (canvas.getWidth()-outer_ring.getIntrinsicWidth())/2;
    r1.right = canvas.getWidth()/2 +outer_ring.getIntrinsicWidth()/2;

    outer_ring.setBounds(r1);
    outer_ring.draw(canvas);

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(Color.BLACK);
    paint.setStyle(Style.STROKE);
    paint.setStrokeWidth(10.0f);

    canvas.drawCircle(canvas.getWidth()/2, ((canvas.getHeight()-outer_ring.getIntrinsicHeight()/2)), 20, paint);

这个视图在所有分辨率上都显示相同的解决方案应该是什么

这是我的布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_
    android:layout_
    android:orientation="vertical" >



    <com.example.testing.CustomMenu
        android:layout_
        android:layout_
        android:id="@+id/myView"
        />

    <Button
        android:id="@+id/button1"
        android:layout_
        android:layout_
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Button" />

</RelativeLayout>

【问题讨论】:

你能在两个设备上记录 r1.bottom 的值吗?它们与设备的高度相同吗? 是的,我做到了。在 S3 中,它比设备高度略小:1134,然后是实际的 1280。在其他分辨率为 480 x 854 的设备中,它显示的确切值 你能把你的完整的onDraw(),有遗漏的部分 我已添加代码,请立即查看 问题出在 getIntrinsicHeight() 方法上,它只返回环的未修改高度,例如,如果它的高度是 200px,那么它在 s3 和其他设备上都会返回 200。改用 getWidth() 【参考方案1】:

编辑

事实证明,提供给onDraw 的画布大小不能保证与View 的实际查看大小相同。它只是保证足够大。在你的情况下,它太大了!

根据this question and answer,关键是使用onSizeChanged 中返回的尺寸作为View 当前显示尺寸的确定。所以你应该保留onSizeChanged 的尺寸,并在onDraw 中使用它们来了解你应该绘制的实际尺寸。 ,:

childWidthMeasureSpecchildHeightMeasureSpec 应该成为在 onSizeChanged 中设置的类变量。 在onDraw 中,分别使用它们代替canvas.getWidth()canvas.getHeight()

虽然这种行为乍一看有点奇怪,但它允许 android 在整理大小时减少它重新分配的画布数量:如果 View 缩小一点(例如) > 顶部栏的外观)它所做的一切都告诉所有相关人员,实际尺寸要小一些,而不是通过画布发布和重新创建循环。

可能不太重要,在您的 java 代码中,您请求您正在绘制的 View 的尺寸。在 xml 中,您将这些维度设置为 wrap_content。这意味着没有明确设置View 的大小。像这样的视图应该请求它可以达到的最大尺寸,并确定它希望得到多大的尺寸,并将其设置为它的尺寸。更明智的做法是通过将CustomMenu 的大小设置为match_patent 来确保尺寸固定,这样它们就固定了。

但是,如果没有这个,父 View 给了你一些界限。看来这些界限可能会或可能不会考虑到顶部栏,这很公平。

【讨论】:

感谢您的时间和解决方案。这真的很有帮助,解决了我的问题。你付出的所有努力终于有了成果。【参考方案2】:

尝试使用this.getHeight() 代替canvas.getHeight()this.getWidth() 代替canvas.getWidth()

thisView 相关)

【讨论】:

我也将尝试您的选择,但请参阅 Neils 的评论和解决方案。这解决了我的问题

以上是关于android中的自定义视图的主要内容,如果未能解决你的问题,请参考以下文章

如何删除android中的自定义列表视图项?

Android中的自定义视图控件

如何为android中的所有视图使用相同的自定义字体?

我在哪里定义我的 OnClickListener 以关闭 Android 中的自定义对话框视图?

如何在android中的自定义圆角图像视图中设置图像

无法从android中的自定义列表视图中获取所选项目