2013-04-12 9 views
19

Sto provando a creare un TextView il cui sfondo è un semicerchio. Creo un ovale usando ShapeDrawable. Ho provato a creare un semicerchio usando ScaleDrawable per raddoppiare la dimensione verticale dell'ovale e ritagliarlo. Tuttavia, ScaleDrawable non ha alcun effetto. Perchè no? Qual è il modo migliore per disegnare un semicerchio sullo sfondo di una vista?Disegna un semicerchio sullo sfondo di una vista

res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    > 
    <TextView 
     android:id="@+id/main_view" 
     android:background="@drawable/semicircle" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentTop="true" 
     android:layout_alignParentLeft="true" 
     android:layout_alignParentRight="true" 
     android:gravity="center_horizontal" 
    /> 
    </RelativeLayout> 

ris/drawable/semicircle.xml

<?xml version="1.0" encoding="utf-8"?> 
<scale xmlns:android="http://schemas.android.com/apk/res/android" 
    android:drawable="@drawable/circle" 
    android:scaleGravity="top|clip_vertical" 
    android:scaleHeight="200%" 
    android:scaleWidth="100%" > 
</scale> 

ris/drawable/circle.xml

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval" 
    <solid 
     android:color="#444" /> 
</shape> 

src /.../ MainActivity.java

//... 
public class MainActivity extends Activity { 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main_activity); 
     findViewById(R.id.main_view).getBackground().setLevel(10000); 
    } 
//... 
+1

Penso migliore risposta per questa domanda è qui: https://stackoverflow.com/a/45406439/2443849 –

risposta

23

È possibile implementare si possiede Drawable . Ma non può essere gonfiato da XML. È necessario impostare il drawable dal codice usando View.setBackgroundDrawable();

Vedere la mia implementazione di esempio per disegnare un semicerchio usando drawable.

public class SemiCircleDrawable extends Drawable { 

    private Paint paint; 
    private RectF rectF; 
    private int color; 
    private Direction angle; 

    public enum Direction 
    { 
     LEFT, 
     RIGHT, 
     TOP, 
     BOTTOM 
    } 

    public SemiCircleDrawable() { 
     this(Color.BLUE, Direction.LEFT); 
    } 

    public SemiCircleDrawable(int color, Direction angle) { 
     this.color = color; 
     this.angle = angle; 
     paint = new Paint(); 
     paint.setColor(color); 
     paint.setStyle(Style.FILL); 
     rectF = new RectF(); 
    } 

    public int getColor() { 
     return color; 
    } 

    /** 
    * A 32bit color not a color resources. 
    * @param color 
    */ 
    public void setColor(int color) { 
     this.color = color; 
     paint.setColor(color); 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     canvas.save(); 

     Rect bounds = getBounds(); 

     if(angle == Direction.LEFT || angle == Direction.RIGHT) 
     { 
      canvas.scale(2, 1); 
      if(angle == Direction.RIGHT) 
      { 
       canvas.translate(-(bounds.right/2), 0); 
      } 
     } 
     else 
     { 
      canvas.scale(1, 2); 
      if(angle == Direction.BOTTOM) 
      { 
       canvas.translate(0, -(bounds.bottom/2)); 
      } 
     } 


     rectF.set(bounds); 

     if(angle == Direction.LEFT) 
      canvas.drawArc(rectF, 90, 180, true, paint); 
     else if(angle == Direction.TOP) 
      canvas.drawArc(rectF, -180, 180, true, paint); 
     else if(angle == Direction.RIGHT) 
      canvas.drawArc(rectF, 270, 180, true, paint); 
     else if(angle == Direction.BOTTOM) 
      canvas.drawArc(rectF, 0, 180, true, paint); 
    } 

    @Override 
    public void setAlpha(int alpha) { 
     // Has no effect 
    } 

    @Override 
    public void setColorFilter(ColorFilter cf) { 
     // Has no effect 
    } 

    @Override 
    public int getOpacity() { 
     // Not Implemented 
     return 0; 
    } 

} 
+1

Grazie Vivek! Userò questo approccio. Qualche idea sul perché i drawable XML non possono essere usati? – joshuanapoli

+1

controlla questa discussione https://groups.google.com/forum/?fromgroups=#!topic/android-developers/glpdi0AdMzI Ha una soluzione ma è hacky. –

1

invece è possibile utilizzare l'immagine per impostare come sfondo ...

1> Designer immagine usando vernice e salvarlo in qualsiasi formato supportato come .jpg o .png cioè questa sarà la tua immagine con un semicerchio che vuoi.

2> salvare l'immagine in res/cartella drawable

3> impostare lo sfondo TextView a quell'immagine utilizzando android:background="@drawable/yourimage.jpg"

speranza che questo aiuta ...

2

Ho fatto questa classe spero aiuti voi, tutte le variabili sono in spagnolo ma è piuttosto semplice,

utilizzare il costruttore SemiCirculo come parametri il rgb per il semicerchio e la risoluzione (numero di triangoli per la vostra semicerchio)

il metodo CalcularPuntosPorcentaje utilizza come parametri il centro del cerchio, l'angolo iniziale, la larghezza dell'angolo e la radio.

il metodo ImprimeCirculo usa la tela come parametro, è usato per disegnare il semicerchio una volta che è già stato calcolato i punti del semicerchio con il metodo sopra menzionato.

il metodo CalcularPuntosPorcentaje è simile a CalcularPuntosPorcentaje, ma invece di inizio e parametri angolari LARGHEZZA si utilizza un% da 0 a 100

finalmente il setOffset e SetColor vengono utilizzati per modificare il poing o di riferimento di partenza predefinito per l'angolo ed il colore del semicerchio

import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Path; 


public class SemiCirculo { 

    private Path circulo; 
    private Paint color; 
    private float px, py, radio, anguloI, anchoa,offset; 
    private int r, g, b; 
    private int resolucion; 
    private float puntox[],puntoy[]; 


    public SemiCirculo(int r1, int g1, int b1, int resolucion1) { 

     this.offset = 0; 
     this.color = new Paint(); 
     this.r = r1; 
     this.g = g1; 
     this.b = b1; 
     this.color.setColor(Color.rgb(r, g, b)); 
     color.setAntiAlias(true); 
     circulo = new Path(); 
     this.resolucion = resolucion1; 
     this.puntox = new float[this.resolucion]; 
     this.puntoy = new float[this.resolucion]; 
     this.anguloI = 0; 
     this.anchoa = 1; 

    } 

    public void SetOffset(float off) { 
     this.offset = off; 
    } 

    public void SetColor(int r1,int g1, int b1){   
     this.r=r1; 
     this.g=g1; 
     this.b=b1; 
     this.color.setColor(Color.rgb(r, g, b)); 
    } 

    public void CalcularPuntosPorcentaje(float px1, float py1, 
      float porcentaje, float radio1) { 
     this.anguloI = 0 + this.offset; 
     this.px = px1; 
     this.py = py1; 
     this.radio = radio1; 
     this.anguloI = 0; 
     this.anchoa = porcentaje/100 * 360; 

     this.CalcularPuntos(px, py, anguloI, anchoa, radio); 
    } 

    public void CalcularPuntos(float px1, float py1, float anguloI1, 
      float anchoangulo, float radio1) { 
     this.anguloI = anguloI1 + this.offset; 

     this.anchoa = anchoangulo; 
     this.px = px1; 
     this.py = py1; 
     this.radio = radio1 ; 

     float angulo = 360 - this.anguloI - this.anchoa; 

     for (int i = 0; i < resolucion; i++) { 
      this.puntox[i] = this.px - (float) Math.sin(Math.toRadians(angulo)) 
        * this.radio; 
      this.puntoy[i] = this.py - (float) Math.cos(Math.toRadians(angulo)) 
        * this.radio; 
      angulo = (360 - this.anguloI - this.anchoa) 
        + ((this.anchoa/(float) (this.resolucion)) * (i + 2)); 
     } 

     this.circulo.reset(); 

     this.circulo.moveTo(this.px, this.py); 
     for (int i = 0; i < resolucion; i++) { 
      this.circulo.lineTo(this.puntox[i], this.puntoy[i]); 
     } 

    } 

    public void ImprimeCirculo(Canvas canvas) { 

     canvas.drawPath(this.circulo, this.color); 

    } 

} 
+2

I nomi dei metodi non devono essere in maiuscolo in Java. Il fatto che sia in spagnolo rende anche difficile per le persone qui capire. – afollestad

25

Per ritagliare la forma ovale, basta incorporare in un ClipDrawable simili:

ris/drawable/semicircl e.xml

<?xml version="1.0" encoding="utf-8"?> 
<clip 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:clipOrientation="vertical" 
    android:gravity="bottom"> 
    <shape android:shape="oval"> 
     <solid android:color="#444"/> 
    </shape> 
</clip> 

ClipDdrawable scopo comune è quello di creare personalizzato barre di avanzamento. Si ritaglia una parte del suo contenuto e lo visualizza progressivamente quando la sua proprietà di "livello" aumenta in un intervallo di [0; 10000] (0 = nascosto, 10000 = completamente visualizzato).

  • clipOrientation è l'orientamento del progresso di ritaglio.
  • gravity è il bordo di inizio dell'avanzamento del ritaglio/lato.

Per ottenere un semicerchio, imposta questa ClipDrawable come sfondo vista, e programmaticamente modificare le sue "livello":

//... 
findViewById(R.id.my_view).getBackground().setLevel(5000) 
//... 

Opere su tutte le versioni di Android ("aggiunta nel livello di API 1") e non richiede alcuna visualizzazione personalizzata.

;-)

+0

è possibile avere anche un bordo attorno alla clip? –

+1

Un tratto può essere aggiunto alla forma del bambino: (all'interno dell'ovale tag) Ma questo potrebbe non essere quello che voglio, perché anche questo confine sarebbe troncato. – John

+0

Thx John. Quindi non c'è la possibilità di bordare il genitore in una forma a clip. –

Problemi correlati