Android HorizontalScrollView с правильным layout_gravity работает неправильно
Я пытаюсь получить следующий вид: Описание на левом сайте и значение справа. например:.
![enter image description here]()
Проблема заключается в том, что текст может быть длинным, поэтому я переношу его в HorizontalScrollView. Я использую следующий xml:
<LinearLayout
android:layout_width="fill_parent"
android:layout_weight="1"
android:orientation="horizontal"
android:layout_height="wrap_content">
<TextView
android:layout_height="wrap_content"
android:textColor="#000000"
android:layout_width="110dp"
android:text="Description:"/>
<HorizontalScrollView
android:layout_weight="1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_height="wrap_content"
android:textColor="#000000"
android:layout_width="wrap_content"
android:layout_gravity="right"
android:text="Very1 very2 very3 very4 very5 very6 long text"/>
</HorizontalScrollView>
</LinearLayout>
И вот проблема. После прокрутки к самому большому углу я получил представление (отсутствующее начало текста):
![enter image description here]()
После прокрутки к самому большому углу я получил представление (добавочное пространство после текста):
![enter image description here]()
Если я изменю AndroidView android: layout_gravity на "left", все будет работать так, как ожидалось. После прокрутки влево в углу я получил представление:
![enter image description here]()
После прокрутки к самому большому углу я получил представление:
![enter image description here]()
Является ли это способом заставить его работать правильно и выровнять текст по правому сайту, когда он короток?
Ответы
Ответ 1
Я знаю, что это было какое-то время, но вот обходной путь (проверенный):
public class RightAlignedHorizontalScrollView extends HorizontalScrollView {
private boolean mGravityRight = false;
private boolean mAutoScrolling = false;
public RightAlignedHorizontalScrollView(Context context) {
super(context);
}
public RightAlignedHorizontalScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RightAlignedHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public View getChildView() {
return getChildAt(0);
}
private int getScrollRange() {
int scrollRange = 0;
if (getChildCount() > 0) {
View child = getChildAt(0);
scrollRange = Math.max(0, child.getWidth() - (getWidth() - getPaddingLeft() - getPaddingRight()));
}
return scrollRange;
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// HorizontalScrollView is broken for Gravity.RIGHT. So we're fixing it.
mAutoScrolling = false;
int childWidth = getChildView().getWidth();
super.onLayout(changed, left, top, right, bottom);
int delta = getChildView().getWidth() - childWidth;
View childView = getChildView();
FrameLayout.LayoutParams p = (LayoutParams) childView.getLayoutParams();
int horizontalGravity = p.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
int verticalGravity = p.gravity & Gravity.VERTICAL_GRAVITY_MASK;
if (horizontalGravity == Gravity.RIGHT) {
if (getScrollRange() > 0) {
mGravityRight = true;
p.gravity = Gravity.LEFT | verticalGravity;
childView.setLayoutParams(p);
super.onLayout(changed, left, top, right, bottom);
}
} else if (mGravityRight) {
if (getScrollRange() == 0) {
mGravityRight = false;
p.gravity = Gravity.RIGHT | verticalGravity;
childView.setLayoutParams(p);
super.onLayout(changed, left, top, right, bottom);
}
}
if (mGravityRight && delta > 0) {
scrollBy(delta, 0);
mAutoScrolling = true;
}
}
@Override
public void computeScroll() {
if (mAutoScrolling) return;
super.computeScroll();
}
@Override
public void scrollTo(int x, int y) {
if (mAutoScrolling) return;
super.scrollTo(x, y);
}
}
Ответ 2
Не используйте гравитацию для TextView, она будет работать, как вы ожидали.
Как вы сказали, проблема в том, что она ведет себя неправильно с правильной гравитацией.
Ответ 3
Я знаю, что это неактивно в течение года, но это все еще проблема в 2013 году. Создайте новый класс, который расширяет HorizontalScrollView и скопируйте/вставьте код ниже.
@Override
public boolean onTouchEvent(MotionEvent ev) {
autoScrolling = false;
return super.onTouchEvent(ev);
}
private int getScrollRange() {
int scrollRange = 0;
if(getChildCount() > 0) {
View child = getChildAt(0);
scrollRange = Math.max(0, child.getWidth() - (getWidth() - getPaddingLeft() - getPaddingRight()));
}
return scrollRange;
}
private boolean gravityRight = false;
private boolean autoScrolling = false;
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// HorizontalScrollView is broken for Gravity.RIGHT. So we're fixing it.
if(getChildCount() == 0) return super.onLayout(changed, left, top, right, bottom);
int childWidth = getChildAt(0).getWidth();
super.onLayout(changed, left, top, right, bottom);
int delta = getChildAt(0).getWidth() - childWidth;
AdvancedDisplay view = getView();
ScrollableDisplay.LayoutParams p = (LayoutParams) view.getLayoutParams();
int horizontalGravity = p.gravity & Gravity.HORIZONTAL_GRAVITY_MASK;
int verticalGravity = p.gravity & Gravity.VERTICAL_GRAVITY_MASK;
if(horizontalGravity == Gravity.RIGHT) {
if(getScrollRange() > 0) {
gravityRight = true;
p.gravity = Gravity.LEFT | verticalGravity;
view.setLayoutParams(p);
super.onLayout(changed, left, top, right, bottom);
}
}
else if(gravityRight) {
if(getScrollRange() == 0) {
gravityRight = false;
p.gravity = Gravity.RIGHT | verticalGravity;
view.setLayoutParams(p);
super.onLayout(changed, left, top, right, bottom);
}
}
if(gravityRight && delta > 0) {
autoScrolling = false;
scrollBy(delta, 0);
autoScrolling = true;
}
}
@Override
public void computeScroll() {
if(autoScrolling) return;
super.computeScroll();
}
@Override
public void scrollTo(int x, int y) {
if(autoScrolling) return;
super.scrollTo(x, y);
}