2015-11-13 11 views
6

Các công cụ Android Studio Vector Tài sản chuyển đổi drawable vector để PNG-s cho các thiết bị pre-Lollipop nhưng tôi nhận được chất lượng thực sự xấu PNG-s như bạn có thể xem tại đây:Làm thế nào để thiết lập kích thước của vector drawable bên trong của một nút trong Android?

Converted Vector to PNG

Hơn thế nữa là của nút màu nền rắn được coi là màu xanh lá cây ánh sáng này mà bạn nhìn thấy ở bên trái nhưng drawable ghi đè lên nó:

<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> 

các xml cho drawable là (mặc định từ các biểu tượng tài liệu):

<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"/> 

Tôi cũng muốn làm biểu tượng xuất hiện nhỏ hơn một chút bằng cách tinh chỉnh các giá trị và tôi nhận thấy ngày càng tăng kích thước viewport giảm vào biểu tượng nhưng tôi không chắc là tôi hiểu tại sao.

Vì vậy: Làm cách nào để làm cho biểu tượng và PNG được tạo ra xuất hiện nhỏ hơn, ít bị mờ hơn và với màu nền được đặt trong tệp tài nguyên? Cảm ơn bạn.

EDIT: Tôi quản lý để có được màu nền vững chắc với các biểu tượng bằng cách kết hợp chúng trong một tập tin xml riêng biệt với lớp-danh sách:

<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" 
    /> 

Kết quả là:

The result of some tweaking

Tôi đã quản lý để giảm làm mờ bằng cách tăng chiều rộng và chiều cao của vector có thể vẽ được. Tuy nhiên, không có các thẻ android:top|bottom|left|right, có thể vẽ được trên toàn bộ khu vực của nút. Nút thứ hai không cần phải có màu nền vì vậy tôi không sử dụng các thẻ danh sách lớp => không có cách nào để đặt lề top|bottom|left|right cho đối tượng có thể vẽ.
Nếu tôi giảm kích thước nút, điều tôi đang làm là giảm vùng có thể nhấp của nút.

Câu hỏi được cập nhật của tôi là cách đặt kích thước của vectơ có thể vẽ được bên trong nút/nút chuyển đổi/nút radio mà không làm giảm kích thước của nút?

CẬP NHẬT
Tôi không thể tìm cách thay đổi kích thước véc tơ có thể vẽ trên thiết bị API 21 trước. Vì vậy, thay vào đó tôi đã tự làm các nút nhỏ hơn và tăng diện tích cảm ứng của mỗi nút.

+1

Chế độ xem là không gian trong đó biểu tượng được vẽ và đường dẫn Dữ liệu cho các tọa độ khác nhau hướng dẫn hình dạng nên là gì. Ví dụ, nếu bạn có một khung nhìn 24 x 24 và vẽ một đường thẳng từ điểm 0,12 đến điểm 24,12, thì đó là một đường ngang được vẽ một nửa xuống khung nhìn của bạn từ bên này sang bên kia. Nếu bạn thay đổi kích thước khung nhìn thành 48 x 48 nhưng dòng của bạn vẫn từ điểm 0,12 đến điểm 24,12 thì nó không bắt đầu từ nửa chừng nữa và nó sẽ không đạt đến phía bên kia của khung nhìn. –

Trả lời

10

Cách tiếp cận chính xác để chia tỷ lệ bất kỳ có thể vẽ là sử dụng vectorDrawable.setBounds(left,top,right,bottom), nhưng tiếc là không hoạt động cho các đối tượng vẽ vector (tại sao Google?).

Vì vậy, để giải quyết sự cố, tôi chuyển đổi chúng thành bitmap drawable và cho phép chúng tôi sử dụng phương thức setBounds trên bitmap drawable. Lưu ý rằng bạn đang chia tỷ lệ bitmap ở đây, vì vậy bạn có thể mất một số độ sắc nét của hình ảnh. Tôi chủ yếu sử dụng những phương pháp đó khi tôi cần sử dụng drawable của tôi như là một hợp chất drawable của một văn bản xem hoặc một nút ví dụ.

Tôi đã kết thúc viết một lớp trợ giúp sẽ tải một vector drawable thiết lập một màu cho nó và trả về một bitmap drawable mà bạn thực sự có thể mở rộng và màu như bạn muốn. Tôi đã thử nghiệm nó cho các cấp API 19 lên đến 23, và nó hoạt động.

Đừng quên sử dụng vectorDrawables.useSupportLibrary = true trong số build.gradle.

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; 
    } 
} 

Bây giờ tôi sẽ sử dụng lớp helper này như thế này:

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); 

Điều quan trọng là sử dụng một bối cảnh của một Xem hay Hoạt động, không phải là bối cảnh ứng dụng! Hy vọng nó sẽ giải quyết vấn đề của bạn, hoặc giúp đỡ người khác. Và nếu ai đó có một giải pháp tốt hơn và sạch hơn, tôi cũng muốn biết.

0

MyTextView lớp:

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> 

Cách sử dụng:

<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" /> 

Lưu ý: Vấn đề duy nhất ở đây là một vector chưa sửa đổi (drawableWidthHeightCompatTextView didn' t sử dụng), trong đó width vàcủa vectơlà 24,
Không phải là bằng kích thước trên thiết bị, với vectơ được đổi kích thước (số widthheight là 12 và drawableWidthHeightCompatTextView="24").

Các vấn đề liên quan