2016-01-25 2 views
1

Я пытаюсь получить ViewDragHelper работать с вертикальным LinearLayout, - Контейнер - который имеетView Drag Helper помощник

A ---- List View 
B ---- horizontal linear layout 
C ---- Support Map Fragment 

как мнения детей.

A имеет layout_height="0dp". Потянув вниз на B, необходимо пропорционально увеличить высоту A, там, показывая содержимое на ListView, тем самым автоматически переставляя B и изменяя размер C в процессе.

Ниже приведен код Контейнера LinearLayout.

public class MyLinearLayout extends LinearLayout { 

private LinearLayout headerLayout; 
private ListView filtersListView; 

private ViewDragHelper viewDragHelper; 
private int MARGIN; 

public MyLinearLayout (Context context) { 
    super(context); 
    init(); 
} 

public MyLinearLayout (Context context, AttributeSet attrs) { 
    super(context, attrs); 
    init(); 
} 

public MyLinearLayout (Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(); 
} 

private void init() { 
    viewDragHelper = ViewDragHelper.create(this, 1, new DragHelperCallback()); 
    float GESTURE_THRESHOLD_DP = 10.0f; 
    float scale = getResources().getDisplayMetrics().density; 

    MARGIN = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f); 
} 

@Override 
protected void onFinishInflate() { 
    Log.i("Places", "onFinishInflate"); 
    super.onFinishInflate(); 

    headerLayout = (LinearLayout) findViewById(R.id.header); 
    filtersListView = (ListView) findViewById(R.id.filters_list); 
} 

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    Log.i("Places", "onInterceptTouchEvent"); 
    return viewDragHelper.shouldInterceptTouchEvent(ev); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    Log.i("Places", "onTouchEvent"); 
    viewDragHelper.processTouchEvent(event); 

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) event.getRawY()); 
    layoutParams.setMargins(MARGIN, MARGIN, MARGIN, MARGIN); 
    filtersListView.setLayoutParams(layoutParams); 

    return true; 
} 

private class DragHelperCallback extends ViewDragHelper.Callback { 

    @Override 
    public boolean tryCaptureView(View child, int pointerId) { 
     Log.i("Places", "tryCaptureView " + (child == headerLayout)); 
     return child == headerLayout; 
    } 

    @Override 
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 
     Log.i("Places", "onViewPositionChanged " + changedView.getClass().getName()); 
     super.onViewPositionChanged(changedView, left, top, dx, dy); 
    } 

    @Override 
    public void onViewReleased(View releasedChild, float xvel, float yvel) { 
     Log.i("Places", "onViewReleased " + releasedChild.getClass().getName()); 
     super.onViewReleased(releasedChild, xvel, yvel); 
    } 
} 
} 

Я рассмотрел следующее.

ViewDragHelper: how to use it?

+0

ViewDragHelper.shouldInterceptTouchEvent (ev) всегда возвращает false. Дайте мне знать, если вам нужна дополнительная информация. –

ответ

1

Ваш ViewDragHelper откусил. В частности, вам не хватает переопределения clampViewPositionVertical(), которое требуется для полного перетаскивания представления. Прямо сейчас, ваш ViewDragHelper фактически не работает. Вероятно, вы получаете какое-то движение, потому что вы управляете LayoutParams непосредственно за каждые onTouchEvent(), что также вызовет некоторые проблемы.

Вы, вероятно, хотите, чтобы ваш код обратного вызова выглядеть следующим образом:

@Override 
public boolean onInterceptTouchEvent(MotionEvent ev) { 
    return viewDragHelper.shouldInterceptTouchEvent(ev); 
} 

@Override 
public boolean onTouchEvent(MotionEvent event) { 
    viewDragHelper.processTouchEvent(event); 

    return true; 
} 

private class DragHelperCallback extends ViewDragHelper.Callback { 

    @Override 
    public int clampViewPositionVertical(View child, int top, int dy) { 
     //Never go below fully visible 
     final int bottomBound = getHeight() - child.getHeight(); 
     //Never go above the top 
     final int topBound = 0; 

     return Math.max(Math.min(top, bottomBound), topBound); 
    } 

    @Override 
    public boolean tryCaptureView(View child, int pointerId) { 
     //Capture touches to the header view 
     return child == headerLayout; 
    } 

    @Override 
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { 
     if (dy == 0) return; 

     //React to the position change of the header by modifying layout 
     LinearLayout.LayoutParams layoutParams = (LayoutParams) filtersListView.getLayoutParams(); 
     layoutParams.height += dy; 
     filtersListView.setLayoutParams(layoutParams); 
    } 
} 

Это устанавливает перетаскивать границы вашего «вида заголовка» свободно перемещаться между верхней точкой зрения контейнера и нижним (зажимая его поэтому он не выходит за пределы экрана). Само по себе это приведет только к перемещению заголовка. Перемещение вашего LayoutParams кода в onViewPositionChanged() позволяет вашим представлениям сверху/снизу реагировать на точное расстояние перетаскивания.

Два предупреждения:

  1. Не добавлять поля к вашему LayoutParams. То, как вы используете их для постоянного изменения пропорций, приведет к перетаскиванию. Если вам нужно вставить содержимое ListView, используйте прокладку или другой вложенный контейнер.
  2. Изменение формата всего вида, как это может быть очень дорогое (макеты проходят не дешево, и вы запускаете его каждый раз, когда вы изменяете LayoutParams). Это может работать для очень простой компоновки, но если ваше представление становится более сложным, вы, вероятно, увидите, что производительность пострадает от старого оборудования.
+0

Эй, Дэйв, хорошо слышать от вас, я попробую это. –

Смежные вопросы