안드로이드에서 문자 사이의 간격을 조정하는 방법이 있습니까 TextView
? 나는 이것이 일반적으로 "커닝"이라고 생각합니다.Android TextView에서 텍스트 자간을 조정하는 방법은 무엇입니까?
나는 android:textScaleX
속성을 알고 있지만 간격과 함께 문자를 압축합니다.
안드로이드에서 문자 사이의 간격을 조정하는 방법이 있습니까 TextView
? 나는 이것이 일반적으로 "커닝"이라고 생각합니다.Android TextView에서 텍스트 자간을 조정하는 방법은 무엇입니까?
나는 android:textScaleX
속성을 알고 있지만 간격과 함께 문자를 압축합니다.
AFAIK에서는 커닝을 TextView
으로 조정할 수 없습니다. 2D 그래픽 API를 사용하여 Canvas
에 텍스트를 그릴 경우 커닝을 조정할 수 있습니다.
당신은 또한 SpannedString를 사용하여 시도 할 수 있지만 당신이 그것을 분석하고 단어
나는 커닝을 조정 발견하는 유일한 방법 각각에 대한 문자 간격을 변경해야합니다, 사용자 정의 글꼴을 생성하는 글리프의 진행이 변경됩니다.
TextView를 확장하고 "setSpacing"메서드를 추가하는 사용자 지정 클래스를 작성했습니다. 해결 방법은 @Noah가 말한 것과 유사합니다. 이 메서드는 문자열의 각 문자 사이에 공백을 추가하고 공백의 TextScaleX를 SpannedString으로 변경하여 양수 및 음수 간격을 허용합니다. 누군가가 사용
/**
* Text view that allows changing the letter spacing of the text.
*
* @author Pedro Barros (pedrobarros.dev at gmail.com)
* @since May 7, 2013
*/
import android.content.Context;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ScaleXSpan;
import android.util.AttributeSet;
import android.widget.TextView;
public class LetterSpacingTextView extends TextView {
private float spacing = Spacing.NORMAL;
private CharSequence originalText = "";
public LetterSpacingTextView(Context context) {
super(context);
}
public LetterSpacingTextView(Context context, AttributeSet attrs){
super(context, attrs);
}
public LetterSpacingTextView(Context context, AttributeSet attrs, int defStyle){
super(context, attrs, defStyle);
}
public float getSpacing() {
return this.spacing;
}
public void setSpacing(float spacing) {
this.spacing = spacing;
applySpacing();
}
@Override
public void setText(CharSequence text, BufferType type) {
originalText = text;
applySpacing();
}
@Override
public CharSequence getText() {
return originalText;
}
private void applySpacing() {
if (this == null || this.originalText == null) return;
StringBuilder builder = new StringBuilder();
for(int i = 0; i < originalText.length(); i++) {
builder.append(originalText.charAt(i));
if(i+1 < originalText.length()) {
builder.append("\u00A0");
}
}
SpannableString finalText = new SpannableString(builder.toString());
if(builder.toString().length() > 1) {
for(int i = 1; i < builder.toString().length(); i+=2) {
finalText.setSpan(new ScaleXSpan((spacing+1)/10), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
super.setText(finalText, BufferType.SPANNABLE);
}
public class Spacing {
public final static float NORMAL = 0;
}
}
를 ^^ 도움이
희망 :
LetterSpacingTextView textView = new LetterSpacingTextView(context);
textView.setSpacing(10); //Or any float. To reset to normal, use 0 or LetterSpacingTextView.Spacing.NORMAL
textView.setText("My text");
//Add the textView in a layout, for instance:
((LinearLayout) findViewById(R.id.myLinearLayout)).addView(textView);
대단하군요! 고마워요, 정말 도움이되었습니다 –
이 코드는 문자 간격을 줄이는 데는 잘 작동하지만 불행히도 나를 위해 텍스트 줄 바꿈을 해독합니다. –
no-break space builder.append ("\ u00A0")로 builder.append ("")를 바꾸면 문제가 해결되었습니다. 코드를 보내 주셔서 감사합니다! –
사람이를 사용하지 않고 (기술적, CharSequence
) 문자열에 커닝을 적용하는 간단한 방법을 찾고 있다면 TextView
: 이
public static Spannable applyKerning(CharSequence src, float kerning)
{
if (src == null) return null;
final int srcLength = src.length();
if (srcLength < 2) return src instanceof Spannable
? (Spannable)src
: new SpannableString(src);
final String nonBreakingSpace = "\u00A0";
final SpannableStringBuilder builder = src instanceof SpannableStringBuilder
? (SpannableStringBuilder)src
: new SpannableStringBuilder(src);
for (int i = src.length() - 1; i >= 1; i--)
{
builder.insert(i, nonBreakingSpace);
builder.setSpan(new ScaleXSpan(kerning), i, i + 1,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
여기 내 솔루션입니다 각 문자 사이에 균일 한 간격 (픽셀 단위)이 추가됩니다. 이 범위는 모든 텍스트가 단일 행에 있다고 가정합니다. 이것은 기본적으로 @commonsWare가 제안하는 것을 구현합니다.
SpannableStringBuilder builder = new SpannableStringBuilder("WIDE normal");
builder.setSpan(new TrackingSpan(20), 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
...
private static class TrackingSpan extends ReplacementSpan {
private float mTrackingPx;
public TrackingSpan(float tracking) {
mTrackingPx = tracking;
}
@Override
public int getSize(Paint paint, CharSequence text,
int start, int end, Paint.FontMetricsInt fm) {
return (int) (paint.measureText(text, start, end)
+ mTrackingPx * (end - start - 1));
}
@Override
public void draw(Canvas canvas, CharSequence text,
int start, int end, float x, int top, int y,
int bottom, Paint paint) {
float dx = x;
for (int i = start; i < end; i++) {
canvas.drawText(text, i, i + 1, dx, y, paint);
dx += paint.measureText(text, i, i + 1) + mTrackingPx;
}
}
}
@Pedro Barros 대답의 작은 편집이 있습니다. SpannableString을 사용하여 설정하면 유용합니다. 일부 문자의 다른 색상을 만들려면 :
private void applySpacing() {
SpannableString finalText;
if (!(originalText instanceof SpannableString)) {
if (this.originalText == null) return;
StringBuilder builder = new StringBuilder();
for (int i = 0; i < originalText.length(); i++) {
builder.append(originalText.charAt(i));
if (i + 1 < originalText.length()) {
builder.append("\u00A0");
}
}
finalText = new SpannableString(builder.toString());
} else {
finalText = (SpannableString) originalText;
}
for (int i = 1; i < finalText.length(); i += 2) {
finalText.setSpan(new ScaleXSpan((spacing + 1)/10), i, i + 1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
super.setText(finalText, TextView.BufferType.SPANNABLE);
}
@PedroBarros 대답을 사용하고 싶지만 간격을 픽셀로 정의해야합니다.
가 여기에 applySpacing 방법에 내 편집의 :
private void applySpacing() {
if (this == null || this.originalText == null) return;
Paint testPaint = new Paint();
testPaint.set(this.getPaint());
float spaceOriginalSize = testPaint.measureText("\u00A0");
float spaceScaleXFactor = (spaceOriginalSize > 0 ? spacing/spaceOriginalSize : 1);
StringBuilder builder = new StringBuilder();
for(int i = 0; i < originalText.length(); i++) {
builder.append(originalText.charAt(i));
if(i+1 < originalText.length()) {
builder.append("\u00A0");
}
}
SpannableString finalText = new SpannableString(builder.toString());
if(builder.toString().length() > 1) {
for(int i = 1; i < builder.toString().length(); i+=2) {
finalText.setSpan(new ScaleXSpan(spaceScaleXFactor), i, i+1, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
}
super.setText(finalText, BufferType.SPANNABLE);
}
나는 안드로이드 개발자로 초보자이야,이 좋은하지 않은 경우 알려 주시기 바랍니다!
이 답변은 drawText (텍스트 뷰의 텍스트가 아닙니다)를 사용하여 캔버스에 커닝하여 텍스트를 그리려는 사람에게 도움이 될 수 있습니다.
Lollipop 이후 setLetterSpacing 메서드는 Paint에서 사용할 수 있습니다. SDK가 LOLLIPOP 이상인 경우 setLetterSpacing이 사용됩니다. 그렇지 않으면 위의 @ dgmltn의 제안과 유사한 작업을 수행하는 메소드가 호출됩니다.
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
paint.setLetterSpacing(-0.04f); // setLetterSpacing is only available from LOLLIPOP and on
canvas.drawText(text, xOffset, yOffset, paint);
} else {
float spacePercentage = 0.05f;
drawKernedText(canvas, text, xOffset, yOffset, paint, spacePercentage);
}
/**
* Programatically drawn kerned text by drawing the text string character by character with a space in between.
* Return the width of the text.
* If canvas is null, the text won't be drawn, but the width will still be returned
* kernPercentage determines the space between each letter. If it's 0, there will be no space between letters.
* Otherwise, there will be space between each letter. The value is a fraction of the width of a blank space.
*/
private int drawKernedText(Canvas canvas, String text, float xOffset, float yOffset, Paint paint, float kernPercentage) {
Rect textRect = new Rect();
int width = 0;
int space = Math.round(paint.measureText(" ") * kernPercentage);
for (int i = 0; i < text.length(); i++) {
if (canvas != null) {
canvas.drawText(String.valueOf(text.charAt(i)), xOffset, yOffset, paint);
}
int charWidth;
if (text.charAt(i) == ' ') {
charWidth = Math.round(paint.measureText(String.valueOf(text.charAt(i)))) + space;
} else {
paint.getTextBounds(text, i, i + 1, textRect);
charWidth = textRect.width() + space;
}
xOffset += charWidth;
width += charWidth;
}
return width;
}
하나 더 솔루션.
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/transparent"/>
<size android:height="1dp" android:width="1dp"/>
</shape>
같은 간격 사용 코드를 설정하려면 : pixel_1dp은 XML입니다
public static SpannableStringBuilder getSpacedSpannable(Context context, String text, int dp) {
if (text == null) return null;
if (dp < 0) throw new RuntimeException("WRONG SPACING " + dp);
Canvas canvas = new Canvas();
Drawable drawable = ContextCompat.getDrawable(context, R.drawable.pixel_1dp);
Bitmap main = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
canvas.setBitmap(main);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
drawable.draw(canvas);
SpannableStringBuilder builder = new SpannableStringBuilder();
char[] array = text.toCharArray();
Bitmap bitmap = Bitmap.createScaledBitmap(main, dp * main.getWidth(), main.getHeight(), false);
for (char ch : array) {
builder.append(ch);
builder.append(" ");
ImageSpan imageSpan = new ImageSpan(context, bitmap);
builder.setSpan(imageSpan, builder.length() - 1, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return builder;
}
textView.setText(getSpacedSpannable(context, textView.getText().toString(), <Your spacing DP>), TextView.BufferType.SPANNABLE);
잘, 나는 그 그 같아요. 건배, 마이크 – emmby
안녕하세요, @ CommonSWare, 2D 그래픽 API를 사용하여 캔버스에 텍스트를 그릴 때 커닝을 조정하는 방법은 무엇입니까? 나에게 단서를 주시겠습니까? – neevek
사용 된 글꼴의 수정 된 버전을 제공하여 자간 조절을 구현할 수 있습니다. – mvds