Android: come disegnare un bordo su un LinearLayout


197

Ho tre file. L'XML, la funzione di disegno e l'attività principale. Ne ho alcuni LinearLayoutnel mio file 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>

Questa è la funzione di disegno:

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

E questa è l'attività principale:

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

Il programma potrebbe disegnare il bordo ma la dimensione non si adattava al LinearLayout. E quando clicco di LinearLayoutnuovo, il programma si arresta in modo anomalo.

Un'altra cosa, voglio disegnare due cerchi al centro del LinearLayout, ma come posso capire le coordinate del centro?

Risposte:


460

Hai davvero bisogno di farlo a livello di codice?

Solo considerando il titolo: potresti usare ShapeDrawable come Android: sfondo ...

Ad esempio, definiamo res/drawable/my_custom_background.xmlcome:

<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>

e definisci android: background = "@ drawable / my_custom_background".

Non ho testato, ma dovrebbe funzionare.

Aggiornare:

Penso che sia meglio sfruttare la potenza delle risorse disegnabili a forma di xml se si adatta alle tue esigenze. Con un progetto "da zero" (per Android-8), definire 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>

e a 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>

Riferito per funzionare su un dispositivo di pan di zenzero. Nota che dovrai correlare android:paddingil LinearLayout al valore della android:widthforma / tratto. Per favore, non usare @android:color/whitenella tua applicazione finale ma piuttosto un colore definito dal progetto.

È possibile applicare android:background="@drawable/border" android:padding="10dip"a ciascuno dei LinearLayout dal campione fornito.

Per quanto riguarda gli altri tuoi post relativi alla visualizzazione di alcuni cerchi come sfondo di LinearLayout, sto giocando con risorse disegnabili Inset / Scale / Layer ( vedi Risorse disegnabili per ulteriori informazioni) per ottenere qualcosa che funzioni per visualizzare cerchi perfetti sullo sfondo di un LinearLayout ma non è riuscito al momento…

Il tuo problema risiede chiaramente nell'uso di getBorder.set{Width,Height}(100);. Perché lo fai in un metodo onClick?

Ho bisogno di ulteriori informazioni per non perdere il punto: perché lo fai programmaticamente? Hai bisogno di un comportamento dinamico? I tuoi drawable di input sono png o ShapeDrawable è accettabile? eccetera.

Continua (forse domani e non appena fornirai maggiori precisazioni su ciò che vuoi ottenere) ...



@Renaud c'è un modo per cambiare il colore del bordo in modo problematico?
user1940676

12
Non sono sicuro del perché, ma quando l'ho usato su un LinearLayoutho ottenuto un solido riempimento dal colore del bordo, a meno che non aggiungessi il seguente figlio shapeall'elemento:<solid android:color="@android:color/transparent" />
dahvyd

2
Per me è stato lo stesso che ho dovuto aggiungere un, <solid android:color="@color/lighter_gray" />altrimenti ho avuto uno sfondo nero
Panciz

1
Questo metodo funziona perfettamente; tuttavia, crea "Overdraw" a due livelli, il che è davvero negativo per le prestazioni, anche se si imposta lo sfondo su "null" o "trasparente". Qualcuno può suggerire un modo per risolvere questo problema?
Sam Ramezanli,

16

Estendi LinearLayout / RelativeLayout e utilizzalo direttamente sull'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
Per favore, non allocare memoria nel onDraw()metodo, crea i tuoi oggetti in un init()metodo, chiamato dal costruttore e riutilizzali nel onDraw()metodo. L'allocazione onDraw()(chiamata 60 volte al secondo) comporta scarse prestazioni, consumo della batteria, ecc.
Louis CAD
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.