How to have an image with a dynamic text in it, all in a drawable, like the “today” action item on Google Calendar app?

前端 未结 2 1534
無奈伤痛
無奈伤痛 2021-02-19 07:43

Background

Google Calendar app has an action item that dynamically change according to the current day (\"today\"):

I\'m required to do a very similar

2条回答
  •  慢半拍i
    慢半拍i (楼主)
    2021-02-19 08:19

    Reference is made to your other question "How to fully mimic Action item view in the toolbar, for a customized one?"

    I have incorporated the approach in my answer to the above-referenced question into your implementation of a custom drawable in your answer to this question. Below is a new version of TextDrawable.java that dynamically builds a boxed TextView for display as the desired icon for a menu item. It avoids drawing caches and simply manages a TextView internally for display.

    TextDrawable.java

    public class TextDrawable extends Drawable {
        private final int mIntrinsicSize;
        private final TextView mTextView;
    
        public TextDrawable(Context context, CharSequence text) {
            mIntrinsicSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DRAWABLE_SIZE,
                                                             context.getResources().getDisplayMetrics());
            mTextView = createTextView(context, text);
            mTextView.setWidth(mIntrinsicSize);
            mTextView.setHeight(mIntrinsicSize);
            mTextView.measure(mIntrinsicSize, mIntrinsicSize);
            mTextView.layout(0, 0, mIntrinsicSize, mIntrinsicSize);
        }
    
        private TextView createTextView(Context context, CharSequence text) {
            TextView textView = new TextView(context);
    //        textView.setId(View.generateViewId()); // API 17+
            LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            lp.gravity = Gravity.CENTER;
            textView.setLayoutParams(lp);
            textView.setGravity(Gravity.CENTER);
            textView.setBackgroundResource(R.drawable.ic_backtodate);
            textView.setTextColor(Color.WHITE);
            textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TEXT_SIZE);
            textView.setText(text);
            return textView;
        }
    
        public void setText(CharSequence text) {
            mTextView.setText(text);
            invalidateSelf();
        }
    
        @Override
        public void draw(@NonNull Canvas canvas) {
            mTextView.draw(canvas);
        }
    
        @Override
        public int getOpacity() {
            return PixelFormat.OPAQUE;
        }
    
        @Override
        public int getIntrinsicWidth() {
            return mIntrinsicSize;
        }
    
        @Override
        public int getIntrinsicHeight() {
            return mIntrinsicSize;
        }
    
        @Override
        public void setAlpha(int alpha) {
        }
    
        @Override
        public void setColorFilter(ColorFilter filter) {
        }
    
        private static final int DRAWABLE_SIZE = 32; // device-independent pixels (DP)
        private static final int DEFAULT_TEXT_SIZE = 12; // device-independent pixels (DP)
    }
    

    Invoke this custom Drawable as follows (Kotlin):

    mTextDrawable = TextDrawable(this, "1")
    menu.add("goToToday").setIcon(mTextDrawable).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
    

    To change the displayed date (Kotlin):

    mTextDrawable?.setText(i.toString())    
    

提交回复
热议问题