2017-03-11 1 views
6

Mon activité devrait ressembler à ceci:Comment dessiner un segment de cercle au bas de la vue [android]?

Je ne sais pas quelle est la meilleure façon de montrer le segment du cercle entre le haut et bas vues. Je souhaite éviter de sauvegarder le segment en tant qu'image.

Existe-t-il un moyen de le montrer en utilisant drawable xml (J'ai essayé d'y parvenir en utilisant oval, mais je ne sais pas comment faire est si "plat")?

Peut-être en tirant sur canvas?

+0

essayer de créer une classe 'ShapeDrawable' avec une coutume' Shape' passé à 'constructeur ShapeDrawable' (le plus probable que vous dessinerez avec l'aide de la méthode «Chemin # quadTo» – pskink

+0

Merci pour vos conseils, je vais essayer –

+0

juste pour la clarté im demandant que vous avez besoin de la sortie comme image que vous avez donné sur votre question, non? –

Répondre

9

Je pense que l'option 3 est le meilleur, vous pouvez contrôler exactement ce que vous dessinez, mais vous n'avez pas perdre des points de karma POO

OPTION 1

Vous pouvez créer une View pour votre haut View et mettre en œuvre vous-même dessin comme celui-ci, je suis ici, mais le sous-classement RelativeLayout vous pouvez sous-classe ce que vous voulez View

public class CurveBgRelativeLayout extends RelativeLayout { 

    public CurveBgRelativeLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    private Path path; 
    private Paint paint; 

    @Override 
    protected void onSizeChanged(int w, int h, int oldw, int oldh) { 
     super.onSizeChanged(w, h, oldw, oldh); 

     paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
     paint.setStyle(Paint.Style.FILL); 
     paint.setColor(0xffff0000); 
     path = new Path(); 

     float horizontalOffset = w * .8f; 
     float top = -h * .8f; 
     float bottom = h; 

     RectF ovalRect = new RectF(-horizontalOffset, top, w + horizontalOffset, bottom); 
     path.lineTo(ovalRect.left, top); 
     path.arcTo(ovalRect, 0, 180, false); 
     path.setFillType(Path.FillType.INVERSE_EVEN_ODD); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 

     if (path != null) 
      canvas.drawPath(path, paint); 

     super.onDraw(canvas); 
    } 
} 

puis dans votre mise en page 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"> 

    <com.example.CurveBgRelativeLayout 
     android:layout_width="match_parent" 
     android:background="#ffffffff" 
     android:layout_height="0dp" 
     android:layout_weight="1"/> 

    <View 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1" 
     android:background="#ffff0000" 
     /> 
</LinearLayout> 



OPTION 2

Vous pouvez créer un drawable xml comme arrière-plan pour votre haut View, le seul problème ici est que l'étirement horizontal de la cercle est donné avec une taille dp, il est donc pas par rapport à la taille de la View

<?xml version="1.0" encoding="utf-8"?> 
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item 
     android:height="40dp" 
     android:gravity="bottom"> 
     <shape android:shape="rectangle"> 
      <solid android:color="#ffff0000" /> 
     </shape> 
    </item> 
    <item 
     android:width="500dp" 
     android:height="60dp" 
     android:gravity="bottom|center_horizontal" 
     android:top="-40dp"> 
     <shape android:shape="oval"> 
      <solid android:color="#ffffffff" />  
     </shape> 
    </item> 
    <item 
     android:height="30dp" 
     android:bottom="30dp" 
     android:gravity="bottom"> 
     <shape android:shape="rectangle"> 
      <solid android:color="#ffffffff" /> 
     </shape> 
    </item> 
</layer-list> 


OPTION 3

public class CurveBottomDrawable extends Drawable { 

    private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    private Path path = new Path(); 

    public CurveBottomDrawable(int color) { 
     paint.setStyle(Paint.Style.FILL); 
     paint.setColor(color); 
    } 

    @Override 
    public void draw(@NonNull Canvas canvas) { 

     paint.setStyle(Paint.Style.FILL); 
     paint.setColor(0xffff0000); 

     path.reset(); 
     Rect bounds = getBounds(); 

     float horizontalOffset = bounds.width() * .8f; 
     float top = -bounds.height() * .8f; 
     float bottom = bounds.height(); 

     RectF ovalRect = new RectF(-horizontalOffset, top, bounds.width() + horizontalOffset, bottom); 
     path.lineTo(ovalRect.left, top); 
     path.arcTo(ovalRect, 0, 180, false); 
     path.setFillType(Path.FillType.INVERSE_EVEN_ODD); 

     canvas.drawPath(path, paint); 
    } 

    @Override 
    public void setAlpha(@IntRange(from = 0, to = 255) int alpha) { 
     paint.setAlpha(alpha); 
    } 

    @Override 
    public void setColorFilter(@Nullable ColorFilter colorFilter) { 
     paint.setColorFilter(colorFilter); 
    } 

    @Override 
    public int getOpacity() { 
     return PixelFormat.TRANSPARENT; 
    } 

} 

puis mettez-le programme

myView.setBackground(new CurveBottomDrawable(0xffff0000)); 
+0

J'ai l'impression que 'onDraw()' ne sera pas appelé car 'setWillNotDraw (false)' n'a pas été effectuée. – azizbekian

+0

Merci beaucoup, la première option est ce que je cherchais –

+0

@lelloman, j'ai vérifié la première solution. Il commencera à fonctionner après 'setWillNotDraw (false)', sinon 'onDraw()' de ViewGroup' ne sera pas appelé. – azizbekian