Android: So zeichnen Sie einen Rahmen für ein LinearLayout

197

Ich habe drei Dateien. Das XML, die Zeichenfunktion und die Hauptaktivität. Ich habe einige LinearLayoutin meiner XML-Datei.

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

Dies ist die Zeichenfunktion:

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

Und das ist die Hauptaktivität:

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

Das Programm konnte einen Rand zeichnen, aber die Größe passte nicht zum LinearLayout. Und wenn ich erneut auf klicke LinearLayout, stürzt das Programm ab.

Eine andere Sache, ich möchte zwei Kreise in der Mitte des zeichnen LinearLayout, aber wie könnte ich die Mittelkoordinaten herausfinden?

SPG
quelle

Antworten:

458

Müssen Sie das wirklich programmgesteuert tun?

Nur unter Berücksichtigung des Titels: Sie könnten ein ShapeDrawable als Android verwenden: Hintergrund…

Definieren wir zum Beispiel Folgendes 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>

und definiere android: background = "@ drawable / my_custom_background".

Ich habe nicht getestet, aber es sollte funktionieren.

Aktualisieren:

Ich denke, dass es besser ist, die Ressourcenleistung der XML-Form zu nutzen, wenn dies Ihren Anforderungen entspricht. Definieren Sie mit einem "von Grund auf neu" -Projekt (für 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>

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

Berichten zufolge an einem Lebkuchengerät arbeiten. Beachten Sie, dass Sie android:paddingdas LinearLayout mit dem android:widthWert der Form / des Strichs in Beziehung setzen müssen . Bitte nicht verwenden@android:color/white in Ihrer endgültigen Anwendung, sondern eine projektdefinierte Farbe.

Sie können android:background="@drawable/border" android:padding="10dip"jedes LinearLayout aus Ihrem bereitgestellten Beispiel anwenden .

Was Ihre anderen Beiträge betrifft, die sich auf die Anzeige einiger Kreise als Hintergrund von LinearLayout beziehen, spiele ich mit zeichnbaren Ressourcen für Einfügung / Skalierung / Ebene ( siehe Zeichnungsressourcen) weitere Informationen finden ), damit etwas funktioniert, um perfekte Kreise im Hintergrund eines LinearLayout anzuzeigen, was jedoch fehlgeschlagen ist im Moment…

Ihr Problem liegt eindeutig in der Verwendung von getBorder.set{Width,Height}(100); . Warum machen Sie das in einer onClick-Methode?

Ich brauche weitere Informationen, um den Punkt nicht zu verpassen: Warum machst du das programmgesteuert? Benötigen Sie ein dynamisches Verhalten? Ihre Eingabe Drawables sind PNG oder ShapeDrawable ist akzeptabel? etc.

Fortsetzung folgt (vielleicht morgen und sobald Sie mehr Präzisionen für das geben, was Sie erreichen möchten)…

Renaud
quelle
@Renaud gibt es eine Möglichkeit, die Rahmenfarbe problematisch zu ändern?
user1940676
12
Ich bin mir nicht sicher, warum dies der Fall war, aber als ich dies für eine verwendete, erhielt LinearLayoutich eine feste Füllung aus der shape<solid android:color="@android:color/transparent" />
Rahmenfarbe
2
Für mich war es das gleiche, was ich hinzufügen musste, <solid android:color="@color/lighter_gray" />sonst bekam ich einen schwarzen Hintergrund
Panciz
1
Diese Methode funktioniert perfekt; Es wird jedoch eine zweischichtige "Überzeichnung" erstellt, was für die Leistung sehr schlecht ist, selbst wenn Sie den Hintergrund auf "null" oder "transparent" setzen. Kann jemand einen Weg vorschlagen, um dieses Problem zu beheben?
Sam Ramezanli
16

Erweitern Sie LinearLayout / RelativeLayout und verwenden Sie es direkt im 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>
Gabriel Riba
quelle
34
Bitte ordnen Sie keinen Speicher in der onDraw()Methode zu, erstellen Sie Ihre Objekte in einer init()vom Konstruktor aufgerufenen Methode und verwenden Sie sie in der onDraw()Methode wieder. Das Zuweisen onDraw()(60-mal pro Sekunde aufgerufen) führt zu schlechter Leistung, Batterieentladung usw.
Louis CAD