├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── encodings.xml ├── gradle.xml ├── markdown-exported-files.xml ├── markdown-navigator.xml ├── markdown-navigator │ └── profiles_settings.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── LICENSE ├── README.md ├── Xi2UG.png ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── net │ │ └── studymongolian │ │ └── fontmetrics │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── net │ │ │ └── studymongolian │ │ │ └── fontmetrics │ │ │ ├── FontMetricsView.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-w820dp │ │ └── dimens.xml │ │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── net │ └── studymongolian │ └── fontmetrics │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/markdown-exported-files.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/markdown-navigator.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 16 | 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | 35 | 36 | 37 | 1.8 38 | 39 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 suragch 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Android FontMetrics 2 | An Android app for measuring and testing FontMetrics 3 | 4 | ![App preview](/Xi2UG.png?raw=true) 5 | 6 | This app was originally created and used for these Stack Overflow questions: 7 | 8 | - http://stackoverflow.com/questions/27631736/meaning-of-top-ascent-baseline-descent-bottom-and-leading-in-androids-font 9 | - http://stackoverflow.com/a/42091739/ 10 | 11 | I decided to put the project on GitHub to make it easier to experiment with, and also so that other people will improve it. 12 | 13 | ## TODO 14 | 15 | If you want to help, here are some improvements that are needed: 16 | - Color code the checkbox items and the lines in the custom view 17 | - Keyboard popping up when first entering app isn't necessary 18 | - Add a few custom (free) fonts and add an option to select different fonts. 19 | -------------------------------------------------------------------------------- /Xi2UG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/suragch/AndroidFontMetrics/94aa4362f684c5c0d7486010981c1b484bf3da70/Xi2UG.png -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.2" 6 | defaultConfig { 7 | applicationId "net.studymongolian.fontmetrics" 8 | minSdkVersion 9 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(dir: 'libs', include: ['*.jar']) 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.1.1' 28 | testCompile 'junit:junit:4.12' 29 | } 30 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/yonghu/Android/Sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/androidTest/java/net/studymongolian/fontmetrics/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package net.studymongolian.fontmetrics; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("net.studymongolian.fontmetrics", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/net/studymongolian/fontmetrics/FontMetricsView.java: -------------------------------------------------------------------------------- 1 | package net.studymongolian.fontmetrics; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.text.TextPaint; 9 | import android.util.AttributeSet; 10 | import android.view.View; 11 | import android.widget.Toast; 12 | 13 | 14 | public class FontMetricsView extends View { 15 | 16 | public final static int DEFAULT_FONT_SIZE_PX = 200; 17 | //private static final int PURPLE = Color.parseColor("#9315db"); 18 | //private static final int ORANGE = Color.parseColor("#ff8a00"); 19 | private static final float STROKE_WIDTH = 5.0f; 20 | 21 | private String mText; 22 | private int mTextSize; 23 | private Paint mAscentPaint; 24 | private Paint mTopPaint; 25 | private Paint mBaselinePaint; 26 | private Paint mDescentPaint; 27 | private Paint mBottomPaint; 28 | private Paint mMeasuredWidthPaint; 29 | private Paint mTextBoundsPaint; 30 | private TextPaint mTextPaint; 31 | private Paint mLinePaint; 32 | private Paint mRectPaint; 33 | private Rect mBounds; 34 | private boolean mIsTopVisible; 35 | private boolean mIsAscentVisible; 36 | private boolean mIsBaselineVisible; 37 | private boolean mIsDescentVisible; 38 | private boolean mIsBottomVisible; 39 | private boolean mIsBoundsVisible; 40 | private boolean mIsWidthVisible; 41 | 42 | 43 | public FontMetricsView(Context context) { 44 | super(context); 45 | init(); 46 | } 47 | 48 | 49 | public FontMetricsView(Context context, AttributeSet attrs) { 50 | super(context, attrs); 51 | init(); 52 | } 53 | 54 | private void init() { 55 | mText = "My text line"; 56 | mTextSize = DEFAULT_FONT_SIZE_PX; 57 | mTextPaint = new TextPaint(); 58 | mTextPaint.setAntiAlias(true); 59 | mTextPaint.setTextSize(mTextSize); 60 | mTextPaint.setColor(Color.BLACK); 61 | 62 | mLinePaint = new Paint(); 63 | mLinePaint.setColor(Color.RED); 64 | mLinePaint.setStrokeWidth(STROKE_WIDTH); 65 | 66 | mAscentPaint = new Paint(); 67 | mAscentPaint.setColor(getResources().getColor(R.color.ascent)); 68 | mAscentPaint.setStrokeWidth(STROKE_WIDTH); 69 | 70 | mTopPaint = new Paint(); 71 | mTopPaint.setColor(getResources().getColor(R.color.top)); 72 | mTopPaint.setStrokeWidth(STROKE_WIDTH); 73 | 74 | mBaselinePaint = new Paint(); 75 | mBaselinePaint.setColor(getResources().getColor(R.color.baseline)); 76 | mBaselinePaint.setStrokeWidth(STROKE_WIDTH); 77 | 78 | mBottomPaint = new Paint(); 79 | mBottomPaint.setColor(getResources().getColor(R.color.bottom)); 80 | mBottomPaint.setStrokeWidth(STROKE_WIDTH); 81 | 82 | mDescentPaint = new Paint(); 83 | mDescentPaint.setColor(getResources().getColor(R.color.descent)); 84 | mDescentPaint.setStrokeWidth(STROKE_WIDTH); 85 | 86 | mMeasuredWidthPaint = new Paint(); 87 | mMeasuredWidthPaint.setColor(getResources().getColor(R.color.measured_width)); 88 | mMeasuredWidthPaint.setStrokeWidth(STROKE_WIDTH); 89 | 90 | mTextBoundsPaint = new Paint(); 91 | mTextBoundsPaint.setColor(getResources().getColor(R.color.text_bounds)); 92 | mTextBoundsPaint.setStrokeWidth(STROKE_WIDTH); 93 | mTextBoundsPaint.setStyle(Paint.Style.STROKE); 94 | 95 | mRectPaint = new Paint(); 96 | mRectPaint.setColor(Color.BLACK); 97 | mRectPaint.setStrokeWidth(STROKE_WIDTH); 98 | mRectPaint.setStyle(Paint.Style.STROKE); 99 | 100 | 101 | mBounds = new Rect(); 102 | 103 | mIsTopVisible = true; 104 | mIsAscentVisible = true; 105 | mIsBaselineVisible = true; 106 | mIsDescentVisible = true; 107 | mIsBottomVisible = true; 108 | mIsBoundsVisible = true; 109 | mIsWidthVisible = true; 110 | } 111 | 112 | @Override 113 | protected void onDraw(Canvas canvas) { 114 | super.onDraw(canvas); 115 | 116 | // center the text baseline vertically 117 | int verticalAdjustment = this.getHeight() / 2; 118 | canvas.translate(0, verticalAdjustment); 119 | 120 | float startX = getPaddingLeft(); 121 | float startY = 0; 122 | float stopX = this.getMeasuredWidth(); 123 | float stopY = 0; 124 | 125 | // draw text 126 | canvas.drawText(mText, startX, startY, mTextPaint); // x=0, y=0 127 | 128 | // draw lines 129 | startX = 0; 130 | 131 | if (mIsTopVisible) { 132 | startY = mTextPaint.getFontMetrics().top; 133 | stopY = startY; 134 | canvas.drawLine(startX, startY, stopX, stopY, mTopPaint); 135 | } 136 | 137 | if (mIsAscentVisible) { 138 | startY = mTextPaint.getFontMetrics().ascent; 139 | stopY = startY; 140 | //mLinePaint.setColor(Color.GREEN); 141 | canvas.drawLine(startX, startY, stopX, stopY, mAscentPaint); 142 | } 143 | 144 | if (mIsBaselineVisible) { 145 | startY = 0; 146 | stopY = startY; 147 | canvas.drawLine(startX, startY, stopX, stopY, mBaselinePaint); 148 | } 149 | 150 | if (mIsDescentVisible) { 151 | startY = mTextPaint.getFontMetrics().descent; 152 | stopY = startY; 153 | //mLinePaint.setColor(Color.BLUE); 154 | canvas.drawLine(startX, startY, stopX, stopY, mDescentPaint); 155 | } 156 | 157 | if (mIsBottomVisible) { 158 | startY = mTextPaint.getFontMetrics().bottom; 159 | stopY = startY; 160 | // mLinePaint.setColor(ORANGE); 161 | mLinePaint.setColor(Color.RED); 162 | canvas.drawLine(startX, startY, stopX, stopY, mBaselinePaint); 163 | } 164 | 165 | if (mIsBoundsVisible) { 166 | 167 | mTextPaint.getTextBounds(mText, 0, mText.length(), mBounds); 168 | float dx = getPaddingLeft(); 169 | canvas.drawRect(mBounds.left + dx, mBounds.top, mBounds.right + dx, mBounds.bottom, mTextBoundsPaint); 170 | } 171 | 172 | if (mIsWidthVisible) { 173 | 174 | 175 | // get measured width 176 | float width = mTextPaint.measureText(mText); 177 | 178 | // get bounding width so that we can compare them 179 | mTextPaint.getTextBounds(mText, 0, mText.length(), mBounds); 180 | 181 | // draw vertical line just before the left bounds 182 | startX = getPaddingLeft() + mBounds.left - (width - mBounds.width()) / 2; 183 | stopX = startX; 184 | startY = -verticalAdjustment; 185 | stopY = startY + this.getHeight(); 186 | canvas.drawLine(startX, startY, stopX, stopY, mMeasuredWidthPaint); 187 | 188 | // draw vertical line just after the right bounds 189 | startX = startX + width; 190 | stopX = startX; 191 | canvas.drawLine(startX, startY, stopX, stopY, mMeasuredWidthPaint); 192 | } 193 | } 194 | 195 | @Override 196 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 197 | 198 | int width = 200; 199 | int height = 200; 200 | 201 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 202 | int widthRequirement = MeasureSpec.getSize(widthMeasureSpec); 203 | if (widthMode == MeasureSpec.EXACTLY) { 204 | width = widthRequirement; 205 | } else if (widthMode == MeasureSpec.AT_MOST && width > widthRequirement) { 206 | width = widthRequirement; 207 | } 208 | 209 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 210 | int heightRequirement = MeasureSpec.getSize(heightMeasureSpec); 211 | if (heightMode == MeasureSpec.EXACTLY) { 212 | height = heightRequirement; 213 | } else if (heightMode == MeasureSpec.AT_MOST && width > heightRequirement) { 214 | height = heightRequirement; 215 | } 216 | 217 | setMeasuredDimension(width, height); 218 | } 219 | 220 | // getters 221 | public Paint.FontMetrics getFontMetrics() { 222 | return mTextPaint.getFontMetrics(); 223 | } 224 | 225 | public Rect getTextBounds() { 226 | mTextPaint.getTextBounds(mText, 0, mText.length(), mBounds); 227 | return mBounds; 228 | } 229 | 230 | public float getMeasuredTextWidth() { 231 | return mTextPaint.measureText(mText); 232 | } 233 | 234 | // setters 235 | public void setText(String text) { 236 | mText = text; 237 | invalidate(); 238 | requestLayout(); 239 | } 240 | 241 | public void setTextSizeInPixels(int pixels) { 242 | mTextSize = pixels; 243 | mTextPaint.setTextSize(mTextSize); 244 | invalidate(); 245 | requestLayout(); 246 | } 247 | 248 | public void setTopVisible(boolean isVisible) { 249 | mIsTopVisible = isVisible; 250 | invalidate(); 251 | } 252 | 253 | public void setAscentVisible(boolean isVisible) { 254 | mIsAscentVisible = isVisible; 255 | invalidate(); 256 | } 257 | 258 | public void setBaselineVisible(boolean isVisible) { 259 | mIsBaselineVisible = isVisible; 260 | invalidate(); 261 | } 262 | 263 | public void setDescentVisible(boolean isVisible) { 264 | mIsDescentVisible = isVisible; 265 | invalidate(); 266 | } 267 | 268 | public void setBottomVisible(boolean isVisible) { 269 | mIsBottomVisible = isVisible; 270 | invalidate(); 271 | } 272 | 273 | public void setBoundsVisible(boolean isVisible) { 274 | mIsBoundsVisible = isVisible; 275 | invalidate(); 276 | } 277 | 278 | public void setWidthVisible(boolean isVisible) { 279 | mIsWidthVisible = isVisible; 280 | invalidate(); 281 | } 282 | 283 | } 284 | -------------------------------------------------------------------------------- /app/src/main/java/net/studymongolian/fontmetrics/MainActivity.java: -------------------------------------------------------------------------------- 1 | package net.studymongolian.fontmetrics; 2 | 3 | import android.content.Context; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.view.inputmethod.InputMethodManager; 8 | import android.widget.CheckBox; 9 | import android.widget.EditText; 10 | import android.widget.TextView; 11 | 12 | public class MainActivity extends AppCompatActivity implements View.OnClickListener{ 13 | 14 | FontMetricsView myFontMetricsView; // custom view 15 | EditText mTextStringEditText; 16 | EditText mFontSizeEditText; 17 | CheckBox cbTop; 18 | CheckBox cbAscent; 19 | CheckBox cbBaseline; 20 | CheckBox cbDescent; 21 | CheckBox cbBottom; 22 | CheckBox cbBounds; 23 | CheckBox cbMeasuredWidth; 24 | 25 | TextView tvTop; 26 | TextView tvAscent; 27 | TextView tvBaseline; 28 | TextView tvDescent; 29 | TextView tvBottom; 30 | TextView tvBounds; 31 | TextView tvMeasuredWidth; 32 | TextView tvLeading; 33 | 34 | 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_main); 39 | 40 | myFontMetricsView = (FontMetricsView) findViewById(R.id.viewWindow); 41 | mTextStringEditText = (EditText) findViewById(R.id.etTextString); 42 | mFontSizeEditText = (EditText) findViewById(R.id.etFontSize); 43 | 44 | mTextStringEditText.setText("My text line"); 45 | mFontSizeEditText.setText("200"); 46 | 47 | 48 | findViewById(R.id.updateButton).setOnClickListener(this); 49 | cbTop = (CheckBox) findViewById(R.id.cbTop); 50 | cbAscent = (CheckBox) findViewById(R.id.cbAscent); 51 | cbBaseline = (CheckBox) findViewById(R.id.cbBaseline); 52 | cbDescent = (CheckBox) findViewById(R.id.cbDescent); 53 | cbBottom = (CheckBox) findViewById(R.id.cbBottom); 54 | cbBounds = (CheckBox) findViewById(R.id.cbTextBounds); 55 | cbMeasuredWidth = (CheckBox) findViewById(R.id.cbWidth); 56 | 57 | cbTop.setOnClickListener(this); 58 | cbAscent.setOnClickListener(this); 59 | cbBaseline.setOnClickListener(this); 60 | cbDescent.setOnClickListener(this); 61 | cbBottom.setOnClickListener(this); 62 | cbBounds.setOnClickListener(this); 63 | cbMeasuredWidth.setOnClickListener(this); 64 | 65 | tvTop = (TextView) findViewById(R.id.tvTop); 66 | tvAscent = (TextView) findViewById(R.id.tvAscent); 67 | tvBaseline = (TextView) findViewById(R.id.tvBaseline); 68 | tvDescent = (TextView) findViewById(R.id.tvDescent); 69 | tvBottom = (TextView) findViewById(R.id.tvBottom); 70 | tvBounds = (TextView) findViewById(R.id.tvTextBounds); 71 | tvMeasuredWidth = (TextView) findViewById(R.id.tvWidth); 72 | tvLeading = (TextView) findViewById(R.id.tvLeadingValue); 73 | updateTextViews(); 74 | 75 | } 76 | 77 | 78 | 79 | @Override 80 | public void onClick(View v) { 81 | 82 | switch (v.getId()) { 83 | case R.id.updateButton: 84 | myFontMetricsView.setText(mTextStringEditText.getText().toString()); 85 | int fontSize; 86 | try { 87 | fontSize = Integer.valueOf(mFontSizeEditText.getText().toString()); 88 | }catch (NumberFormatException e) { 89 | fontSize = FontMetricsView.DEFAULT_FONT_SIZE_PX; 90 | } 91 | myFontMetricsView.setTextSizeInPixels(fontSize); 92 | updateTextViews(); 93 | hideKeyboard(getCurrentFocus()); 94 | break; 95 | case R.id.cbTop: 96 | myFontMetricsView.setTopVisible(cbTop.isChecked()); 97 | break; 98 | case R.id.cbAscent: 99 | myFontMetricsView.setAscentVisible(cbAscent.isChecked()); 100 | break; 101 | case R.id.cbBaseline: 102 | myFontMetricsView.setBaselineVisible(cbBaseline.isChecked()); 103 | break; 104 | case R.id.cbDescent: 105 | myFontMetricsView.setDescentVisible(cbDescent.isChecked()); 106 | break; 107 | case R.id.cbBottom: 108 | myFontMetricsView.setBottomVisible(cbBottom.isChecked()); 109 | break; 110 | case R.id.cbTextBounds: 111 | myFontMetricsView.setBoundsVisible(cbBounds.isChecked()); 112 | break; 113 | case R.id.cbWidth: 114 | myFontMetricsView.setWidthVisible(cbMeasuredWidth.isChecked()); 115 | break; 116 | } 117 | 118 | 119 | } 120 | 121 | public void updateTextViews() { 122 | tvTop.setText(String.valueOf(myFontMetricsView.getFontMetrics().top)); 123 | tvAscent.setText(String.valueOf(myFontMetricsView.getFontMetrics().ascent)); 124 | tvBaseline.setText(String.valueOf(0f)); 125 | tvDescent.setText(String.valueOf(myFontMetricsView.getFontMetrics().descent)); 126 | tvBottom.setText(String.valueOf(myFontMetricsView.getFontMetrics().bottom)); 127 | tvBounds.setText("w = " + String.valueOf(myFontMetricsView.getTextBounds().width() + 128 | " h = " + String.valueOf(myFontMetricsView.getTextBounds().height()))); 129 | tvMeasuredWidth.setText(String.valueOf(myFontMetricsView.getMeasuredTextWidth())); 130 | tvLeading.setText(String.valueOf(myFontMetricsView.getFontMetrics().leading)); 131 | } 132 | 133 | private void hideKeyboard(View view) { 134 | if (view != null) { 135 | InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); 136 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 21 | 22 | 26 | 27 | 30 | 31 | 36 | 37 | 44 | 45 |