and*_*per 13 android android-drawable android-toolbar
Google日历应用有一个动作项,可根据当天("今天")动态更改:
我需要做一个非常相似的事情,但周围的文字略有不同.
通过创建一个包含文本和图像的Drawable(基于此处),我确实成功地使其工作.
但是,我认为我做得不够好:
下面是完整的代码(也可在此项目中的):
TextDrawable.java
public class TextDrawable extends Drawable {
private static final int DEFAULT_COLOR = Color.WHITE;
private static final int DRAWABLE_SIZE = 24;
private static final int DEFAULT_TEXT_SIZE = 8;
private Paint mPaint;
private CharSequence mText;
private final int mIntrinstSize;
private final Drawable mDrawable;
public TextDrawable(Context context, CharSequence text) {
mText = text;
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(DEFAULT_COLOR);
mPaint.setTextAlign(Align.CENTER);
float textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TEXT_SIZE, context.getResources().getDisplayMetrics());
mPaint.setTextSize(textSize);
mIntrinstSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DRAWABLE_SIZE, context.getResources().getDisplayMetrics());
mDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_backtodate);
mDrawable.setBounds(0, 0, mIntrinstSize, mIntrinstSize);
}
@Override
public void draw(Canvas canvas) {
Rect bounds = getBounds();
mDrawable.draw(canvas);
canvas.drawText(mText, 0, mText.length(),
bounds.centerX(), bounds.centerY() + mPaint.getFontMetricsInt(null) / 3, mPaint); // this seems very wrong
}
@Override
public int getOpacity() {
return mPaint.getAlpha();
}
@Override
public int getIntrinsicWidth() {
return mIntrinstSize;
}
@Override
public int getIntrinsicHeight() {
return mIntrinstSize;
}
@Override
public void setAlpha(int alpha) {
mPaint.setAlpha(alpha);
}
@Override
public void setColorFilter(ColorFilter filter) {
mPaint.setColorFilter(filter);
}
}
Run Code Online (Sandbox Code Playgroud)
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val drawable = TextDrawable(this, "1")
imageView.setImageDrawable(drawable)
}
}
Run Code Online (Sandbox Code Playgroud)
ic_backtodate.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="25dp" android:height="25dp"
android:viewportHeight="76.0" android:viewportWidth="76.0">
<path
android:fillColor="#ffffff" android:fillType="evenOdd"
android:pathData="M47.294,60.997H28.704C21.148,60.997 15,54.755 15,47.083V28.905c0,-7.672 6.148,-13.913 13.704,-13.913h18.59C54.852,14.992 61,21.233 61,28.905v18.178c0,7.672 -6.148,13.914 -13.706,13.914zM57.592,28.905c0,-5.763 -4.62,-10.453 -10.298,-10.453h-18.59c-5.676,0 -10.296,4.69 -10.296,10.453v18.178c0,5.765 4.62,10.454 10.296,10.454h18.59c5.678,0 10.298,-4.689 10.298,-10.454z"/>
</vector>
Run Code Online (Sandbox Code Playgroud)
如何克服不同的字体问题?我已经全局使用"Lato"字体(不是在示例应用程序中,而是在真实应用程序中,使用支持库的"下载字体" API,但将它们内置到应用程序中),但我不认为Paint对象可以用它吧?
我怎样才能使文本居中?
我通过View-hierarchy工具查看了Google Calendar如何为此部分工作.对我来说,他们似乎只使用了TextView.他们是如何做到的呢?也许使用9补丁?但它对Toolbar项目有效吗?
编辑:
就目前而言,由于我的日程紧张,我不能使用可绘制的解决方案.如果能做得好,仍然会很高兴.
我目前的解决方案不涉及它.我只是使用一个模仿正常操作项的特殊视图.它并不完美(不能完全模仿真实的动作项目),但现在已经足够了.因为它不完美,我在这里写了一个新的线程.
编辑:因为这实际上可以很好地工作,并仍然作为一个正常的行动项目,我已经决定再试一次.
我已经设法很好地集中了文本,但字体现在是问题.似乎如果操作系统使用自己的字体,即使我将"Lato"设置为应用程序之一,它也不会用在我制作的drawable中:
我认为这是我需要解决的最后一个问题.
这是代码:
styles.xml
<item name="android:fontFamily" tools:targetApi="jelly_bean">@font/lato</item>
<item name="fontFamily">@font/lato</item>
Run Code Online (Sandbox Code Playgroud)
MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var textDrawable: TextDrawable
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
textDrawable = TextDrawable(this, "1")
setSupportActionBar(toolbar)
val handler = Handler()
val runnable = object : Runnable {
var i = 1
override fun run() {
if (isFinishing||isDestroyed)
return
textDrawable.text = (i + 1).toString()
i = (i + 1) % 31
handler.postDelayed(this, 1000)
}
}
runnable.run()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menu.add("goToToday").setIcon(textDrawable).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
menu.add("asd").setIcon(R.drawable.abc_ic_menu_copy_mtrl_am_alpha).setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)
return super.onCreateOptionsMenu(menu)
}
}
Run Code Online (Sandbox Code Playgroud)
TextDrawable.kt
class TextDrawable(context: Context, text: CharSequence) : Drawable() {
companion object {
private val DEFAULT_COLOR = Color.WHITE
private val DEFAULT_TEXT_SIZE = 12
}
var text: CharSequence = text
set (value) {
field = value
invalidateSelf()
}
private val mPaint: TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private val mDrawable: Drawable?
init {
mPaint.color = DEFAULT_COLOR
mPaint.textAlign = Align.CENTER
val textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TEXT_SIZE.toFloat(), context.resources.displayMetrics)
mPaint.textSize = textSize
mDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_backtodate)
mDrawable!!.setBounds(0, 0, mDrawable.intrinsicWidth, mDrawable.intrinsicHeight)
}
override fun draw(canvas: Canvas) {
val bounds = bounds
mDrawable!!.draw(canvas)
canvas.drawText(text, 0, text.length,
bounds.centerX().toFloat(), (bounds.centerY() + mPaint.getFontMetricsInt(null) / 3).toFloat(), mPaint) // this seems very wrong, but seems to work fine
}
override fun getOpacity(): Int = mPaint.alpha
override fun getIntrinsicWidth(): Int = mDrawable!!.intrinsicWidth
override fun getIntrinsicHeight(): Int = mDrawable!!.intrinsicHeight
override fun setAlpha(alpha: Int) {
mPaint.alpha = alpha
invalidateSelf()
}
override fun setColorFilter(filter: ColorFilter?) {
mPaint.colorFilter = filter
invalidateSelf()
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我想我已经找到了如何使用文字的字体,使用:
mPaint.typeface=TypefaceCompat.createFromResourcesFamilyXml(...)
Run Code Online (Sandbox Code Playgroud)
不确定如何填写参数.还在调查......
好的,找到有关如何为我制作的Drawable类的TextPaint使用相同字体的答案:
mPaint.typeface = ResourcesCompat.getFont(context, R.font.lato)
Run Code Online (Sandbox Code Playgroud)
结果:
这是该类的完整实现:
class TextDrawable(context: Context, text: CharSequence) : Drawable() {
companion object {
private val DEFAULT_COLOR = Color.WHITE
private val DEFAULT_TEXT_SIZE_IN_DP = 12
}
private val mTextBounds = Rect()
private val mPaint: TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG)
private val mDrawable: Drawable?
var text: CharSequence = text
set (value) {
field = value
invalidateSelf()
}
init {
mPaint.typeface = ResourcesCompat.getFont(context, R.font.lato)
mPaint.color = DEFAULT_COLOR
mPaint.textAlign = Align.CENTER
val textSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, DEFAULT_TEXT_SIZE_IN_DP.toFloat(), context.resources.displayMetrics)
mPaint.textSize = textSize
mDrawable = AppCompatResources.getDrawable(context, R.drawable.ic_backtodate)
mDrawable!!.setBounds(0, 0, mDrawable.intrinsicWidth, mDrawable.intrinsicHeight)
}
override fun draw(canvas: Canvas) {
val bounds = bounds
mDrawable!!.draw(canvas)
mPaint.getTextBounds(text.toString(), 0, text.length, mTextBounds);
val textHeight = mTextBounds.bottom - mTextBounds.top
canvas.drawText(text as String?, (bounds.right / 2).toFloat(), (bounds.bottom.toFloat() + textHeight + 1) / 2, mPaint)
}
override fun getOpacity(): Int = mPaint.alpha
override fun getIntrinsicWidth(): Int = mDrawable!!.intrinsicWidth
override fun getIntrinsicHeight(): Int = mDrawable!!.intrinsicHeight
override fun setAlpha(alpha: Int) {
mPaint.alpha = alpha
invalidateSelf()
}
override fun setColorFilter(filter: ColorFilter?) {
mPaint.colorFilter = filter
invalidateSelf()
}
}
Run Code Online (Sandbox Code Playgroud)
编辑:此代码现已完成,并且运行良好。它应该可以正常工作,并且部分基于Calendar应用程序本身,这是我建议查看的地方(此处和此处)。
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |