2D滚动,支持RTL布局

2D Scrolling, supporting RTL layout

最近,我们开始添加对阿拉伯语的支持——这需要 RTL 布局。我们的一个屏幕使用了 2D 滚动条,我在这里找到了它:

https://github.com/mukulraw/rekhta/blob/master/app/src/main/java/com/example/mukul/rekhta/TwoDScrollView.java

但是,当我们切换到 RTL 时,有两个问题:

我已经尝试查看 Horizo​​ntal scrollview 的源代码 - 它可以正确处理 rtl。到目前为止,我只在代码中看到两个对 rtl 的引用:在 onLayout() 期间。但是,当我尝试类似的操作时,我的 child 视图就消失了。

到目前为止,我找不到其他同时支持 2d 滚动和 rtl 的解决方案。所以,我希望在这里为我和未来需要类似东西的灵魂解决它。

好的,所以将一大堆不同的解决方案放在一起:

  1. 创建两个自定义组件,一个扩展 ScrollView,另一个扩展 Horizo​​ntal ScrollView:

    public class VScroll extends ScrollView {
    
     public VScroll(Context context, AttributeSet attrs, int defStyle) {
       super(context, attrs, defStyle);
     } 
    
     public VScroll(Context context, AttributeSet attrs) {
      super(context, attrs);
     }
    
     public VScroll(Context context) {
       super(context);
     }
    
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
       return false;
     } 
    }
    

    public class HScroll extends HorizontalScrollView {
    
     public HScroll(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
     }
    
     public HScroll(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
    
     public HScroll(Context context) {
         super(context);
     }
    
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
         return false;
     }
    }
    
  2. 在需要“2d 滚动条”的 activity 中,使用以下命令: 在 OnCreate() 中:

        vScroll = findViewById(R.id.vScroll);
        hScroll = findViewById(R.id.hScroll);
    

然后

private VelocityTracker mVelocityTracker;
private float mx, my;
private float curX, curY;
private boolean started;

@Override
public boolean onTouchEvent(MotionEvent event) {

  if (mVelocityTracker == null) {
     mVelocityTracker = VelocityTracker.obtain();
  }
  mVelocityTracker.addMovement(event);

  curX = event.getX();
  curY = event.getY();
  int dx = (int) (mx - curX);
  int dy = (int) (my - curY);
  switch (event.getAction()) {
     case MotionEvent.ACTION_MOVE:
        if (started) {
            vScroll.smoothScrollBy(0, dy);
            hScroll.smoothScrollBy(dx, 0);
        } else {
            started = true;
        }
        mx = curX;
        my = curY;
        break;
      case MotionEvent.ACTION_UP:
        final VelocityTracker velocityTracker = mVelocityTracker;
        velocityTracker.computeCurrentVelocity(1000);
        int initialXVelocity = (int) velocityTracker.getXVelocity();
        int initialYVelocity = (int) velocityTracker.getYVelocity();
        vScroll.fling(-initialYVelocity);
        hScroll.fling(-initialXVelocity);

        if (mVelocityTracker != null) {
          mVelocityTracker.recycle();
          mVelocityTracker = null;
        }
        break;
    }
    return true;
}

这允许双向滚动(是的,甚至是对角线滚动)以及一些速度以允许 'fling' 效果。最重要的是,它可以很好地与 RTL 和 LTR 布局配合使用!希望这对其他人也有用....

编辑:忘记添加 XML 部分:

<pack.customcomponents.VScroll android:layout_height="fill_parent"
    android:layout_width="fill_parent" android:id="@+id/vScroll">
    <pack.customcomponents.HScroll android:id="@+id/hScroll"
        android:layout_width="fill_parent" android:layout_height="fill_parent">
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@android:color/white"
            android:id="@+id/view_to_scroll"/>
    </pack.customcomponents.HScroll>
</pack.customcomponents.VScroll>