2013-04-12 13 views
19

Próbuję utworzyć widok tekstowy, którego tło jest półkola. Tworzę owal za pomocą ShapeDrawable. Próbowałem utworzyć półokrąg, używając ScaleDrawable, aby podwoić rozmiar pionowy owalu i przyciąć go. Jednak ScaleDrawable nie ma żadnego efektu. Dlaczego nie? Jaki jest najlepszy sposób narysowania półkola w tle widoku?Rysowanie półokręgu w tle widoku

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> 

res/rozciągliwej/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> 

res/odkształcalne/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

myślę najlepszą odpowiedzią na to pytanie jest tutaj: https://stackoverflow.com/a/45406439/2443849 –

Odpowiedz

23

można zaimplementować jesteś właścicielem rozciągliwej . Ale to nie może być zawyżone z XML. Musisz ustawić ciągnięcie z kodu za pomocą View.setBackgroundDrawable();

Zobacz przykładową implementację, aby narysować półokręgu za pomocą ciągnięcia.

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

Dzięki Vivek! Zastosuję to podejście. Masz pojęcie, dlaczego nie można użyć rysunków XML? – joshuanapoli

+1

sprawdź tę dyskusję https://groups.google.com/forum/?fromgroups=#!topic/android-developers/glpdi0AdMzI Ma rozwiązanie, ale jest zhakowane. –

1

zamiast tego można użyć, aby ustawić obraz jako tło ...

1> zaprojektować dowolny obraz stosując farbę i zapisz go w dowolnym obsługiwany format, taki jak .jpg lub .png tzn. będzie to twój obraz z półkolem, który chcesz.

2> zapisać obraz w RES/rozciągliwej folderu

3> ustawić TextView tło dla tego obrazu przy użyciu android:background="@drawable/yourimage.jpg"

nadzieję, że to pomaga ...

2

Zrobiłem tę klasę nadzieję, że pomoże Ci wszystkie zmienne są w języku hiszpańskim, ale jest dość proste,

konstruktora SemiCirculo wykorzystania jako parametry RGB półkola i rozdzielczość (ilość trójkątów na swoje półokrąg)

Metoda CalcularPuntosPorcentaje służy jako parametry środka okręgu, kąta początkowego, szerokości kąta i radia.

Metoda ImprimeCirculo używa parametru canvas jako parametru, służy do narysowania półokręgu, gdy już jest on wyskalowany punktami półokręgu z poprzednią wspomnianą metodą.

sposób CalcularPuntosPorcentaje jest podobny do CalcularPuntosPorcentaje, ale insted wyjściowych i szer parametry kątowych jest stosowanie% od 0 do 100

koniec wytwarza SetOffset i setcolor służą do zmiany z domyślnej Poing o, odniesienie do kąt a kolor półkola

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

Nazwy metod nie powinny być pisane wielkimi literami w Javie. Fakt, że jest w języku hiszpańskim, również utrudnia tutaj zrozumienie. – afollestad

25

przyciąć kształt owalny, tak umieścić go w ClipDrawable jak poniżej:

Res/odkształcalne/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 wspólny cel jest tworzenie niestandardowych pasków postępu. Ściąga część swojej zawartości i stopniowo wyświetla ją, gdy jej właściwość "level" zwiększa się w zakresie [0; 10000] (0 = ukryty, 10000 = w pełni wyświetlany).

  • clipOrientation to orientacja postępu obcinania.
  • gravity to początek obcinania postępów/strona.

Aby uzyskać półkole, ustaw tę ClipDrawable jak Państwa zdaniem tle, a programowo dostosować swój „poziom”:

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

działa na wszystkich wersjach Androida („Dodane w poziomie API 1”) i nie wymaga widoku niestandardowego.

;-)

+0

Czy możliwe jest również obramowanie klipu? –

+1

Do kształtu dziecka można dodać obrys: (wewnątrz owalnego tagu ) Ale to nie jest to, co Ty chcę, ponieważ ta granica również zostanie obcięta. – John

+0

Thx John. Nie ma więc możliwości obramowania rodzica w kształcie klipu. –