1

ResourceCursorAdapter가 채워진 ListView가 있습니다. loaders 메커니즘을 사용하여 목록 항목에 대해 ContentProvider를 쿼리합니다. 목록 항목에서 스 와이프 제스처를 감지하여 일부 동작을 수행합니다. 새 항목은 백그라운드 서비스에 의해 추가되므로 목록이 동적으로 변경 될 수 있습니다.Android에서 스 와이프 제스처 ListView items

스 와이프를 시작하고 데이터베이스 변경이 발생하는 경우를 제외하면 모든 것이 정상적으로 작동합니다 (새 행을 추가하는 백그라운드 서비스의 결과). 이 경우 제스처가 제대로 감지되지 않습니다. ACTION_CANCEL이 목록 항목보기로 전달되고 모든 보이는 항목에 대해 bindView가 실행되는 것으로 나타났습니다. bindView 메서드 내에서 일부 텍스트 만 설정합니다. 거기에는 리스너가 변경되지 않습니다.

배경 서비스로 새 항목을 추가하는 경우에도 제스처가 작동하도록하려면 어떻게해야합니까? 아마도 모션이 취소되는 것을 방지하는 방법이 있거나 데이터베이스 업데이트를 일시 중지하여 제스처를 방해하지 않을 수 있습니다.

+0

로더를 사용하는 경우 LoaderCallbacks 구현의'onLoadFinished'에서 아마도'Adapter.swapCursor'를 사용하고 있습니다 ... 이것을 가정하면 ... 슬라이드하기 시작할 때 (일부 플래그를 추가 할 때) 이것을하지 마십시오. 어떤 대기열에 커서를 놓고 슬라이드를 마친 후'swapCursor'를 사용하십시오. – Selvin

+0

모든 가정은 옳지 만이 해결책은 효과가 없습니다. 나는 당신이 묘사 한 것을 정확하게 시도했지만 오래된 데이터를 표시하는 대신 내 목록이 비어있게되었습니다. 일부 디버깅 후 CursorLoader가 이전 커서에서 close() 메서드를 호출한다는 것을 알았습니다. 따라서 더 이상 사용할 수 없습니다. 어쨌든 도와 주셔서 감사합니다. – Bartek

답변

0

데이터와 UI에 대한 업데이트를 분리해야합니다. 이것은 약간 추한 것입니다.

1) 커서 어댑터를 사용하지 마십시오. 커서의 결과를 일부 데이터 구조로로드하고 어댑터가 해당 데이터 사본을 사용하게하십시오. 그런 다음 새 데이터를 얻으면 해당 데이터 구조의 새 복사본을 만든 다음 어댑터가 보게되는 변수에 저장하고 notifyDataSetChanged를 호출합니다. 그런 식으로 커서를 변경하고 화면을 업데이트하는 것은 연결되지 않습니다.

2) 서비스가 커서를 업데이트하면 자동으로 목록보기를 업데이트하지 마십시오. 그런 다음 ListView를 하위 클래스로 만듭니다. 서비스에서 업데이트를 받으면 새 데이터를 저장하지만 목록보기는 업데이트하지 마십시오. 대신 플래그를 설정하십시오. 새 ListView 하위 클래스에서 onTouchEvent를 재정 의하여 ACTION_UP 이벤트가 발생하면 해당 플래그도 확인하십시오. 플래그가 설정되어 있으면 false로 설정 한 다음 어댑터의 notifyDataSetChanged를 설정하십시오. 이렇게하면 사용자가 스크롤을 마칠 때까지 목록이 업데이트되지 않습니다.

+0

두 번째 접근 방식이 저에게 효과적이지는 않지만 답변을 수락합니다. notifyDataSetChanged() 및 notifyDataSetInvalidated()를 모두 재정의 한 후에도 목록 항목보기가 만들어지고 바인딩되었습니다. 레이아웃 메커니즘에 의해 호출되어 뷰를 정확하게 측정하고 배치하는 것처럼 보입니다. === 필자는 BaseAdapter를 확장하고 필요한 데이터를 목록에 저장하는 작업을 마쳤습니다. 데이터 세트 변경/무효화 알림을 얻기 위해 커서 인스턴스를 유지해야했습니다. 목록 항목 중 하나를 터치하는 동안 터치가 끝나면 새 커서를 저장하여 목록을 다시 채우는 것만으로 데이터 업데이트를 잠급니다. – Bartek

0

ResourceCursorAdapter에서보기에 대한 터치 리스너를 newView()으로 설정하십시오. newView()에서 사용할 터치 리스너를 전달하려면 어댑터의 생성자를 수정해야합니다.

+0

나는 당신이 대답하는 것을 이해하지 못한다는 것을 두려워합니다. 모든 목록 항목보기에 공통 터치 리스너가 하나만 있어야한다고 제안 하시겠습니까? 왜 이것이 도움이 될까요? 지금은 newView 메서드 내에서 터치 리스너를 만들어 모든보기가 고유 한 인스턴스를 갖도록합니다. – Bartek

0

다음과 같은 방법으로 해결했습니다. 내 목록 어댑터에서

, 나는 플래그가 :

private boolean mIsSwiping; 

사용자가 강타 시작하고 슬쩍 작업이 완료 될 때 거짓 때이 true로 설정을 (자동화 된 애니메이션을 통해 할 수있다).

getView() 맨 위에서 플래그의 값을 확인하고 필요한 경우 일찍 리턴합니다. 이렇게하면 잘못된 목록보기 항목을 다시 그릴 수 없습니다. 또한

if (convertView != null && mIsSwiping) { 
    return convertView; 
} 

, 어댑터를 사용하는 조각에, 나는 비슷한 논리를 가지고 있지만, 커서 부하 로직에 적용 :

private Cursor mNewCursor; 

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) { 
    if (mListAdapter.isSwiping()) { 
     mNewCursor = cursor; 

    } else { 
     mListAdapter.swapCursor(cursor); 
     mNewCursor = null; 

    } 
} 

그리고 같은 조각에서 바로 설정하기 전에 mListFragment의 false로 플래그를 mIsSwiping :이 도움이

if (mNewCursor != null) { 
    mListFragment.swapCursor(mNewCursor); 
    mNewCursor = null; 
} 

희망 - 정말 그냥 콘크리트 코드 위에 게이브의 답변을 구체화합니다.

별도로 추적해야하는 한 가지는 mNewCursor가 스왑 아웃하기 전에 닫혀 있는지 여부입니다. 나는 그 문제에 스스로 부딪치지 않았다. 그러나 YMMV.