Android: cara menggambar perbatasan ke LinearLayout

197

Saya punya tiga file. XML, fungsi draw, dan Activity utama. Saya punya beberapa LinearLayoutdi file XML saya.

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

Ini adalah fungsi undian:

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

Dan ini adalah Kegiatan utama:

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

Program bisa menggambar garis batas tetapi ukurannya tidak sesuai LinearLayout. Dan ketika saya mengklik LinearLayoutlagi, program macet.

Hal lain, saya ingin menggambar dua lingkaran di tengah LinearLayout, tetapi bagaimana saya bisa mengetahui koordinat pusat?

SPG
sumber

Jawaban:

460

Apakah Anda benar-benar perlu melakukan itu secara terprogram?

Hanya dengan mempertimbangkan judulnya: Anda bisa menggunakan ShapeDrawable sebagai android: latar belakang ...

Sebagai contoh, mari kita definisikan res/drawable/my_custom_background.xmlsebagai:

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

dan tentukan android: background = "@ drawable / my_custom_background".

Saya belum diuji tetapi harus bekerja.

Memperbarui:

Saya pikir itu lebih baik untuk memanfaatkan kekuatan sumber daya xml bentuk menarik jika itu sesuai dengan kebutuhan Anda. Dengan proyek "dari awal" (untuk android-8), tentukan 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>

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

Dilaporkan untuk bekerja pada perangkat roti jahe. Perhatikan bahwa Anda harus menghubungkan android:paddingLinearLayout dengan nilai android:widthbentuk / goresan itu. Tolong, jangan gunakan@android:color/white dalam aplikasi akhir Anda melainkan warna yang ditentukan proyek.

Anda dapat menerapkan android:background="@drawable/border" android:padding="10dip"ke setiap LinearLayout dari sampel yang Anda berikan.

Adapun posting Anda yang lain terkait dengan menampilkan beberapa lingkaran sebagai latar belakang LinearLayout, saya bermain dengan sumber daya yang dapat ditarik Inset / Scale / Layer ( lihat Sumber Daya yang Dapat Diambil untuk informasi lebih lanjut) untuk mendapatkan sesuatu yang berfungsi menampilkan lingkaran sempurna di latar belakang LinearLayout tetapi gagal saat ini…

Masalah Anda terletak dengan jelas dalam penggunaan getBorder.set{Width,Height}(100); . Mengapa Anda melakukannya dalam metode onClick?

Saya memerlukan informasi lebih lanjut untuk tidak melewatkan intinya: mengapa Anda melakukan itu secara terprogram? Apakah Anda memerlukan perilaku yang dinamis? Input Anda dapat digambar png atau ShapeDrawable dapat diterima? dll.

Untuk dilanjutkan (mungkin besok dan segera setelah Anda memberikan lebih banyak persiapan tentang apa yang ingin Anda capai) ...

Renaud
sumber
@Renaud apakah ada cara untuk mengubah warna tepi bermasalah?
user1940676
12
Tidak yakin mengapa itu terjadi, tetapi ketika saya menggunakan ini pada LinearLayoutsaya mendapat warna solid dari warna perbatasan, kecuali saya menambahkan anak berikut ke shapeelemen:<solid android:color="@android:color/transparent" />
dahvyd
2
Bagi saya itu sama dengan yang saya harus tambahkan, <solid android:color="@color/lighter_gray" />kalau tidak saya punya latar belakang hitam
Panciz
1
Metode ini berfungsi sempurna; namun, ia menciptakan dua lapisan "Overdraw" yang benar-benar buruk untuk kinerja, bahkan jika Anda mengatur latar belakang ke "null" atau "transparan". Adakah yang bisa menyarankan cara untuk memperbaiki masalah ini?
Sam Ramezanli
16

Perluas LinearLayout / RelativeLayout dan gunakan langsung pada 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
sumber
34
Tolong, jangan mengalokasikan memori dalam onDraw()metode, membuat objek Anda dalam suatu init()metode, dipanggil oleh konstruktor dan menggunakannya kembali dalam onDraw()metode. Mengalokasikan dalam onDraw()(disebut 60 kali per detik) menyebabkan kinerja yang buruk, menguras baterai, dll
Louis CAD