Android: как нарисовать границу для LinearLayout

197

У меня есть три файла. XML, функция рисования и основная активность. У меня есть некоторые LinearLayoutв моем файле XML.

<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);
    }
}

И это основной вид деятельности:

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, но как я могу определить координаты центра?

SPG
источник

Ответы:

460

Вам действительно нужно сделать это программно?

Просто учитывая заголовок: вы можете использовать ShapeDrawable в качестве Android: фон ...

Например, давайте определим 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>

Сообщается о работе на пряничном устройстве. Обратите внимание, что вам нужно будет связать android:paddingLinearLayout со значением android:widthформы / обводки. Пожалуйста, не используйте @android:color/whiteв вашем окончательном приложении, а скорее проект определенного цвета.

Вы можете подать заявку android:background="@drawable/border" android:padding="10dip"на каждую из LinearLayout из предоставленного вами образца.

Что касается других ваших постов, связанных с отображением некоторых кругов в качестве фона LinearLayout, я играю с прорисовываемыми ресурсами Inset / Scale / Layer ( см. Drawable Resources для получения дополнительной информации), чтобы получить что-то работающее для отображения идеальных кругов на фоне LinearLayout, но не получилось в данный момент…

Ваша проблема заключается в использовании getBorder.set{Width,Height}(100);. Почему вы делаете это методом onClick?

Мне нужна дополнительная информация, чтобы не упустить момент: почему вы делаете это программно? Вам нужно динамическое поведение? Ваши входные данные в формате png или ShapeDrawable приемлемы? и т.п.

Продолжение следует (возможно, завтра и как только вы предоставите больше информации о том, чего хотите достичь)…

Renaud
источник
@Renaud есть ли способ изменить цвет рамки проблематично?
user1940676
12
Не знаю, почему это было так, но когда я использовал это для a, LinearLayoutя получил сплошную заливку из цвета границы, если только я не добавил следующий shapeэлемент к элементу:<solid android:color="@android:color/transparent" />
dahvyd
2
Для меня это было то же самое, что я должен был добавить, <solid android:color="@color/lighter_gray" />иначе я получил черный фон
Panciz
1
Этот метод отлично работает; тем не менее, он создает два слоя «Overdraw», что очень плохо сказывается на производительности, даже если вы установите фон «null» или «прозрачный». Может кто-нибудь предложить способ решить эту проблему?
Сэм Рамезанли
16

Расширьте 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>
Габриэль Риба
источник
34
Пожалуйста, не выделяйте память в onDraw()методе, создавайте свои объекты в init()методе, вызываемом конструктором, и повторно используйте их в onDraw()методе. Выделение onDraw()(вызывается 60 раз в секунду) ведет к снижению производительности, разряду батареи и т. Д.
Louis CAD