【问题标题】:custom button padding and text size issue自定义按钮填充和文本大小问题
【发布时间】:2016-09-19 20:27:16
【问题描述】:

我通过扩展LinearLayout 创建了一个自定义视图,使其成为带有图标和文本的按钮。

这是课程 -

public class FancyButton extends LinearLayout {

    private final static float CORNER_RADIUS = 3.0f;

    private String mButtonText;
    private String mFontName;
    private float mButtonTextSize;
    private int mBackgroundColor;
    private int mSeparatorColor;
    private Drawable mIcon;

    private Typeface mButtonTextTypeface;

    private Bitmap maskBitmap;
    private Paint paint, maskPaint;
    private float cornerRadius;


    public FancyButton(Context context) {
        super(context);
        init(context, null, 0);
    }

    public FancyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context, attrs, 0);
    }

    public FancyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context, attrs, defStyleAttr);
    }


    private void init(Context context, AttributeSet attrs, int defStyleAttr) {
        if (attrs != null) {

            parseSignInButtonAttrs(context, attrs, defStyleAttr, R.style.FancyButton);


            LayoutInflater inflater = (LayoutInflater) context
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            inflater.inflate(R.layout.fancy_button_widget, this, true);

            setOrientation(LinearLayout.HORIZONTAL);
            setGravity(Gravity.CENTER_VERTICAL);
            setPadding(20, 20, 20, 20);


            ImageView buttonIconImageView = (ImageView) getChildAt(0);
            View separator = getChildAt(1);
            TextView buttonTextView = (TextView) getChildAt(2);

            if (null != mButtonTextTypeface)
                buttonTextView.setTypeface(mButtonTextTypeface);

            setBackgroundColor(mBackgroundColor);

            buttonIconImageView.setImageDrawable(mIcon);
            separator.setBackgroundColor(mSeparatorColor);

            buttonTextView.setTextColor(Color.WHITE);
            buttonTextView.setText(mButtonText);
            buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mButtonTextSize);

            if (null != mFontName)
                mButtonTextTypeface = TypefaceLoader.get(getContext(), "fonts/" + mFontName);

            initCornerRadiusDraw(context);

        }
    }

    private void initCornerRadiusDraw(Context context) {
        DisplayMetrics metrics = context.getResources().getDisplayMetrics();
        cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, CORNER_RADIUS, metrics);

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);

        maskPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

        setWillNotDraw(false);
    }

    private void parseSignInButtonAttrs(Context context, AttributeSet attrs, final int defStyleAttr, final int defStyleRes) {
        final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.FancyButton, defStyleAttr, defStyleRes);

        mFontName = a.getString(R.styleable.FancyButton_buttonFont);
        mButtonText = a.getString(R.styleable.FancyButton_buttonText);
        mBackgroundColor = a.getColor(R.styleable.FancyButton_buttonBackgroundColor, ContextCompat.getColor(context, R.color.app_blue));
        mIcon = a.getDrawable(R.styleable.FancyButton_buttonIcon);

        mButtonTextSize = a.getDimension(R.styleable.FancyButton_buttonTextSize, 12);

        mSeparatorColor = CommonUtils.getDarkerShade(mBackgroundColor);

        a.recycle();
    }

    @Override
    public void draw(Canvas canvas) {
        Bitmap offscreenBitmap = Bitmap.createBitmap(canvas.getWidth(), canvas.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas offscreenCanvas = new Canvas(offscreenBitmap);

        super.draw(offscreenCanvas);

        if (maskBitmap == null) {
            maskBitmap = createMask(canvas.getWidth(), canvas.getHeight());
        }

        offscreenCanvas.drawBitmap(maskBitmap, 0f, 0f, maskPaint);
        canvas.drawBitmap(offscreenBitmap, 0f, 0f, paint);
    }

    private Bitmap createMask(int width, int height) {
        Bitmap mask = Bitmap.createBitmap(width, height, Bitmap.Config.ALPHA_8);
        Canvas canvas = new Canvas(mask);

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.WHITE);

        canvas.drawRect(0, 0, width, height, paint);

        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        canvas.drawRoundRect(new RectF(0, 0, width, height), cornerRadius, cornerRadius, paint);

        return mask;
    }
}

现在这会创建一个如下所示的按钮 -

如您所见,文本看起来很大,并且没有添加填充。

<com.sachingutte.testapp.views.FancyButton
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/rounded_box"
        custom:buttonBackgroundColor="@color/app_blue"
        custom:buttonIcon="@drawable/ic_menu_gallery"
        custom:buttonText="@string/dashboard"
        custom:buttonTextColor="@android:color/white"
        custom:buttonTextSize="12sp" />

编辑布局膨胀 -

<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:src="@drawable/ic_menu_camera" />

    <View
        android:layout_width="1dp"
        android:layout_height="match_parent"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:background="@color/app_blue" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="12sp" />
</merge>

【问题讨论】:

  • mButtonTextSize = a.getDimension(R.styleable.FancyButton_buttonTextSize, 12);将 12 更改为 10 并检查
  • @Pravin 问题是12sp 应用于此自定义视图的文本大小与默认按钮小部件不匹配。当布局中使用相同的单位大小时,它会按原样显示。正是这种视图使文本显得很大。它不成比例,也不随设备的密度缩放。

标签: android android-linearlayout android-view android-custom-view


【解决方案1】:

填充

从您提供的屏幕中,我可以看到实际上正在应用填充。我可以看到以某种方式显示1dp 宽View:

您只是将其设置为一个相对较小的值 (20px)。


文字大小

问题在于这个调用:

mButtonTextSize = a.getDimension(R.styleable.FancyButton_buttonTextSize, 12);

正如您可以从docs 中看到的那样:

单位转换基于与此 TypedArray 对象来自的资源关联的当前 DisplayMetrics。

所以当您调用getDimension 时会涉及到单位转换。因此,您不会得到sp 值,而是基于特定屏幕的转换值。

你可以做的是:

  1. 如果您希望您的默认文本大小正好是 12sp,您可以通过以下方式获得:

float defaultTextSize = 12 * context.getResources().getDisplayMetrics.scaledDensity;
  1. 用这个获得你的价值:

mButtonTextSize = a.getDimensionPixelSize(R.styleable.FancyButton_buttonTextSize, (int) defaultTextSize);
  1. 以这种方式将其设置为您的TextView:

buttonTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, mButtonTextSize); 

【讨论】:

  • 谢谢。我将按照您的建议检查文本大小修复。但是关于填充,即使我给它一个很大的值,比如 100dp;填充仍然与图像中所示相同。
  • @SachinGutte 是你的rounded_box 可绘制9-patch?
  • 其实背景rounded_box对自定义视图没有作用。它在那里是因为我忘了删除它。我正在使用onDraw() 直接在视图上应用圆形边框。
  • @SachinGutte 是的,关于那个...首先,而不是覆盖draw(),你应该覆盖onDraw(),更重要的是,在每一个绘图过程中,你正在创建两个位图,你绝不回收或重复使用。这肯定会导致OutOfMemory 异常。
  • @SachinGutte 并进一步查看后,尝试将 canvas 而不是 overscreenCanvas 传递到 super.draw(...); (仅用于测试)。这也可能会导致布局的填充出现问题。
猜你喜欢
  • 1970-01-01
  • 2021-12-28
  • 2014-06-07
  • 1970-01-01
  • 2015-01-13
  • 2013-07-08
  • 2018-02-03
  • 2017-11-27
  • 2013-05-05
相关资源
最近更新 更多