自定义字体导致我的动态 ViewPager 的 OnMeasure 截断文本行
Custom font causing my dynamic ViewPager's OnMeasure to cut off lines of text
所以在某些情况下,我的自定义 TextView 会截断最后一行文本。我正在使用自定义字体。好像只截断了最后一个字。我将我的自定义文本视图更改为常规文本视图,这会强制我的文本视图使用标准字体而不是我的自定义字体,然后大小调整突然起作用了。
问题理论:在使用 DDMS 工具查看我的视图周围的布局大小并比较自定义字体版本与常规字体版本时,它似乎正确地测量了字符的高度——如果它没有它会切断我更大的自定义字体上的部分 y、g 和 p。但是它并没有正确地猜测我的大字体将占用的行数,并且测量行数就好像它是较小的非自定义字体一样。所以当一个字符串以一个刚好在换行边缘的两个字母单词结尾时,它认为它不需要换行到下一行并将其切断。
包含问题子 CustomTextView 的 ViewPager 内部布局:
<LinearLayout
android:id="@+id/header_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="-12dp"
android:paddingRight="-12dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
snip>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
snip>
<!---v--- this is the problem child--->
<com.snip.custom.views.CustomTextView
android:id="@+id/label"
style="@style/typographyParagraphBody"
android:layout_centerHorizontal="true"
android:gravity="center"
android:layout_marginBottom="20dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:text="@{carouselItemViewModel.label}"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
</LinearLayout>
无聊的 ViewPager:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
我的布局文件:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@{carouselViewModel.carouselBackgroundColor}"
android:orientation="vertical">
<com.snip.custom.views.CustomTextView
android:id="@+id/text"
style="@style/irrelevant"
android:text="@{carouselViewModel.text}"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-17dp"
android:layout_gravity="top"
android:layout_below="@id/text"
app:tabBackground="@drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:viewPager="@{{viewPager}}" />
<com.snip.custom.views.CustomViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingEnd="20dp"
android:paddingStart="20dp"
android:layout_below="@id/tab_layout"
app:currentItem="@{carouselViewModel.carouselCurrentItemSubject}"
app:setOffscreenPageLimit="@{carouselViewModel.carouselOffscreenPageLimitSubject}"
app:itemView="@{carouselViewModel.carouselItemViewSelector}"
app:items="@{carouselViewModel.carouselItems}"
app:onAdapterChangeListener="@{carouselViewModel.carouselAdapterChangeSubject}"
app:onPageChangeListener="@{carouselViewModel.carouselPageChangeSubject}"/>
</RelativeLayout>
看来我需要更多代码才能正确测量 children,因为他们不知道自己的布局参数。所以我通过应用 parent widthMeasureSpec.
重新测量它们
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
height = Math.max(child.getMeasuredHeight(), measureViewHeight(child, widthMeasureSpec));
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int measureViewHeight(View view, int widthMeasuredSpec) {
view.measure(getChildMeasureSpec(widthMeasuredSpec,
getPaddingLeft() + getPaddingRight(),
view.getLayoutParams().width),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
return view.getMeasuredHeight();
}
所以在某些情况下,我的自定义 TextView 会截断最后一行文本。我正在使用自定义字体。好像只截断了最后一个字。我将我的自定义文本视图更改为常规文本视图,这会强制我的文本视图使用标准字体而不是我的自定义字体,然后大小调整突然起作用了。
问题理论:在使用 DDMS 工具查看我的视图周围的布局大小并比较自定义字体版本与常规字体版本时,它似乎正确地测量了字符的高度——如果它没有它会切断我更大的自定义字体上的部分 y、g 和 p。但是它并没有正确地猜测我的大字体将占用的行数,并且测量行数就好像它是较小的非自定义字体一样。所以当一个字符串以一个刚好在换行边缘的两个字母单词结尾时,它认为它不需要换行到下一行并将其切断。
包含问题子 CustomTextView 的 ViewPager 内部布局:
<LinearLayout
android:id="@+id/header_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="-12dp"
android:paddingRight="-12dp"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.CardView
snip>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
snip>
<!---v--- this is the problem child--->
<com.snip.custom.views.CustomTextView
android:id="@+id/label"
style="@style/typographyParagraphBody"
android:layout_centerHorizontal="true"
android:gravity="center"
android:layout_marginBottom="20dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:text="@{carouselItemViewModel.label}"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
</RelativeLayout>
</LinearLayout>
无聊的 ViewPager:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
我的布局文件:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@{carouselViewModel.carouselBackgroundColor}"
android:orientation="vertical">
<com.snip.custom.views.CustomTextView
android:id="@+id/text"
style="@style/irrelevant"
android:text="@{carouselViewModel.text}"/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="-17dp"
android:layout_gravity="top"
android:layout_below="@id/text"
app:tabBackground="@drawable/dot_tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
app:tabPaddingEnd="5dp"
app:tabPaddingStart="5dp"
app:viewPager="@{{viewPager}}" />
<com.snip.custom.views.CustomViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clipToPadding="false"
android:paddingEnd="20dp"
android:paddingStart="20dp"
android:layout_below="@id/tab_layout"
app:currentItem="@{carouselViewModel.carouselCurrentItemSubject}"
app:setOffscreenPageLimit="@{carouselViewModel.carouselOffscreenPageLimitSubject}"
app:itemView="@{carouselViewModel.carouselItemViewSelector}"
app:items="@{carouselViewModel.carouselItems}"
app:onAdapterChangeListener="@{carouselViewModel.carouselAdapterChangeSubject}"
app:onPageChangeListener="@{carouselViewModel.carouselPageChangeSubject}"/>
</RelativeLayout>
看来我需要更多代码才能正确测量 children,因为他们不知道自己的布局参数。所以我通过应用 parent widthMeasureSpec.
重新测量它们@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height){
height = h;
}
height = Math.max(child.getMeasuredHeight(), measureViewHeight(child, widthMeasureSpec));
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
private int measureViewHeight(View view, int widthMeasuredSpec) {
view.measure(getChildMeasureSpec(widthMeasuredSpec,
getPaddingLeft() + getPaddingRight(),
view.getLayoutParams().width),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
return view.getMeasuredHeight();
}