반응형
TypefaceSpan 또는 StyleSpan을 사용자 지정 서체와 함께 사용하려면 어떻게해야합니까?
나는 이것을 할 방법을 찾지 못했습니다. 가능합니까?
글쎄, 나는 사용 가능한 클래스로 그것을 수행하는 방법을 알아낼 수 없었기 때문에 TypefaceSpan
이제는 나를 위해 작동합니다. 내가 한 일은 다음과 같습니다.
package de.myproject.text.style;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.text.TextPaint;
import android.text.style.TypefaceSpan;
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
public CustomTypefaceSpan(String family, Typeface type) {
super(family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
notme은 본질적으로 올바른 아이디어를 가지고 있지만 "가족"이 중복됨에 따라 주어진 솔루션은 약간 엉망입니다. TypefaceSpan은 Android가 ParcelableSpan 인터페이스와 관련하여 특정 동작에 대해 알고 있고 예상하는 특수 범위 중 하나이기 때문에 약간 부정확합니다 (Notme의 하위 클래스가 제대로 구현할 수 없거나 구현할 수 없음).
더 간단하고 정확한 솔루션은 다음과 같습니다.
public class CustomTypefaceSpan extends MetricAffectingSpan
{
private final Typeface typeface;
public CustomTypefaceSpan(final Typeface typeface)
{
this.typeface = typeface;
}
@Override
public void updateDrawState(final TextPaint drawState)
{
apply(drawState);
}
@Override
public void updateMeasureState(final TextPaint paint)
{
apply(paint);
}
private void apply(final Paint paint)
{
final Typeface oldTypeface = paint.getTypeface();
final int oldStyle = oldTypeface != null ? oldTypeface.getStyle() : 0;
final int fakeStyle = oldStyle & ~typeface.getStyle();
if ((fakeStyle & Typeface.BOLD) != 0)
{
paint.setFakeBoldText(true);
}
if ((fakeStyle & Typeface.ITALIC) != 0)
{
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(typeface);
}
}
Android P에서는 여기에 표시된대로 알고있는 동일한 TypefaceSpan 클래스를 사용할 수 있습니다 .
그러나 이전 버전에서는 비디오의 뒷부분에 표시된 내용을 사용할 수 있습니다 .
누구든지 관심이 있다면 Benjamin 코드의 C # Xamarin 버전이 있습니다.
using System;
using Android.Graphics;
using Android.Text;
using Android.Text.Style;
namespace Utils
{
//https://stackoverflow.com/a/17961854/1996780
/// <summary>A text span which applies <see cref="Android.Graphics.Typeface"/> on text</summary>
internal class CustomFontSpan : MetricAffectingSpan
{
/// <summary>The typeface to apply</summary>
public Typeface Typeface { get; }
/// <summary>CTor - creates a new instance of the <see cref="CustomFontSpan"/> class</summary>
/// <param name="typeface">Typeface to apply</param>
/// <exception cref="ArgumentNullException"><paramref name="typeface"/> is null</exception>
public CustomFontSpan(Typeface typeface) =>
Typeface = typeface ?? throw new ArgumentNullException(nameof(typeface));
public override void UpdateDrawState(TextPaint drawState) => Apply(drawState);
public override void UpdateMeasureState(TextPaint paint) => Apply(paint);
/// <summary>Applies <see cref="Typeface"/></summary>
/// <param name="paint"><see cref="Paint"/> to apply <see cref="Typeface"/> on</param>
private void Apply(Paint paint)
{
Typeface oldTypeface = paint.Typeface;
var oldStyle = oldTypeface != null ? oldTypeface.Style : 0;
var fakeStyle = oldStyle & Typeface.Style;
if (fakeStyle.HasFlag(TypefaceStyle.Bold))
paint.FakeBoldText = true;
if (fakeStyle.HasFlag(TypefaceStyle.Italic))
paint.TextSkewX = -0.25f;
paint.SetTypeface(Typeface);
}
}
}
및 사용법 : (OnCreate 활동에서)
var txwLogo = FindViewById<TextView>(Resource.Id.logo);
var font = Resources.GetFont(Resource.Font.myFont);
var wordtoSpan = new SpannableString(txwLogo.Text);
wordtoSpan.SetSpan(new CustomFontSpan(font), 6, 7, SpanTypes.InclusiveInclusive); //One caracter
txwLogo.TextFormatted = wordtoSpan;
몇 가지 유사한 솔루션을 시도한 결과 이것이 간단하고 실행 가능 하다는 것을 알았습니다 . 항목 클릭은 onOptionsItemSelected 대신 버튼 클릭으로 처리됩니다. 감사!
내 프로젝트의 코드는 다음과 같습니다.
내 menu_main.xml에서 :
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".MainActivity">
<item
android:id="@+id/action_friends"
android:orderInCategory="100"
android:title="@string/hello_world"
app:actionViewClass="android.widget.Button"
app:showAsAction="always" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never" />
</menu>
내 MainActivity.java에서 :
@Override
public boolean onCreateOptionsMenu(Menu menu) {
//Use custom menu
MenuInflater inflater = getMenuInflater();
//Inflate the custom menu
inflater.inflate(R.menu.menu_main, menu);
//reference to the item of the menu
MenuItem i=menu.findItem(R.id.action_friends);
Button itemuser =(Button) i.getActionView();
if(itemuser!=null){
// Create Typeface object to use unicode font in assets folder
Typeface a = Typeface.createFromAsset(getApplicationContext(), "fontawesome-webfont.ttf");
// Set unicode font to menu item
itemuser.setTypeface(a);
itemuser.setText(getString(R.string.fa_users));
// Set item text and color
itemuser.setTextColor(Color.BLACK);
// Make item background transparent
itemuser.setBackgroundColor(Color.TRANSPARENT);
itemuser.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v) {
//set action when clicked
}
});
}
return super.onCreateOptionsMenu(menu);
}
반응형
'code' 카테고리의 다른 글
자바 스크립트가 \ n (0) | 2020.10.25 |
---|---|
Info.plist 유틸리티 오류 : "해당 파일이 없기 때문에 Info.plist를 열 수 없습니다." (0) | 2020.10.25 |
Rails에서 정적 콘텐츠를 수행하는 방법은 무엇입니까? (0) | 2020.10.25 |
Django Rest Framework-인증 자격 증명이 제공되지 않았습니다. (0) | 2020.10.25 |
종횡비를 계산하는 알고리즘은 무엇입니까? (0) | 2020.10.25 |