Kırpma Tuval Nesneleri

Bu codelab, Kotlin'deki Gelişmiş Android kursuna dahildir. Codelab'ler sırasında sırayla çalıştığınızda bu kurstan en yüksek değeri elde edersiniz ancak zorunlu değildir. Tüm kurs codelab'leri Kotlin Codelab'de Gelişmiş Android açılış sayfasında listelenmiştir.

Giriş

Bu codelab'in amacı doğrultusunda, klips bir resmin, tuvalin veya bit eşlemin bölgelerinin seçici bir şekilde çizilmiş veya ekrana çizilmemiş olan bölgelerini tanımlamanın bir yoludur. Kırpmanın amaçlarından biri, aşırı çizimi azaltmaktır. Geri çekme, ekrandaki bir pikselin son resmi görüntülemek için birden fazla kez çizilmesidir. Fazla çizimi azalttığınızda, çizim performansını en üst düzeye çıkarmak için ekranın bir pikseli veya bölgesinin çizilme sayısını en aza indirirsiniz. Ayrıca, kullanıcı arayüzü tasarımında ve animasyonunda ilginç efektler oluşturmak için kırpma özelliğini kullanabilirsiniz.

Örneğin, aşağıda gösterildiği gibi, çakışan kartlar yığınını çizdiğinizde, her kartı en alttan aşağıya doğru tamamen çizmek yerine, genellikle yalnızca görünür bölümleri çizmek daha verimli olur. "Kırpma işlemlerinin de maliyeti olduğundan ve genel olarak Android sistemi çizim optimizasyonu açısından oldukça başarılı olduğundan "Genellikle" denir.

Kartların yalnızca görünür kısımlarını çizmek için her karta bir kırpma bölgesi belirtirsiniz. Örneğin, aşağıdaki şemada bir resme kırpma dikdörtgeni uygulandığında yalnızca bu dikdörtgenin içindeki bölüm gösterilir.

Kırpma bölgesi genellikle dikdörtgendir ancak herhangi bir şekil veya şekil bileşimi (metin bile olabilir) olabilir. Kırpma bölgesinin dahil olduğu bölgenin dahil edilip edilmeyeceğini de belirtebilirsiniz. Örneğin, dairesel bir kırpma bölgesi oluşturup yalnızca dairenin dışında kalan öğeleri görüntüleyebilirsiniz.

Bu codelab'de, çeşitli kırpma yöntemleriyle denemeler yapacaksınız.

Bilmeniz gerekenler

Aşağıdaki konular hakkında bilgi sahibi olmalısınız:

  • Activity ile uygulama oluşturma ve Android Studio'yu kullanarak uygulama çalıştırma.
  • Canvas oluşturma ve çizim yapma.
  • Özel View oluşturma ve onDraw() ile onSizeChanged() değerlerini geçersiz kılma.

Neler öğreneceksiniz?

  • Canvas üzerinde çizilen nesneler nasıl kırpılır?
  • Bir tuvalin çizim durumlarını kaydetme ve geri yükleme.
  • Tuvale ve metne dönüşüm uygulama.

Yapacaklarınız

  • Ekran üzerinde kesik şekiller çizmenin farklı yollarını ve bu şekillerin görünürlüğüyle ilgili sonuçları gösteren bir uygulama oluşturun.
  • Çevrilmiş ve çevrilmiş metinler de çizeceksiniz.

ClippingExample uygulaması, bir tuvalin hangi kısımlarının görünümde gösterileceğini belirlemek için şekilleri nasıl kullanabileceğinizi ve birleştirebileceğinizi gösterir. Son uygulamanız aşağıdaki ekran görüntüsünde bulunacaktır.

Bu uygulamayı sıfırdan derleyeceğiniz için bir proje oluşturmanız, boyutlar ile dizeleri tanımlamanız ve bazı değişkenleri bildirmeniz gerekir.

1. Adım: ClippingExample projesi oluşturun

  1. Boş Etkinlik şablonuyla ClippingExample adında bir Kotlin projesi oluşturun. Paket adı ön eki için com.example.android kullanın.
  2. MainActivity.kt'yi açın.
  3. onCreate() yönteminde varsayılan içerik görünümünü değiştirin ve içerik görünümünü yeni bir ClippedView örneği olarak ayarlayın. Bu, daha sonra oluşturacağınız klip oluşturma örnekleri için özel görünümünüz olacaktır.
setContentView(ClippedView(this))
  1. MainActivity.kt ile aynı düzeyde, yeni bir Kotlin dosyası ve sınıfı oluşturarak ClippedView adında, View uzantısındaki bir görünüm oluşturun. Fotoğrafa aşağıda gösterilen imzayı verin. Çalışmanızın kalanı bu ClippedView içinde yer alacak. @JvmOverloads ek açıklaması, Kotlin derleyicisine bu işlev için varsayılan parametre değerlerinin yerini alacak aşırı yüklemeler oluşturma talimatı verir.
class ClippedView @JvmOverloads constructor(
   context: Context,
   attrs: AttributeSet? = null,
   defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {
}

2. Adım: Boyut ve dize kaynaklarını ekleyin

  1. res/values/dimens.xml ürününde yeni kaynaklar dosyasında, kırpılmış görünümler için kullanacağınız boyutları tanımlayın. Bu varsayılan boyutlar, oldukça küçük bir ekrana sığacak şekilde kodlanır ve boyutlandırılır.
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="clipRectRight">90dp</dimen>
   <dimen name="clipRectBottom">90dp</dimen>
   <dimen name="clipRectTop">0dp</dimen>
   <dimen name="clipRectLeft">0dp</dimen>

   <dimen name="rectInset">8dp</dimen>
   <dimen name="smallRectOffset">40dp</dimen>

   <dimen name="circleRadius">30dp</dimen>
   <dimen name="textOffset">20dp</dimen>
   <dimen name="strokeWidth">4dp</dimen>

   <dimen name="textSize">18sp</dimen>
</resources>

Uygulamanın daha büyük bir ekranda iyi görünmesi (ve ayrıntıları daha kolay görebilmek için) yalnızca daha büyük ekranlar için geçerli olan daha büyük değerlere sahip bir dimens dosyası oluşturabilirsiniz.

  1. Android Studio'da, values klasörünü sağ tıklayın ve Yeni > Değerler kaynak dosyası'nı seçin.
  2. New Resource File iletişim kutusunda, dimens dosyasını çağırın. Kullanılabilir niteleyiciler'de En Küçük Ekran Genişliği'ni seçin ve >> düğmesini tıklayarak Cosen niteleyicilerine ekleyin. En küçük ekran genişliği kutusuna 480 sayısını girip Tamam'ı tıklayın.

  1. Dosya, aşağıda gösterildiği gibi değerler klasörünüzde gösterilmelidir.

  1. Dosyayı göremiyorsanız uygulamanın Proje Dosyaları görünümüne geçin. Yeni dosyanın tam yolu aşağıda gösterilmiştir: ClippingExample/app/src/main/res/values-sw480dp/dimens.xml.

  1. values-sw480dp/dimens.xml dosyasının varsayılan içeriğini aşağıdaki boyutlarla değiştirin.
<?xml version="1.0" encoding="utf-8"?>
<resources>
   <dimen name="clipRectRight">120dp</dimen>
   <dimen name="clipRectBottom">120dp</dimen>

   <dimen name="rectInset">10dp</dimen>
   <dimen name="smallRectOffset">50dp</dimen>

   <dimen name="circleRadius">40dp</dimen>
   <dimen name="textOffset">25dp</dimen>
   <dimen name="strokeWidth">6dp</dimen>
</resources>
  1. strings.xml satırına aşağıdaki dizeleri ekleyin. Bunlar, zemindeki metni görüntülemek için kullanılır.
<string name="clipping">Clipping</string>
<string name="translated">translated text</string>
<string name="skewed">"Skewed and "</string>

3. Adım: Boyama ve Yol nesnesi oluşturun ve başlatın

  1. Projenizin Android görünümüne geri dönün.
  2. ClippedView dilinde, çizilecek bir Paint değişkeni tanımlayın. Takma ad kaldırma özelliğini etkinleştirin ve aşağıda gösterildiği gibi boyutlarda tanımlanan fırça genişliği ve metin boyutunu kullanın.
private val paint = Paint().apply {
   // Smooth out edges of what is drawn without affecting shape.
   isAntiAlias = true
   strokeWidth = resources.getDimension(R.dimen.strokeWidth)
   textSize = resources.getDimension(R.dimen.textSize)
}
  1. ClippedView ürününde, çizilenin yolunu yerel olarak depolamak için bir Path oluşturun ve ilk kullanıma hazırlayın. android.graphics.Path aktarın.
private val path = Path()

4. Adım: Şekilleri ayarlayın

Bu uygulamada, çeşitli şekillerde kırpılmış birkaç satır ve şekilli iki sütun görüntülüyorsunuz.

Bunların hepsi ortaktır:

  • Kapsayıcı görevi gören büyük bir dikdörtgen (kare)
  • Büyük dikdörtgenin üzerinde çapraz bir çizgi
  • Daire
  • Kısa bir metin dizesi

Bu adımda, kaynaklardan bu şekiller için boyutlar ayarlarsınız. Böylece boyutları daha sonra yalnızca bir kez kullanabilirsiniz.

  1. ClippedView öğesinde path altına, tüm şekil grubunun etrafındaki kırpma dikdörtgeninin boyutları için değişkenler ekleyin.
private val clipRectRight = resources.getDimension(R.dimen.clipRectRight)
private val clipRectBottom = resources.getDimension(R.dimen.clipRectBottom)
private val clipRectTop = resources.getDimension(R.dimen.clipRectTop)
private val clipRectLeft = resources.getDimension(R.dimen.clipRectLeft)
  1. Bir dikdörtgenin başlangıcı ve küçük bir dikdörtgenin ofseti için değişkenler ekleyin.
private val rectInset = resources.getDimension(R.dimen.rectInset)
private val smallRectOffset = resources.getDimension(R.dimen.smallRectOffset)
  1. Bir dairenin yarıçapı için değişken ekleyin. Bu, dairenin içinde çizilen dairenin yarıçapıdır.
private val circleRadius = resources.getDimension(R.dimen.circleRadius)
  1. Dikdörtgenin içine çizilen metin için bir ofset ve metin boyutu ekleyin.
private val textOffset = resources.getDimension(R.dimen.textOffset)
private val textSize = resources.getDimension(R.dimen.textSize)

4. Adım: Satır ve sütun konumlarını ayarlayın

Bu uygulamanın şekilleri, yukarıda ayarlanan boyutların değerleriyle belirlenen iki sütun ve dört satırda görüntülenir. Matematik bölümü bu codelab'in bir parçası değildir, ancak bu adımda verilen koda kopyalarken ona bakın.

  1. İki sütun için koordinatları ayarlayın.
private val columnOne = rectInset
private val columnTwo = columnOne + rectInset + clipRectRight
  1. Dönüştürülen metnin son satırı da dahil olmak üzere her satır için koordinatları ekleyin.
private val rowOne = rectInset
private val rowTwo = rowOne + rectInset + clipRectBottom
private val rowThree = rowTwo + rectInset + clipRectBottom
private val rowFour = rowThree + rectInset + clipRectBottom
private val textRow = rowFour + (1.5f * clipRectBottom)
  1. Uygulamanızı çalıştırın. Uygulama, uygulama adının altında boş bir beyaz ekranla açılır.

onDraw() uygulamasında, aşağıdaki uygulama ekran görüntüsünde gösterildiği gibi yedi farklı kırpılmış dikdörtgen çizmek için yöntemleri çağırıyorsunuz. Dikdörtgenlerin tümü aynı şekilde çizilir. Tek fark, tanımlanmış kırpma bölgeleri ve ekrandaki konumudur.

Dikdörtgenleri çizmek için kullanılan algoritma, aşağıdaki şema ve açıklamada gösterildiği gibi çalışır. Özetle, Canvas başlangıç noktasını taşıyarak bir dizi dikdörtgen çizersiniz. Kavramsal olarak bu, aşağıdaki adımlardan oluşur:

(1) Önce Canvas, dikdörtgenin çizilmesini istediğiniz yere çevirirsiniz. Yani, bir sonraki dikdörtgenin ve diğer tüm şekillerin nerede çizilmesi gerektiğini hesaplamak yerine, Canvas kaynağını, yani koordinat sistemini taşırsınız.

(2) Ardından, tuvalin yeni kaynağındaki dikdörtgeni çiziyorsunuz. Yani şekilleri, çevrilmiş koordinat sisteminde aynı konumda çizersiniz. Bu yöntem çok daha basit ve biraz daha verimlidir.

(3) Son olarak, Canvas'i orijinal Origin durumuna geri yüklersiniz.

Algoritmayı uygulayacağınız şekilde aşağıda bulabilirsiniz:

  1. onDraw() içinde, Canvas öğesini gri arka plan rengiyle doldurmak ve orijinal şekilleri çizmek için bir işlev çağırın.
  2. Her kırpılmış dikdörtgen ve çizilecek metin için bir işlev çağırın.

Her dikdörtgen veya metin için:

  1. Baştaki durumuna sıfırlamak için Canvas öğesinin mevcut durumunu kaydedin.
  2. Tuvalin Origin öğesini çizmek istediğiniz konuma çevirin.
  3. Kırpma şekilleri ve yolları uygulayın.
  4. Dikdörtgen veya metin çizin.
  5. Canvas durumunu geri yükleyin.

Adım: onDraw() geçersiz kılma

  1. onDraw() öğesini, aşağıdaki kodda gösterildiği gibi geçersiz kılın. Çizdiğiniz her şekil için bir işlev çağırırsınız. Bunu daha sonra uygularsınız.
 override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        drawBackAndUnclippedRectangle(canvas)
        drawDifferenceClippingExample(canvas)
        drawCircularClippingExample(canvas)
        drawIntersectionClippingExample(canvas)
        drawCombinedClippingExample(canvas)
        drawRoundedRectangleClippingExample(canvas)
        drawOutsideClippingExample(canvas)
        drawSkewedTextExample(canvas)
        drawTranslatedTextExample(canvas)
        // drawQuickRejectExample(canvas)
    }
  1. Kodun derlenmeye devam etmesi için çizim işlevlerinin her biri için bir saplama oluşturun. Aşağıdaki kodu kopyalayabilirsiniz.
private fun drawBackAndUnclippedRectangle(canvas: Canvas){
}
private fun drawDifferenceClippingExample(canvas: Canvas){
}
private fun drawCircularClippingExample(canvas: Canvas){
}
private fun drawIntersectionClippingExample(canvas: Canvas){
}
private fun drawCombinedClippingExample(canvas: Canvas){
}
private fun drawRoundedRectangleClippingExample(canvas: Canvas){
}
private fun drawOutsideClippingExample(canvas: Canvas){
}
private fun drawTranslatedTextExample(canvas: Canvas){
}
private fun drawSkewedTextExample(canvas: Canvas){
}
private fun drawQuickRejectExample(canvas: Canvas){
}

Uygulama, aynı dikdörtgeni çizer ve önce kırpma olmadan, altı kez çeşitli kırpma yolları uygulayarak altı kez şekillendirir. drawClippedRectangle() yöntemi, aşağıda gösterildiği gibi bir dikdörtgen çizim kodunu dikkate alır.

1. Adım: DrawClippedRectangle() yöntemini oluşturun

  1. Canvas türünde canvas bağımsız değişkenini alan bir drawClippedRectangle() yöntemi oluşturun.
private fun drawClippedRectangle(canvas: Canvas) {
}
  1. drawClippedRectangle() yönteminin içinde, tüm şekil için kırpma dikdörtgeninin sınırlarını ayarlayın. Yalnızca kare çizmeyi sınırlandıran bir kırpma dikdörtgeni uygulayın.
canvas.clipRect(
       clipRectLeft,clipRectTop,
       clipRectRight,clipRectBottom
)

Canvas.clipRect(...) yöntemi, gelecekte çizim çizimlerinin üzerine yazılabileceği ekran alanını azaltır. Kırpma sınırlarını, geçerli kırpma dikdörtgeninin ve clipRect() dikdörtgenine iletilen dikdörtgenin uzamsal kesişimi olarak ayarlar. clipRect() yönteminin, bölgeler için farklı formlar kabul eden ve kırpma dikdörtgeninde farklı işlemlere izin veren birçok varyantı vardır.

  1. canvas öğesini beyaz renkle doldurun. Evet. Dikdörtgenler çizmediğiniz için tüm tuval kesiliyor! Kırpma dikdörtgeni nedeniyle, yalnızca kırpma dikdörtgeni tarafından tanımlanan bölge doldurularak beyaz bir dikdörtgen oluşturuyor. Yüzenin geri kalanı gri renkte kalır.
canvas.drawColor(Color.WHITE)
  1. Rengi kırmızı olarak değiştirin ve kırpma dikdörtgeninin içinde bir çapraz çizgi çizin.
paint.color = Color.RED
canvas.drawLine(
   clipRectLeft,clipRectTop,
   clipRectRight,clipRectBottom,paint
)
  1. Rengi yeşile ayarlayın ve kırpma dikdörtgeninin içine bir daire çizin.
paint.color = Color.GREEN
canvas.drawCircle(
   circleRadius,clipRectBottom - circleRadius,
   circleRadius,paint
)
  1. Rengi maviye ayarlayın ve metni kırpma dikdörtgeninin sağ kenarıyla hizalayın. Metin çizmek için canvas.drawText() simgesini kullanın.
paint.color = Color.BLUE
// Align the RIGHT side of the text with the origin.
paint.textSize = textSize
paint.textAlign = Paint.Align.RIGHT
canvas.drawText(
   context.getString(R.string.clipping),
   clipRectRight,textOffset,paint
)

2. Adım: DrawBackAndUnclippedRectangle() yöntemini uygulayın

  1. drawClippedRectangle() yönteminin nasıl çalıştığını görmek için, aşağıda gösterildiği gibi drawBackAndUnclippedRectangle() yöntemini uygulayarak ilk klipsiz dikdörtgeni çizin. canvas öğesini kaydedin, ilk satıra ve sütun konumuna çevirin, drawClippedRectangle() çağrısı yaparak çizin, ardından canvas öğesini önceki durumuna geri yükleyin.
private fun drawBackAndUnclippedRectangle(canvas: Canvas){
   canvas.drawColor(Color.GRAY)
   canvas.save()
   canvas.translate(columnOne,rowOne)
   drawClippedRectangle(canvas)
   canvas.restore()
}
  1. Uygulamanızı çalıştırın. Dairenin, kırmızı çizginin ve gri bir arka plan üzerinde metnin yer aldığı ilk beyaz dikdörtgeni görürsünüz.

Aşağıdaki kırpma örneği yöntemlerinde, grafik efektleri elde etmek ve kırpma bölgelerinde ihtiyacınız olan şekli şekillendirmek için çeşitli kırpma bölgeleri kombinasyonlarını uygulayabilirsiniz.

Bu yöntemlerin her biri aynı kalıbı izler.

  1. Tuvalin geçerli durumunu kaydedin: canvas.save()

Etkinlik bağlamı bir çizim durumu yığını tutar. Çizim durumları, mevcut dönüşüm matrisini ve mevcut kırpma bölgesinden oluşur. Mevcut durumu kaydedebilir, çizim durumunu değiştiren işlemleri (tuvali çevirme veya döndürme gibi) gerçekleştirip kaydedilen çizim durumunu geri yükleyebilirsiniz. (Not: Bu, Git! içindeki "sash&quot" komutu gibidir.

Çiziminiz dönüşümleri içerdiğinde, dönüşümleri tersine çevirme ve zincirleme olarak geri alma hataya açıktır. Örneğin, çevirir, esneter ve sonra döndürürseniz hızlı bir şekilde karmaşıklaşabilir. Bunun yerine, tuvalin durumunu kaydedin, dönüşümlerinizi uygulayın, çizin ve ardından önceki durumu geri yükleyin.

Örneğin, bir kırpma bölgesi tanımlayabilir ve bu durumu kaydedebilirsiniz. Ardından zemini çevirin, kırpma bölgesi ekleyin ve döndürün. Biraz çizim yaptıktan sonra, orijinal kırpma durumunu geri yükleyebilir ve şemada gösterildiği gibi farklı bir çeviri ile sapma dönüşümü yapabilirsiniz.

  1. Tuvalin kaynağını satır/sütun koordinatlarına çevirin: canvas.translate()

Tuvalin kaynağını taşımak ve aynı şeyi yeni bir koordinat sisteminde çizmek, tüm öğeleri çizmekten çok daha kolaydır. (İpucu: Öğeleri döndürmek için aynı tekniği kullanabilirsiniz.)

  1. Varsa dönüşümleri path öğesine uygulayın.
  2. Kırpma uygula: canvas.clipPath(path)
  3. Şekil çizin: drawClippedRectangle() or drawText()
  4. Önceki tuval durumunu geri yükle: canvas.restore()

1. Adım: DrawDifferenceCliplingExample(tuval) uygulayın

İkinci dikdörtgeni çizmek için kod ekleyin. Bu dikdörtgen, resim çerçevesi efekti oluşturmak için iki kırpma dikdörtgeni arasındaki farkı kullanır.

Aşağıdakileri yapan kodu kullanın:

  1. Kanvası kaydedin.
  2. Tuvalin kaynağını ilk satıra, ikinci sütuna, ilk dikdörtgenin sağındaki açık alana çevirin.
  3. İki kırpma dikdörtgeni uygulayın. DIFFERENCE operatörü, ikinci dikdörtgeni ilkinden çıkarır.
  1. Değiştirilen tuvali çizmek için drawClippedRectangle() yöntemini çağırın.
  2. Tuval durumunu geri yükleyin.
private fun drawDifferenceClippingExample(canvas: Canvas) {
   canvas.save()
   // Move the origin to the right for the next rectangle.
   canvas.translate(columnTwo,rowOne)
   // Use the subtraction of two clipping rectangles to create a frame.
   canvas.clipRect(
       2 * rectInset,2 * rectInset,
       clipRectRight - 2 * rectInset,
       clipRectBottom - 2 * rectInset
   )
   // The method clipRect(float, float, float, float, Region.Op
   // .DIFFERENCE) was deprecated in API level 26. The recommended
   // alternative method is clipOutRect(float, float, float, float),
   // which is currently available in API level 26 and higher.
   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O){
       canvas.clipRect(
           4 * rectInset,4 * rectInset,
           clipRectRight - 4 * rectInset,
           clipRectBottom - 4 * rectInset,
            Region.Op.DIFFERENCE
       )
   } else {
       canvas.clipOutRect(
           4 * rectInset,4 * rectInset,
           clipRectRight - 4 * rectInset,
           clipRectBottom - 4 * rectInset
       )
   }
   drawClippedRectangle(canvas)
   canvas.restore()
}
  1. Uygulamanızı çalıştırın. Uygulama aşağıdaki gibi görünmelidir.

2. Adım: DrawCircularClippingExample(uygulama)

Ardından, kodun sonuna dairesel bir yoldan oluşturulmuş dairesel kırpma bölgesini kullanan bir daire çizin. Bunu yapmak için daireyi kaldırın (çizim yapmayın) ve yerine gri arka plan gösterin.

private fun drawCircularClippingExample(canvas: Canvas) {

   canvas.save()
   canvas.translate(columnOne, rowTwo)
   // Clears any lines and curves from the path but unlike reset(),
   // keeps the internal data structure for faster reuse.
   path.rewind()
   path.addCircle(
       circleRadius,clipRectBottom - circleRadius,
       circleRadius,Path.Direction.CCW
   )
   // The method clipPath(path, Region.Op.DIFFERENCE) was deprecated in
   // API level 26. The recommended alternative method is
   // clipOutPath(Path), which is currently available in
   // API level 26 and higher.
   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
       canvas.clipPath(path, Region.Op.DIFFERENCE)
   } else {
       canvas.clipOutPath(path)
   }
   drawClippedRectangle(canvas)
   canvas.restore()
}

3. Adım: DrawIntersectionClippingSample'ı(canvas) uygulayın

Ardından, ikinci satır ve sütunda iki kırpma dikdörtgeninin kesişimini çizmek için kod ekleyin.

Ekran çözünürlüğünüze bağlı olarak bu bölgenin görünümünün farklılık göstereceğini unutmayın. Görünür bölgenin boyutunu değiştirmek için smallRectOffset boyutuyla denemeler yapın. Daha küçük bir smallRectOffset, ekranda daha geniş bir alan oluşturur.

private fun drawIntersectionClippingExample(canvas: Canvas) {
   canvas.save()
   canvas.translate(columnTwo,rowTwo)
   canvas.clipRect(
       clipRectLeft,clipRectTop,
       clipRectRight - smallRectOffset,
       clipRectBottom - smallRectOffset
   )
   // The method clipRect(float, float, float, float, Region.Op
   // .INTERSECT) was deprecated in API level 26. The recommended
   // alternative method is clipRect(float, float, float, float), which
   // is currently available in API level 26 and higher.
   if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O) {
       canvas.clipRect(
           clipRectLeft + smallRectOffset,
           clipRectTop + smallRectOffset,
           clipRectRight,clipRectBottom,
           Region.Op.INTERSECT
       )
   } else {
       canvas.clipRect(
           clipRectLeft + smallRectOffset,
           clipRectTop + smallRectOffset,
           clipRectRight,clipRectBottom
       )
   }
   drawClippedRectangle(canvas)
   canvas.restore()
}

4. Adım: DrawBirleşik Klip Örneği(canvas) uygulayın

Ardından, şekilleri, daireyi ve dikdörtgeni birleştirin ve bir kırpma bölgesi tanımlamak için herhangi bir yol çizin.

private fun drawCombinedClippingExample(canvas: Canvas) {
   canvas.save()
   canvas.translate(columnOne, rowThree)
   path.rewind()
   path.addCircle(
       clipRectLeft + rectInset + circleRadius,
       clipRectTop + circleRadius + rectInset,
       circleRadius,Path.Direction.CCW
   )
   path.addRect(
       clipRectRight / 2 - circleRadius,
       clipRectTop + circleRadius + rectInset,
       clipRectRight / 2 + circleRadius,
       clipRectBottom - rectInset,Path.Direction.CCW
   )
   canvas.clipPath(path)
   drawClippedRectangle(canvas)
   canvas.restore()
}

5. Adım: Çizimleri YuvarlatılmışDikdörtgenKlip Örneği(Tuval) uygulayın

Ardından, yaygın olarak kullanılan bir kırpma şekli olan yuvarlak bir dikdörtgen ekleyin.

  1. Üst düzeyde bir dikdörtgen değişkeni oluşturun ve başlatın. RectF, kayan noktanın dikdörtgen koordinatlarını tutan bir sınıftır.
private var rectF = RectF(
   rectInset,
   rectInset,
   clipRectRight - rectInset,
   clipRectBottom - rectInset
)
  1. drawRoundedRectangleClippingExample() işlevini uygulayın. addRoundRect() işlevi bir dikdörtgen, köşe yarıçapının x ve y değerleri için değerler ve yuvarlak dikdörtgenin çemberini döndürme yönü. Path.Direction kapalı yollara (ör. dikdörtgenler, ovaller) yönlere nasıl odaklanıldığını belirtir. CCW, saat yönünün kısaltmasıdır.
private fun drawRoundedRectangleClippingExample(canvas: Canvas) {
   canvas.save()
   canvas.translate(columnTwo,rowThree)
   path.rewind()
   path.addRoundRect(
       rectF,clipRectRight / 4,
       clipRectRight / 4, Path.Direction.CCW
   )
   canvas.clipPath(path)
   drawClippedRectangle(canvas)
   canvas.restore()
}

6. Adım: çizimOutsideClippingExample(uygulama)

Kırpma dikdörtgeninin girintilerini iki katına çıkararak dikdörtgenin dışını kırpın.

private fun drawOutsideClippingExample(canvas: Canvas) {
   canvas.save()
   canvas.translate(columnOne,rowFour)
   canvas.clipRect(2 * rectInset,2 * rectInset,
       clipRectRight - 2 * rectInset,
       clipRectBottom - 2 * rectInset)
   drawClippedRectangle(canvas)
   canvas.restore()
}

7. Adım: DrawtranslatedTextExample özelliğini uygulayın(canvas)

Metin çizmek, diğer şekillerden tamamen farklı değildir ve metne dönüşüm uygulayabilirsiniz. Örneğin, tuvali çevirip metni çizerek metni çevirebilirsiniz.

  1. Aşağıdaki işlevi uygulayın.
private fun drawTranslatedTextExample(canvas: Canvas) {
   canvas.save()
   paint.color = Color.GREEN
   // Align the RIGHT side of the text with the origin.
   paint.textAlign = Paint.Align.LEFT
   // Apply transformation to canvas.
   canvas.translate(columnTwo,textRow)
   // Draw text.
   canvas.drawText(context.getString(R.string.translated),
       clipRectLeft,clipRectTop,paint)
   canvas.restore()
}
  1. Çevrilmiş metni görmek için uygulamanızı çalıştırın.

8. Adım: DrawSkewedTextExample(canvas) yöntemini uygulayın

Ayrıca metni çarpıtabilirsiniz. Yani bunu çeşitli şekillerde bozabilirsiniz.

  1. ClippedView işlevinde aşağıdaki işlevi oluşturun.
private fun drawSkewedTextExample(canvas: Canvas) {
   canvas.save()
   paint.color = Color.YELLOW
   paint.textAlign = Paint.Align.RIGHT
   // Position text.
   canvas.translate(columnTwo, textRow)
   // Apply skew transformation.
   canvas.skew(0.2f, 0.3f)
   canvas.drawText(context.getString(R.string.skewed),
       clipRectLeft, clipRectTop, paint)
   canvas.restore()
}
  1. Çevrilen metnin önüne çizilen çarpık metni görmek için uygulamanızı çalıştırın.

quickReject() Canvas yöntemi, belirli bir dikdörtgenin veya yolun, tüm dönüşümler uygulandıktan sonra görünür olan bölgelerin dışında tamamen yer alıp almayacağını kontrol etmenizi sağlar.

quickReject() yöntemi, daha karmaşık çizimler oluştururken ve bunu mümkün olduğunca hızlı bir şekilde yapmanız gerektiğinde çok kullanışlıdır. quickReject() sayesinde, hangi nesneleri çizmenize gerek olmadığını verimli bir şekilde belirleyebilirsiniz ve kendi kesişim mantığınızı yazmanıza gerek kalmaz.

  • Ekranda dikdörtgen veya yol hiç görünmezse quickReject() yöntemi true değerini döndürür. Kısmi çakışmalar için kendi kontrolünüzü yapmanız gerekir.
  • EdgeType, en yakın piksele yuvarlama için AA (Karşıtlık: Kenarları yuvarlayarak kenarlardan başlayarak yuvarlayın) veya BW (Siyah Beyaz: Yalnızca en yakın piksel sınırına yuvarlayarak kenarlara davranın).

quickReject() ürününün birkaç sürümü vardır ve bunları dokümanlarda da bulabilirsiniz.

boolean

quickReddet(float left, float top, float right, float bottom, Canvas.EdgeType type)

boolean

quickReddet(RectF rect, Canvas.EdgeType type)

boolean

quickReddet(Yol path, Canvas.EdgeType type)

Bu alıştırmada, daha önce olduğu gibi yeni bir satıra, metnin altına ve clipRect içine bir çizim çizeceksiniz.

  • İlk olarak, clipRect ile çakışan bir dikdörtgen inClipRectangle ile quickReject() öğesini çağırırsınız. Bu nedenle, quickReject() yanlış değerini döndürür, clipRect BLACK ile doldurulur ve inClipRectangle dikdörtgen çizilir.

  • Kodu değiştirin ve notInClipRectangle ile quickReject() numaralı telefonu arayın. quickReject() artık "true" (doğru) değerini döndürüyor. clipRect WHITE ile dolu ve notInClipRectangle çizilmiyor.

Karmaşık çizimleriniz olduğunda, hangi şeklin kırpma bölgesinin tamamen dışında olduğunu ve hangilerinde kırpma bölgesinin tamamen içinde olduğunun yanı sıra ek hesaplamalar yapmanız ve çizimler yapmanız gerekebilir.

Adım: quickDismiss() ile deneme yapın

  1. Üst düzeyde, ek bir satırın y koordinatları için değişken oluşturun.
   private val rejectRow = rowFour + rectInset + 2*clipRectBottom
  1. ClippedView öğesine aşağıdaki drawQuickRejectExample() işlevini ekleyin. quickReject() kodunu kullanmak için bilmeniz gereken her şeyi içerdiğinden kodu okuyun.
private fun drawQuickRejectExample(canvas: Canvas) {
   val inClipRectangle = RectF(clipRectRight / 2,
       clipRectBottom / 2,
       clipRectRight * 2,
       clipRectBottom * 2)

   val notInClipRectangle = RectF(RectF(clipRectRight+1,
       clipRectBottom+1,
       clipRectRight * 2,
       clipRectBottom * 2))

   canvas.save()
   canvas.translate(columnOne, rejectRow)
   canvas.clipRect(
       clipRectLeft,clipRectTop,
       clipRectRight,clipRectBottom
   )
   if (canvas.quickReject(
           inClipRectangle, Canvas.EdgeType.AA)) {
       canvas.drawColor(Color.WHITE)
   }
   else {
       canvas.drawColor(Color.BLACK)
       canvas.drawRect(inClipRectangle, paint
       )
   }
       canvas.restore()
}
  1. onDraw() içinde, drawQuickRejectExample() çağrısının yorumunu kaldırın.
  2. Uygulamanızı çalıştırdığınızda siyah bir dikdörtgen görürsünüz. Bu dikdörtgen, doldurulmuş kırpma bölgesi ve inClipRectangle ile temsil edilen iki dikdörtgenle çakıştığı için quickReject() false ve inClipRectangle çizilir.

  1. drawQuickRejectExample() içinde kodu değiştirerek notInClipRectangle. çalıştırmak için quickReject() kodunu quickReject() true döndürür ve kırpma bölgesi beyazla doldurulur.

Tamamlanan codelab'in kodunu indirin.

$  git clone https://github.com/googlecodelabs/android-kotlin-drawing-clipping


Alternatif olarak, veri havuzunu Zip dosyası olarak indirip sıkıştırılmış dosyayı Android Studio'da açabilirsiniz.

Zip'i İndir

  • Bir etkinliğin Context değeri, Canvas için dönüşümleri ve kırpma bölgelerini koruyan bir durum sağlar.
  • Tuvalinizi çizmek ve orijinal durumuna dönmek için canvas.save() ve canvas.restore() kullanın.
  • Bir tuvale birden fazla şekil çizmek için konumunu hesaplayabilir veya çizim yüzeyinizin kaynağını taşıyabilirsiniz (çevirebilirsiniz). İkincisi, yinelenen çizim dizileri için yardımcı program yöntemleri oluşturmayı kolaylaştırabilir.
  • Kırpma bölgeleri, herhangi bir şekil veya şekil kombinasyonu olabilir.
  • Kırpma bölgelerini tam olarak gerektiği şekilde almak için bu bölgeleri ekleyebilir, çıkarabilir ve kesişebilirsiniz.
  • Tuvali dönüştürerek metne metin uygulayabilirsiniz.
  • quickReject() Canvas yöntemi, belirli bir dikdörtgenin veya yolun halihazırda görünür olan bölgelerin dışında tam olarak bulunup bulunmadığını kontrol etmenize olanak tanır.

Udacity kursu:

Android geliştirici dokümanları:

Ayrıca, Android çerçevesinin ekrana nasıl geldiğine dair ayrıntılı bir açıklama için Grafik Mimari serisine de bakın.

Bu bölümde, bir eğitmen tarafından sunulan kurs kapsamında bu codelab üzerinden çalışan öğrenciler için olası ev ödevi ödevleri listelenmektedir. Öğretmenin şunları yapması gerekir:

  • Gerekirse ev ödevini atayın.
  • Öğrencilere ev ödevlerinin nasıl gönderileceğini bildirin.
  • Ev ödevlerine not verin.

Öğretmenler bu önerileri istedikleri kadar kullanabilir veya uygun görebilir ve uygun olan diğer ev ödevlerini atayabilirler.

Bu codelab'de kendiniz çalışıyorsanız, bilginizi test etmek için bu ödevlerden yararlanabilirsiniz.

Bu soruları yanıtlayın

1. Soru

Şekillerin çizilmesinden etkili bir şekilde hariç tutmak için hangi yöntemi çağırıyorsunuz?

makbuz excludeFromDrawing()

makbuz quickReject()

makbuz onDraw()

makbuz clipRect()

2. Soru

Canvas.save() ve Canvas.restore() hangi bilgileri kaydedip geri yükler?

▢ Renk, çizgi genişliği vb.

▢ Yalnızca mevcut dönüşümler

▢ Mevcut dönüşümler ve kırpma bölgesi

▢ Yalnızca geçerli kırpma bölgesi

3. Soru

Paint.Align şunları belirtir:

▢ Aşağıdaki çizim şekilleri nasıl hizalanır?

▢ Metnin kökenin hangi kenarından alındığı

▢ Kırpma bölgesinde nerede hizalanır?

▢ Metnin hangi tarafta başlangıç noktasına hizalanacağı

Bu kurstaki diğer codelab'lerin bağlantıları için Kotlin codelab'lerdeki Gelişmiş Android açılış sayfasına bakın.