Android:如何为LinearLayout绘制边框

220

我有三个文件:XML文件、绘图函数和主Activity。 我的XML文件中有一些LinearLayout。

<LinearLayout android:orientation="horizontal"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:layout_weight="1">
    <LinearLayout android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_weight="1"
                  android:background="#ef3"
                  android:id="@+id/img01"/>
    <LinearLayout android:layout_width="fill_parent"
                  android:layout_height="fill_parent"
                  android:layout_weight="1"
                  android:background="#E8A2B4"
                  android:id="@+id/img02"/>
</LinearLayout>

这是绘制函数:

public class getBorder extends TextView {
    public getBorder(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();

        paint.setColor(android.graphics.Color.RED);

        canvas.drawLine(0, 0, this.getWidth() - 1, 0, paint);
        canvas.drawLine(0, 0, 0, this.getHeight() - 1, paint);
        canvas.drawLine(this.getWidth() - 1, 0, this.getWidth() - 1,
            this.getHeight() - 1, paint);
        canvas.drawLine(0, this.getHeight() - 1, this.getWidth() - 1,
            this.getHeight() - 1, paint);
    }
}

这是主 Activity:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    final getBorder getBorder = new getBorder(this);
    final LinearLayout img01 = (LinearLayout) findViewById(R.id.img01);
    img01.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            getBorder.setWidth(100);
            getBorder.setHeight(100);
            img01.addView(getBorder);
        }
    });       
}

程序可以绘制边框,但大小不适合LinearLayout。当我再次点击LinearLayout时,程序崩溃了。

此外,我想在LinearLayout的中心绘制两个圆圈,但是我该如何找出中心坐标?

2个回答

503

你真的需要以编程方式实现这个吗?

仅考虑标题:你可以使用 ShapeDrawable 作为 android:background...

例如,我们定义 res/drawable/my_custom_background.xml 如下:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
  <corners
      android:radius="2dp"
      android:topRightRadius="0dp"
      android:bottomRightRadius="0dp"
      android:bottomLeftRadius="0dp" />
  <stroke
      android:width="1dp"
      android:color="@android:color/white" />
</shape>

并定义android:background="@drawable/my_custom_background"。

我还没有测试过,但应该可以工作。

更新:

如果适合您的需求,则最好利用xml形状可绘制资源的功能。使用“从头开始”项目(适用于android-8),定义res/layout/main.xml。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/border"
    android:padding="10dip" >
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World, SOnich"
        />
    [... more TextView ...]
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World, SOnich"
        />
</LinearLayout>

res/drawable/border.xml 一起使用

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
   <stroke
        android:width="5dip"
        android:color="@android:color/white" />
</shape>

经报告,在Gingerbread设备上运行。请注意,您需要将LinearLayout的android:paddingandroid:width形状/描边的值相关联。请勿在最终应用程序中使用@ android:color / white ,而是使用项目定义的颜色。

您可以将android:background =“@ drawable / border”android:padding =“10dip”应用于提供的示例中的每个LinearLayout。

至于您其他帖子与显示一些圆形作为LinearLayout背景有关,我正在使用Inset / Scale / Layer可绘制资源(请参见Drawable资源了解更多信息)来获取一些工作以在LinearLayout的背景中显示完美的圆,但目前失败了...

显然,您的问题在于使用getBorder.set{Width,Height}(100);。为什么要在onClick方法中这样做?

我需要进一步的信息来不错过重点:为什么要以编程方式执行此操作?您需要动态行为吗?您的输入可绘制对象是png还是ShapeDrawable可接受?等等。

待续(也许明天,并且只要您提供更多有关所需实现的信息)...


如果我需要在填充内添加边框,而不是在边框内部添加填充,该怎么办?我真的需要创建一个带有填充的布局,然后在其中放置一个具有背景的布局(该布局也具有填充,但在可绘制的 XML 文件中)吗? - android developer
13
不确定原因,但当我将此应用于LinearLayout时,边框颜色填充了整个区域,除非我在shape元素中添加以下子元素:<solid android:color="@android:color/transparent" />。 - dahvyd
2
对我而言,我必须添加<solid android:color="@color/lighter_gray" />,否则背景会变成黑色。 - Panciz
@Renaud 我想在Xamarin.Android中做同样的事情,所以我必须转换Java代码。你能给我一个简单但完整的解决方案,包括你的示例代码(即使是Java),这样我就可以开始工作了,因为我无法实现这段代码。 - Code Pope
1
这种方法完美地工作了,但是它会创建两层“过度绘制”,这对性能来说真的很糟糕,即使你将背景设置为“null”或“透明”。有人能提出解决这个问题的方法吗? - Sam Ramezanli
显示剩余3条评论

18

扩展LinearLayout/RelativeLayout并直接在XML中使用它

package com.pkg_name ;
...imports...
public class LinearLayoutOutlined extends LinearLayout {
    Paint paint;    

    public LinearLayoutOutlined(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        setWillNotDraw(false) ;
        paint = new Paint();
    }
    public LinearLayoutOutlined(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        setWillNotDraw(false) ;
        paint = new Paint();
    }
    @Override
    protected void onDraw(Canvas canvas) {
        /*
        Paint fillPaint = paint;
        fillPaint.setARGB(255, 0, 255, 0);
        fillPaint.setStyle(Paint.Style.FILL);
        canvas.drawPaint(fillPaint) ;
        */

        Paint strokePaint = paint;
        strokePaint.setARGB(255, 255, 0, 0);
        strokePaint.setStyle(Paint.Style.STROKE);
        strokePaint.setStrokeWidth(2);  
        Rect r = canvas.getClipBounds() ;
        Rect outline = new Rect( 1,1,r.right-1, r.bottom-1) ;
        canvas.drawRect(outline, strokePaint) ;
    }

}

<?xml version="1.0" encoding="utf-8"?>

<com.pkg_name.LinearLayoutOutlined
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
    android:layout_width=...
    android:layout_height=...
   >
   ... your widgets here ...

</com.pkg_name.LinearLayoutOutlined>

39
请勿在onDraw()方法中分配内存,应该在init()方法中创建对象,在构造函数中调用init()方法,并在onDraw()方法中重复使用这些对象。在onDraw()方法中分配内存(每秒调用60次)会导致性能下降、耗电等问题。 - Louis CAD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接