2015-11-13 12 views
6

Die Android Studio Vector Assets Tools konvertieren Vektor ziehbar zu PNG-s für Geräte Pre-Lutscher, aber ich bekomme wirklich schlechte Qualität PNG-s, wie Sie hier sehen können:Wie wird die Größe von Vektor innerhalb einer Schaltfläche in Android-Zeichen festgelegt?

Converted Vector to PNG

Was, dass die mehr ist, ist Taste Hintergrund feste Farbe soll dieses Licht grün sein, die Sie auf der linke Seite sehen, aber die ziehbar überschreibt:

<item android:state_checked="true" 
    android:drawable="@drawable/show"> 
    <shape android:shape="rectangle"> 
     <corners android:bottomRightRadius="8dp"/> 
     <solid android:color="@color/waveComponentGreen"/> 
    </shape> 
</item> 

<item android:state_checked="false" 
    android:drawable="@drawable/hide"> 
    <shape android:shape="rectangle"> 
     <corners android:bottomRightRadius="8dp"/> 
     <solid android:color="@color/waveComponentGreen"/> 
    </shape> 
</item> 

die xml für die ziehbar ist (der Standard aus dem Material Icons):

<vector xmlns:android="http://schemas.android.com/apk/res/android" 
    android:width="24dp" 
    android:height="24dp" 
    android:viewportWidth="24.0" 
    android:viewportHeight="24.0"> 
<path 
    android:fillColor="#FF000000" 
    android:pathData="M8.59,16.34l4.58,-4.59 -4.58,-4.59L10,5.75l6,6 -6,6z"/> 

Ich wollte auch das Symbol erscheint ein wenig kleiner machen, indem die Werte zwicken und ich bemerkte, verringert das Symbol, um die Ansichtsfenster Dimensionen zu erhöhen, aber ich bin nicht sicher, ob ich verstehen, warum.

Also: Wie mache ich das Symbol und die generierte PNG kleiner, weniger verschwommen und mit der Hintergrundfarbe in der Ressource-Datei festgelegt? Vielen Dank.

EDIT: Ich es geschafft, die einfarbigen Hintergrund mit dem Symbol zu erhalten, indem sie in einer separaten XML-Datei mit Schicht-Listen kombiniert:

<layer-list 
xmlns:android="http://schemas.android.com/apk/res/android" > 
<item> 
    <shape android:shape="rectangle"> 
     <corners android:bottomRightRadius="10dp"/> 
     <solid android:color="@color/waveComponentGreen"/> 
    </shape> 
</item> 
<item android:drawable="@drawable/show" 
    android:top="10dp" 
    android:bottom="10dp" 
    android:left="10dp" 
    android:right="10dp" 
    /> 

Das Ergebnis ist:

Ich habe es geschafft, die Unschärfe zu reduzieren, indem Sie die Breite und Höhe der Vektor zeichnbar. Ohne die Tags android:top|bottom|left|right erstreckt sich das Zeichen über den gesamten Bereich der Schaltfläche. Die zweite Schaltfläche muss keine Hintergrundfarbe haben, daher verwende ich nicht die Layerlisten-Tags => keine Möglichkeit, einen top|bottom|left|right Rand für das Zeichen festzulegen.
Wenn ich die Größe der Schaltfläche reduzieren, was ich mache, ist die klickbare Fläche der Schaltfläche zu reduzieren.

Meine aktualisierte Frage ist, wie man die Größe des Vektors einziehbar innerhalb eines Knopfes/Wechselknopfes/Radiobuttons einstellt, ohne die Größe des Knopfes selbst zu reduzieren?

UPDATE
ich konnte nicht einen Weg finden, um den Vektor ziehbar auf Pre-API 21 Geräte zu ändern. Also habe ich stattdessen die Buttons selbst verkleinert und den Touchbereich jedes Buttons vergrößert.

+1

Das Ansichtsfenster ist das Feld, in dem das Symbol gezeichnet wird, und pathData gibt die verschiedenen Koordinaten an, die angeben, wie die Form aussehen soll. Wenn Sie beispielsweise ein Ansichtsfenster von 24 mal 24 haben und eine gerade Linie von Punkt 0,12 bis Punkt 24,12 ziehen, dann ist dies eine horizontale Linie, die auf halbem Weg durch Ihr Ansichtsfenster von einer Seite zur anderen gezogen wird. Wenn Sie die Größe des Darstellungsbereichs auf 48 mal 48 ändern, die Linie aber immer noch von Punkt 0,12 zu Punkt 24,12 ist, beginnt sie nicht mehr auf halbem Weg und sie wird nicht auf die andere Seite des Darstellungsbereichs gelangen. –

Antwort

10

Der richtige Ansatz, um alle Zeichen zu skalieren wäre vectorDrawable.setBounds(left,top,right,bottom), , aber das funktioniert leider nicht für Vektor-Zeichen (warum Google?).

Als Workaround lade ich meine Vektor-Drawables, konvertiere sie in Bitmap-Zeichen und das ermöglicht uns, die setBounds-Methode für die Bitmap-Zeichenfunktion zu verwenden. Beachten Sie, dass Sie hier Bitmaps skalieren, damit Sie die Schärfe des Bildes verlieren können. Ich benutze hauptsächlich diese Methoden, wenn ich meinen Drawable als Compound verwenden muss, um beispielsweise eine Textansicht oder einen Button zu zeichnen.

Ich schrieb eine Hilfsklasse, die einen Vector Drawable lädt, setzte eine Tönung darauf und gab eine Bitmap zurück, die man nach Belieben skalieren und tönen konnte. Ich habe es für API-Level 19 bis 23 getestet, und es funktioniert.

Vergessen Sie nicht vectorDrawables.useSupportLibrary = true in Ihrem build.gradle zu verwenden.

public class VectorDrawableUtils { 

/** 
* Gets a Bitmap from provided Vector Drawable image 
* 
* @param vd VectorDrawable 
* @return Bitmap 
*/ 
public static Optional<Bitmap> createBitmapFromVectorDrawable(final @NonNull Drawable vd) { 
    try { 
     Bitmap bitmap; 
     bitmap = Bitmap.createBitmap(vd.getIntrinsicWidth(), vd.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); 
     Canvas canvas = new Canvas(bitmap); 
     vd.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); 
     vd.draw(canvas); 
     return Optional.of(bitmap); 
    } catch (OutOfMemoryError e) { 
     Injector.getDependency(getContext(), IEventTracker.class).logHandledException(e); 
     return Optional.empty(); 
    } 
} 

/** 
* Loads vector drawable and apply tint color on it. 
*/ 
public static Drawable loadVectorDrawableWithTintColor(final @DrawableRes int vdRes, 
                 final @ColorRes int clrRes,final Context context) { 
    Drawable drawable = ContextCompat.getDrawable(context, vdRes); 
    DrawableCompat.setTint(drawable, getContext().getResources().getColor(clrRes)); 
    return drawable; 
} 

/** 
* Converts given vector drawable to Bitmap drawable 
*/ 
public static BitmapDrawable convertVectorDrawableToBitmapDrawable(final @NonNull Drawable vd) { 
    //it is safe to create empty bitmap drawable from null source 
    return new BitmapDrawable(createBitmapFromVectorDrawable(vd).get()); 
} 

/** 
* Loads vector drawable , aplys tint on it and returns a wrapped bitmap drawable. 
* Bitmap drawable can be resized using setBounds method (unlike the VectorDrawable) 
* @param context Requires view context ! 
*/ 
public static Drawable loadVectorDrawableWithTint(
     final @DrawableRes int vectorDrawableRes, final @ColorRes int colorRes,final Context context) { 
    Drawable vd = VectorDrawableUtils.loadVectorDrawableWithTintColor(vectorDrawableRes, 
      colorRes, context); 
    final BitmapDrawable bitmapDrawable = VectorDrawableUtils.convertVectorDrawableToBitmapDrawable(vd); 
    ColorStateList tint = ContextCompat.getColorStateList(context,colorRes); 
    final Drawable wrappedDrawable = DrawableCompat.wrap(bitmapDrawable); 
    DrawableCompat.setTintList(wrappedDrawable,tint); 
    return wrappedDrawable; 
    } 
} 

Nun würde ich diese Hilfsklasse wie folgt verwenden:

Drawable bd = VectorDrawableUtils.loadVectorDrawableWithTint(
       R.drawable.ic_dropdown, R.color.black,getContext()); 
     bd.setBounds(0, 0, textView.getMeasuredHeight(), textView.getMeasuredHeight()); 
     textView.setCompoundDrawablesWithIntrinsicBounds(null, null, bd, null); 

Es ist wichtig, einen Kontext einer Ansicht oder Aktivität zu verwenden, nicht den Anwendungskontext! Hoffe, es wird dein Problem lösen oder jemand anderem helfen. Und wenn jemand eine bessere und sauberere Lösung hat, interessiert mich das auch.

0

MyTextView Klasse:

public class MyTextView extends AppCompatTextView { 

public MyTextView(Context context) { 
    super(context); 
} 

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

public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    initAttrs(context, attrs); 
} 

void initAttrs(Context context, AttributeSet attrs) { 
    if (attrs != null) { 
     TypedArray attributeArray = context.obtainStyledAttributes(
       attrs, 
       R.styleable.MyTextView); 

     int defaultWidthHeight = 0; 
     int widthHeight = 0; 
     Drawable drawableLeft = null; 
     Drawable drawableStart = null; 
     Drawable drawableRight = null; 
     Drawable drawableEnd = null; 
     Drawable drawableBottom = null; 
     Drawable drawableTop = null; 

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 
      drawableLeft = attributeArray.getDrawable(R.styleable.MyTextView_drawableLeftCompatTextView); 
      drawableStart = attributeArray.getDrawable(R.styleable.MyTextView_drawableStartCompatTextView); 
      drawableRight = attributeArray.getDrawable(R.styleable.MyTextView_drawableRightCompatTextView); 
      drawableEnd = attributeArray.getDrawable(R.styleable.MyTextView_drawableEndCompatTextView); 
      drawableBottom = attributeArray.getDrawable(R.styleable.MyTextView_drawableBottomCompatTextView); 
      drawableTop = attributeArray.getDrawable(R.styleable.MyTextView_drawableTopCompatTextView); 
     } else { 
      final int drawableLeftId = attributeArray.getResourceId(R.styleable.MyTextView_drawableLeftCompatTextView, -1); 
      final int drawableStartId = attributeArray.getResourceId(R.styleable.MyTextView_drawableStartCompatTextView, -1); 
      final int drawableRightId = attributeArray.getResourceId(R.styleable.MyTextView_drawableRightCompatTextView, -1); 
      final int drawableEndId = attributeArray.getResourceId(R.styleable.MyTextView_drawableEndCompatTextView, -1); 
      final int drawableBottomId = attributeArray.getResourceId(R.styleable.MyTextView_drawableBottomCompatTextView, -1); 
      final int drawableTopId = attributeArray.getResourceId(R.styleable.MyTextView_drawableTopCompatTextView, -1); 

      if (drawableLeftId != -1) 
       drawableLeft = AppCompatResources.getDrawable(context, drawableLeftId); 
      if(drawableStartId != -1) 
       drawableStart = AppCompatResources.getDrawable(context, drawableStartId); 
      if (drawableRightId != -1) 
       drawableRight = AppCompatResources.getDrawable(context, drawableRightId); 
      if(drawableEndId != -1) 
       drawableEnd = AppCompatResources.getDrawable(context, drawableEndId); 
      if (drawableBottomId != -1) 
       drawableBottom = AppCompatResources.getDrawable(context, drawableBottomId); 
      if (drawableTopId != -1) 
       drawableTop = AppCompatResources.getDrawable(context, drawableTopId); 
     } 

     if(!attributeArray.hasValue(R.styleable.MyTextView_drawableWidthHeightCompatTextView)) { 
      if (attributeArray.hasValue(R.styleable.MyTextView_drawableLeftCompatTextView)) { 
       defaultWidthHeight = drawableLeft.getIntrinsicWidth(); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableStartCompatTextView)) { 
       defaultWidthHeight = drawableStart.getIntrinsicWidth(); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableRightCompatTextView)) { 
       defaultWidthHeight = drawableRight.getIntrinsicWidth(); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableEndCompatTextView)) { 
       defaultWidthHeight = drawableEnd.getIntrinsicWidth(); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableBottomCompatTextView)) { 
       defaultWidthHeight = drawableBottom.getIntrinsicWidth(); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableTopCompatTextView)) { 
       defaultWidthHeight = drawableTop.getIntrinsicWidth(); 
      } 

      widthHeight = attributeArray.getInt(R.styleable.MyTextView_drawableWidthHeightCompatTextView, defaultWidthHeight); 
     } else 
      widthHeight = attributeArray.getInt(R.styleable.MyTextView_drawableWidthHeightCompatTextView, defaultWidthHeight); 

     if(attributeArray.hasValue(R.styleable.MyTextView_drawableColorCompatTextView)){ 
      ColorStateList tintColor = attributeArray.getColorStateList(R.styleable.MyTextView_drawableColorCompatTextView); 
      if (attributeArray.hasValue(R.styleable.MyTextView_drawableLeftCompatTextView)) { 
       //drawableLeft.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableLeft, tintColor); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableStartCompatTextView)) { 
       //drawableStart.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableStart, tintColor); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableRightCompatTextView)) { 
       //drawableRight.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableRight, tintColor); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableEndCompatTextView)) { 
       //drawableEnd.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableEnd, tintColor); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableBottomCompatTextView)) { 
       //drawableBottom.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableBottom, tintColor); 
      } else if (attributeArray.hasValue(R.styleable.MyTextView_drawableTopCompatTextView)) { 
       //drawableTop.setColorFilter(new PorterDuffColorFilter(tintColor.getDefaultColor(), PorterDuff.Mode.MULTIPLY)); 
       DrawableCompat.setTintList(drawableTop, tintColor); 
      } 
     } 

     WrappedDrawable drawableLeftWrapped = new WrappedDrawable(drawableLeft); 
     drawableLeftWrapped.setBounds(0, 0, widthHeight, widthHeight); 
     WrappedDrawable drawableStartWrapped = new WrappedDrawable(drawableStart); 
     drawableStartWrapped.setBounds(0, 0, widthHeight, widthHeight); 
     WrappedDrawable drawableRightWrapped = new WrappedDrawable(drawableRight); 
     drawableRightWrapped.setBounds(0, 0, widthHeight, widthHeight); 
     WrappedDrawable drawableEndWrapped = new WrappedDrawable(drawableEnd); 
     drawableEndWrapped.setBounds(0, 0, widthHeight, widthHeight); 
     WrappedDrawable drawableBottomWrapped = new WrappedDrawable(drawableBottom); 
     drawableBottomWrapped.setBounds(0, 0, widthHeight, widthHeight); 
     WrappedDrawable drawableTopWrapped = new WrappedDrawable(drawableTop); 
     drawableTopWrapped.setBounds(0, 0, widthHeight, widthHeight); 

     setCompoundDrawablesWithIntrinsicBounds(drawableLeftWrapped, drawableTopWrapped, drawableRightWrapped, drawableBottomWrapped); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) 
      setCompoundDrawablesRelativeWithIntrinsicBounds(drawableStartWrapped, drawableTopWrapped, drawableEndWrapped, drawableBottomWrapped); 

     attributeArray.recycle(); 
    } 
} 

class WrappedDrawable extends Drawable { 

    private final Drawable _drawable; 
    protected Drawable getDrawable() { 
     return _drawable; 
    } 

    public WrappedDrawable(Drawable drawable) { 
     super(); 
     _drawable = drawable; 
    } 

    @Override 
    public void setBounds(int left, int top, int right, int bottom) { 
     //update bounds to get correctly 
     super.setBounds(left, top, right, bottom); 
     Drawable drawable = getDrawable(); 
     if (drawable != null) { 
      drawable.setBounds(left, top, right, bottom); 
     } 
    } 

    @Override 
    public void setAlpha(int alpha) { 
     Drawable drawable = getDrawable(); 
     if (drawable != null) { 
      drawable.setAlpha(alpha); 
     } 
    } 

    @Override 
    public void setColorFilter(ColorFilter colorFilter) { 
     Drawable drawable = getDrawable(); 
     if (drawable != null) { 
      drawable.setColorFilter(colorFilter); 
     } 
    } 

    @Override 
    public int getOpacity() { 
     Drawable drawable = getDrawable(); 
     return drawable != null 
       ? drawable.getOpacity() 
       : PixelFormat.UNKNOWN; 
    } 

    @Override 
    public void draw(Canvas canvas) { 
     Drawable drawable = getDrawable(); 
     if (drawable != null) { 
      drawable.draw(canvas); 
     } 
    } 

    @Override 
    public int getIntrinsicWidth() { 
     Drawable drawable = getDrawable(); 
     return drawable != null 
       ? drawable.getBounds().width() 
       : 0; 
    } 

    @Override 
    public int getIntrinsicHeight() { 
     Drawable drawable = getDrawable(); 
     return drawable != null ? 
       drawable.getBounds().height() 
       : 0; 
    } 
} 
} 

attrs.xml:

<declare-styleable name="MyTextView"> 
    <attr name="drawableColorCompatTextView" format="reference|color"/> 
    <attr name="drawableWidthHeightCompatTextView" format="integer"/> 
    <attr name="drawableLeftCompatTextView" format="reference"/> 
    <attr name="drawableStartCompatTextView" format="reference"/> 
    <attr name="drawableRightCompatTextView" format="reference"/> 
    <attr name="drawableEndCompatTextView" format="reference"/> 
    <attr name="drawableTopCompatTextView" format="reference"/> 
    <attr name="drawableBottomCompatTextView" format="reference"/> 
</declare-styleable> 

Verbrauch:

<com.packagename.MyTextView 
    android:id="@+id/txtUserName" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    app:drawableLeftCompatTextView="@drawable/ic_username" 
    app:drawableStartCompatTextView="@drawable/ic_username" 
    app:drawableWidthHeightCompatTextView="48" 
    app:drawableColorCompatTextView="@color/blue" /> 

Hinweis: Das einzige Problem hier ist ein nicht modifiziertes Vektor (drawableWidthHeightCompatTextView didn‘ t verwenden), welcher Vektor width undistsind 24,
Ist das nicht gleiche Größe auf dem Gerät, mit Größe verändertem Vektor (Vectors width und height 12 und drawableWidthHeightCompatTextView="24").