Zeichnen eines kundenspezifischen Kreissegments dynamisch

Mein Kunde möchte das folgende Widget in der Anwendung:
Bildbeschreibung hier eingeben
Der Text kommt vom Server. Der Gradientenwinkel hängt von Variablen ab, die auch vom Server kommen. Auch der Kunde möchte, dass der Gradient dynamisch gefüllt wird (ein Benutzer muss sehen, wie der Gradient ausgefüllt wird, beginnend mit dem 0).
Jetzt mache ich folgendes: Ich benutze zwei Bilder – einer ist der farbige Kreis, der zweite ist der graue Kreis. Ich kreiere ein Kreissegment mit einem gewissen Winkel und wähle es als Maske auf den grauen Kreis und kombiniere dann den farbigen Kreis mit dem neuen grauen Kreis (wo ein Sektor abgeschnitten wird).
Hier ist mein Code. Ich initialisiere die Variablen, die die initializeVarsForCompoundImDrawing aufrufen, dann ein paar Mal in einem zweiten Aufruf die makeCompoundImage und am Ende rufen Sie die nullVarsForCompoundImDrawing , um die Ressourcen nullVarsForCompoundImDrawing :

 private static Bitmap notColoredBitmap; private static Bitmap coloredBitmap; private static Bitmap notColoredWithMaskBitmap; private static Bitmap finalBitmap; private static Canvas notColoredWithMaskCanvas; private static Paint paintForMask; private static Paint smoothPaint; private static Canvas finalCanvas; private static RectF rectForMask; public static void initializeVarsForCompoundImDrawing() { Context context = MainApplication.getContext(); notColoredBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.not_colored); coloredBitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.colored); paintForMask = new Paint(Paint.ANTI_ALIAS_FLAG); paintForMask.setStyle(Paint.Style.FILL); paintForMask.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); rectForMask = new RectF(0, 0, notColoredBitmap.getWidth(), notColoredBitmap.getHeight()); smoothPaint = new Paint(Paint.ANTI_ALIAS_FLAG); } public static void nullVarsForCompoundImDrawing() { notColoredBitmap = null; coloredBitmap = null; paintForMask = null; rectForMask = null; smoothPaint = null; } public static void makeCompoundImage(ImageView imageView, int angle) { notColoredWithMaskBitmap = Bitmap.createBitmap(notColoredBitmap.getWidth(), notColoredBitmap.getHeight(), Bitmap.Config.ARGB_8888); notColoredWithMaskCanvas = new Canvas(notColoredWithMaskBitmap); notColoredWithMaskCanvas.drawBitmap(notColoredBitmap, 0, 0, smoothPaint); notColoredWithMaskCanvas.drawArc(rectForMask, 270, angle, true, paintForMask); finalBitmap = Bitmap.createBitmap(notColoredBitmap.getWidth(), notColoredBitmap.getHeight(), Bitmap.Config.ARGB_8888); finalCanvas = new Canvas(finalBitmap); finalCanvas.drawBitmap(coloredBitmap, 0, 0, smoothPaint); finalCanvas.drawBitmap(notColoredWithMaskBitmap, 0, 0, smoothPaint); imageView.setImageBitmap(finalBitmap); } 

Die erste Frage: Ist es möglich, diesen Code zu verbessern, um weniger Ressourcen zu verwenden?
Die zweite Frage: Wie kann ich den Text der finalBitmap (jetzt ist es ein TextView der am oberen ImageView des ImageView mit dem Bild ImageView wird)?

  • Blick in die Mitte des Layouts, wenn genügend Platz vorhanden ist
  • Fehler: (26, 0) Gradle DSL-Methode nicht gefunden: 'runProguard ()'
  • Android Lollipop, AppCompat ActionBar benutzerdefinierte Ansicht nimmt nicht die gesamte Bildschirmbreite auf
  • Ich erinnere mich nicht an mein android debug.keystore Passwort
  • Android Sqlite IN, NICHT IN Syntax
  • Wie zu beschleunigen Android ndk baut
  • Ändern der EditText-Unterzeilenfarbe mit appcompat v7
  • FrameLayout Margin funktioniert nicht
  • Ich suche nach vorne in YouTube HTML5 Video über Android WebView
  • Laden von Layout in onCreateView für benutzerdefinierte Präferenz
  • Android GridVIew Ändern Sie die Anzahl der Spalten je nach Ausrichtung
  • Warum ist das Hinzufügen eines OnClickListener innerhalb von onBindViewHolder eines RecyclerView.Adapter als schlechte Praxis?
  • 3 Solutions collect form web for “Zeichnen eines kundenspezifischen Kreissegments dynamisch”

    Sie können mein Projekt als Beispiel https://github.com/donvigo/CustomProgressControls verwenden . Es ist noch nicht dokumentiert auf github, aber ich hoffe du wirst meinen Code verstehen 🙂

    EDIT: Text im Kreis ist es kein TextView , es wird mit paint gezeichnet.

    Beantworten Sie Ihre Fragen: ja es kann einfacher gemacht werden, viel einfacher:

     public class Ring extends View { private Bitmap mBack; private Paint mPaint; private RectF mOval; private Paint mTextPaint; public Ring(Context context) { super(context); Resources res = getResources(); mBack = BitmapFactory.decodeResource(res, R.drawable.back); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); Bitmap ring = BitmapFactory.decodeResource(res, R.drawable.ring); mPaint.setShader(new BitmapShader(ring, TileMode.CLAMP, TileMode.CLAMP)); mOval = new RectF(0, 0, mBack.getWidth(), mBack.getHeight()); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setTextSize(24); mTextPaint.setTextAlign(Align.CENTER); } @Override protected void onDraw(Canvas canvas) { canvas.translate((getWidth() - mBack.getWidth()) / 2, (getHeight() - mBack.getHeight()) / 2); canvas.drawBitmap(mBack, 0, 0, null); float angle = 220; canvas.drawArc(mOval, -90, angle, true, mPaint); canvas.drawText("Text", mBack.getWidth() / 2, (mBack.getHeight() - mTextPaint.ascent()) / 2, mTextPaint); } } 

    BEARBEITEN:

    Und das ist eine alternative Lösung (keine Zentrierung, kein Text im Inneren, nur ein Konzept)

     class Ring extends View { private Bitmap back; private Bitmap ring; private RectF oval; private Paint arcPaint; public Ring(Context context) { super(context); Resources res = getResources(); back = BitmapFactory.decodeResource(res, R.drawable.back); ring = BitmapFactory.decodeResource(res, R.drawable.ring); arcPaint = new Paint(); arcPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); oval = new RectF(-1, -1, ring.getWidth()+1, ring.getHeight()+1); } @Override protected void onDraw(Canvas canvas) { canvas.drawARGB(0xaa, 0, 255, 0); canvas.drawBitmap(back, 0, 0, null); canvas.saveLayer(oval, null, Canvas.HAS_ALPHA_LAYER_SAVE_FLAG); canvas.drawBitmap(ring, 0, 0, null); float angle = 300; canvas.drawArc(oval, angle-90, 360-angle, true, arcPaint); canvas.restore(); } } 

    Ich habe ähnliche Sachen gemacht – animierte Fortschrittsbalken, wie auf deinem Bild, aber jeder zweite Zustand der Fortschrittsbalken änderte sich. Im Inneren hatte ich Zeittext, der bis zum Ablauf des Laufens blieb. Ich werde hier nur meine ganze Ansicht setzen, vielleicht wäre es für jemanden nützlich.

     public class TickerView extends View { private Paint mPaint, backPaint; private RectF mOval; private Paint mTextPaint; private int time; private float progress = 100; public TickerView(Context context) { super(context); init(); } public TickerView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public TickerView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.WHITE); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(UIHelper.getPixel(1));//1dp mPaint.setDither(true); // set the dither to true mPaint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want mPaint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too mPaint.setPathEffect(new PathEffect()); // set the path effect when they join. backPaint = new Paint(Paint.ANTI_ALIAS_FLAG); backPaint.setColor(ColorManager.roseLine); backPaint.setStyle(Paint.Style.STROKE); backPaint.setStrokeWidth(UIHelper.getPixel(1));//1dp backPaint.setDither(true); // set the dither to true backPaint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want backPaint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too backPaint.setPathEffect(new PathEffect()); // set the path effect when they join. measure(MeasureSpec.EXACTLY, View.MeasureSpec.EXACTLY); mOval = new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()); mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mTextPaint.setColor(Color.WHITE); mTextPaint.setTypeface(FontSetter.HelveticaNeueLight); mTextPaint.setTextSize(UIHelper.getPixel(15)); mTextPaint.setTextAlign(Paint.Align.CENTER); mOval = new RectF(UIHelper.getPixel(1), UIHelper.getPixel(1), getWidth(), getHeight()); } /** * * @param persent in range [0..1] * @param time - seconds left before progress will be executed */ public void setProgress(float persent, int time){ this.progress = persent; this.time = time; invalidate(); } @Override protected void onDraw(Canvas canvas) { canvas.drawText("" + time, getWidth() / 2, (getHeight() - mTextPaint.ascent()) / 2, mTextPaint); mOval.right = getWidth() - UIHelper.getPixel(1); mOval.bottom = getHeight() - UIHelper.getPixel(1); canvas.drawArc(mOval, 0, 360, false, backPaint); int angle = (int)( progress * 360 ); canvas.drawArc(mOval, -90, angle, false, mPaint); } 

    }

    Das Android ist ein Google Android Fan-Website, Alles über Android Phones, Android Wear, Android Dev und Android Spiele Apps und so weiter.