2017-07-10 23 views
22

Tôi đang cố triển khai ScrollView trong Android không cuộn khi thêm mục bên trên vị trí cuộn hiện tại.Tạo ScrollView bị khóa trong Android

Việc thực hiện mặc định của ScrollView cư xử như sau:

Thêm một mục trên vị trí cuộn hiện tại: enter image description here

Thêm một mục dưới vị trí cuộn hiện tại: enter image description here

Làm thế nào tôi có thể "khóa" ScrollView trước khi thêm một mặt hàng trên dòng điện ent di chuyển vị trí?

Đây là tệp bố cục của tôi, tôi hiện đã ghi đè cả số ScrollViewLinearLayout nhưng chưa thực hiện bất kỳ thay đổi nào.

<LinearLayout 
     android:layout_height="fill_parent" 
     android:orientation="vertical" 
     android:layout_width="fill_parent"> 

    <LinearLayout 
     android:id="@+id/LinearLayout02" 
     android:layout_height="wrap_content" 
     android:layout_width="fill_parent" 
     android:layout_alignParentBottom="true"> 
     <Button 
      android:id="@+id/Button02" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" android:text="Add To Top" 
      android:onClick="addToStart"> 
     </Button> 
     <Button 
      android:id="@+id/Button03" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_weight="1" 
      android:text="Add to End" 
      android:onClick="addToEnd"> 
     </Button> 
    </LinearLayout> 
    <com.poc.scroller.locable.lockablescrollerpoc.LockedScrollView xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:fillViewport="true" 
     android:scrollbarAlwaysDrawVerticalTrack="true" 
     android:verticalScrollbarPosition="right" 
     android:fadeScrollbars="false" 
     android:background="@color/scrollColor"> 

     <com.poc.scroller.locable.lockablescrollerpoc.LockedLinearLayout 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:orientation="vertical" 
      android:id="@+id/Container"> 
     </com.poc.scroller.locable.lockablescrollerpoc.LockedLinearLayout> 

    </com.poc.scroller.locable.lockablescrollerpoc.LockedScrollView> 
</LinearLayout> 
</android.support.constraint.ConstraintLayout> 

Ví dụ Mã Nguồn: https://github.com/Amaros90/android-lockable-scroller-poc

Cảm ơn bạn!

+0

cung cấp bố trí đoạn pls –

+0

Thử gọi cuộn đầu trang và di chuyển xuống dưới vào nút bấm –

+0

@AjayVenugopal những gì bạn đang đề xuất sẽ cung cấp cho các ứng dụng hành vi flaky – Amaros

Trả lời

1

Thực hiện điều này làm việc cho tôi. Bạn có thể xem ứng dụng mẫu mà tôi đã thêm vào trong câu hỏi gốc.

public class LockableScrollView extends ScrollView { 

    private boolean _enabled = true; 

    public LockableScrollView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     super.setFillViewport(true); 
    } 

    @Override 
    public void addView(View layout, ViewGroup.LayoutParams params) { 
     super.addView(layout, params); 

     ((ViewGroup)layout).setOnHierarchyChangeListener(new OnHierarchyChangeListener() { 
      @Override 
      public void onChildViewAdded(View layout, View item) { 
       if (_enabled) { 
        item.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
         @Override 
         public void onLayoutChange(View item, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
         item.removeOnLayoutChangeListener(this); 

         int scrollViewY = ((LockableScrollView)item.getParent().getParent()).getScrollY(); 
         int layoutPosition = ((View)item.getParent()).getTop(); 
         boolean shouldScroll = item.getTop() + layoutPosition <= scrollViewY || item.getBottom() + getTop() <= scrollViewY; 



         if (shouldScroll) { 
          final int childViewHeight = item.getHeight(); 

          ((View)item.getParent()).addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
           @Override 
           public void onLayoutChange(View layout, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
            layout.removeOnLayoutChangeListener(this); 

            LockableScrollView scrollView = ((LockableScrollView)layout.getParent()); 
            scrollView.scrollTo(scrollView.getScrollX(), scrollView.getScrollY() + childViewHeight); 
           } 
          }); 
         } 
         } 
        }); 
       } 
      } 

      @Override 
      public void onChildViewRemoved(View layout, View item) { 
       if (_enabled) { 
        int scrollViewY = ((LockableScrollView)layout.getParent()).getScrollY(); 
        int layoutPosition = layout.getTop(); 
        boolean shouldScroll = item.getTop() + layoutPosition <= scrollViewY || item.getBottom() + getTop() <= scrollViewY; 


        if (shouldScroll) { 
         final int childViewHeight = item.getHeight(); 

         layout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
          @Override 
          public void onLayoutChange(View layout, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
           layout.removeOnLayoutChangeListener(this); 

           LockableScrollView scrollView = ((LockableScrollView)layout.getParent()); 
           scrollView.scrollTo(scrollView.getScrollX(), scrollView.getScrollY() - childViewHeight); 
          } 
         }); 
        } 
       } 
      } 
     }); 
    } 
} 
1

Bạn có thể thử sử dụng RecyclerView và triển khai onDataSetChanged(). Sau đó, phát hiện xem nút add to TOP hoặc add to END có được nhấn hay không. Sau đó sử dụng scrollToPositionWithOffset(int, int) để quản lý cuộn.

Ví dụ:

//Scroll item 3 to 20 pixels from the top 
linearLayoutManager.scrollToPositionWithOffset(3, 20); 

Đối khôi phục lại vị trí cuộn của một RecyclerView, đây là cách để lưu giữ vị trí cuộn (hai đối số cho phương pháp scrollToPositionWithOffset(int, int)):

int index = linearLayoutManager.findFirstVisibleItemPosition(); 
View v = linearLayoutManager.getChildAt(0); 
int top = (v == null) ? 0 : (v.getTop() - linearLayoutManager.getPaddingTop()) 
+0

Khi sử dụng 'RecyclerView', bạn có thể gọi hàm này, và cuộn sẽ không thay đổi _flagsAdapter.notifyItemInserted (0); Nhưng chúng tôi vẫn cần triển khai tính năng này bằng 'ScrollView' chứ không phải với' RecyclerView' – Amaros

16

Bạn có thể dễ dàng có được hành vi ngược lại bằng cách sử dụng addOnLayoutChangeListener trong số LinearLayout và đặt lại ScrollY của ScrollView. Đây là việc thực hiện tại của bạn ScrollViewActivity.onCreate

protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.scrollview); 

    _linearLayout = (LockedLinearLayout)findViewById(R.id.Container); 
    _scrollView = (LockedScrollView)findViewById(R.id.ScrollView); 
    _layoutInflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

    _linearLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() { 
     @Override 
     public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { 
      _scrollView.scrollTo(0, _scrollView.getScrollY() + (bottom - oldBottom)); 
     } 
    }); 

    addExampleImage(10, _linearLayout); 
} 

Sau đó, bạn có thể dễ dàng cờ các addToEnd chức năng hoặc kiểm tra nơi đứa trẻ được bổ sung để tránh thay đổi cuộn khi một số đứa trẻ sẽ được thêm vào phía dưới.

0

bạn có thể làm điều đó một cách dễ dàng chỉ nhận được nó ..

đầu tiên của tất cả các cửa hàng trong sự kiện onclick giá trị int bởi sử dụng getFirstVisiblePosition()

ví dụ.

trong onclick của nút thêm yếu tố làm điều này ---

int currentpos = recycleview.getFirstVisiblePosition();

bây giờ sau khi bạn chèn elment niêm yết/recyclerview ---

recyclerview.scrolltoposition (currentpos);

thats it thử nếu bạn muốn làm điều đó mà không có lỗi ..

Good Luck :)

Các vấn đề liên quan