99
1010import android .graphics .Paint ;
1111import android .text .style .LineHeightSpan ;
12+ import android .util .Log ;
1213
1314public class HeightSpan implements LineHeightSpan {
1415 private final int mHeight ;
1516
1617 public HeightSpan (float height ) {
1718 this .mHeight = (int ) Math .ceil (height );
1819 }
19-
20+ public int getHeight () {
21+ return mHeight ;
22+ }
2023 @ Override
2124 public void chooseHeight (
2225 CharSequence text , int start , int end , int spanstartv , int v , Paint .FontMetricsInt fm ) {
@@ -25,31 +28,55 @@ public void chooseHeight(
2528 // The general solution is that if there's not enough height to show the full line height, we
2629 // will prioritize in this order: descent, ascent, bottom, top
2730
28- if (fm .descent > mHeight ) {
29- // Show as much descent as possible
30- fm .bottom = fm .descent = Math .min (mHeight , fm .descent );
31- fm .top = fm .ascent = 0 ;
32- } else if (-fm .ascent + fm .descent > mHeight ) {
33- // Show all descent, and as much ascent as possible
34- fm .bottom = fm .descent ;
35- fm .top = fm .ascent = -mHeight + fm .descent ;
36- } else if (-fm .ascent + fm .bottom > mHeight ) {
37- // Show all ascent, descent, as much bottom as possible
38- fm .top = fm .ascent ;
39- fm .bottom = fm .ascent + mHeight ;
40- } else if (-fm .top + fm .bottom > mHeight ) {
41- // Show all ascent, descent, bottom, as much top as possible
42- fm .top = fm .bottom - mHeight ;
43- } else {
44- // Show proportionally additional ascent / top & descent / bottom
45- final int additional = mHeight - (-fm .top + fm .bottom );
31+ // if (fm.descent > mHeight) {
32+ // // Show as much descent as possible
33+ // fm.bottom = fm.descent = Math.min(mHeight, fm.descent);
34+ // fm.top = fm.ascent = 0;
35+ // } else if (-fm.ascent + fm.descent > mHeight) {
36+ // // Show all descent, and as much ascent as possible
37+ // fm.bottom = fm.descent;
38+ // fm.top = fm.ascent = -mHeight + fm.descent;
39+ // } else if (-fm.ascent + fm.bottom > mHeight) {
40+ // // Show all ascent, descent, as much bottom as possible
41+ // fm.top = fm.ascent;
42+ // fm.bottom = fm.ascent + mHeight;
43+ // } else if (-fm.top + fm.bottom > mHeight) {
44+ // // Show all ascent, descent, bottom, as much top as possible
45+ // fm.top = fm.bottom - mHeight;
46+ // } else {
47+ // // Show proportionally additional ascent / top & descent / bottom
48+ // final int additional = mHeight - (-fm.top + fm.bottom);
4649
47- // Round up for the negative values and down for the positive values (arbitrary choice)
48- // So that bottom - top equals additional even if it's an odd number.
49- fm .top -= Math .ceil (additional / 2.0f );
50- fm .bottom += Math .floor (additional / 2.0f );
51- fm .ascent = fm .top ;
52- fm .descent = fm .bottom ;
50+ // // Round up for the negative values and down for the positive values (arbitrary choice)
51+ // // So that bottom - top equals additional even if it's an odd number.
52+ // fm.top -= Math.ceil(additional / 2.0f);
53+ // fm.bottom += Math.floor(additional / 2.0f);
54+ // fm.ascent = fm.top;
55+ // fm.descent = fm.bottom;
56+ // }
57+ final int originHeight = fm .descent - fm .ascent ;
58+ // If original height is not positive, do nothing.
59+ if (originHeight <= 0 ) {
60+ return ;
61+ }
62+ final int diff = mHeight - originHeight ;
63+ if (diff == 0 ) {
64+ return ;
65+ }
66+
67+ if (diff > 0 ) {
68+ // Expand line: keep glyphs at the top, add extra space below.
69+ fm .bottom += diff ;
70+ fm .descent += diff ;
71+ } else {
72+ // Shrink line: remove space proportionally from top and bottom (center content).
73+ int reduce = -diff ;
74+ int reduceTop = (int ) Math .ceil (reduce / 2.0f );
75+ int reduceBottom = reduce - reduceTop ;
76+ fm .top += reduceTop ;
77+ fm .ascent += reduceTop ;
78+ fm .bottom -= reduceBottom ;
79+ fm .descent -= reduceBottom ;
5380 }
5481 }
55- }
82+ }
0 commit comments