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.