2014-12-22 9 views
1

CardView에서 RecyclerView를 사용하여 카드 목록을 표시하고 있습니다. 모든 카드에는 2 개의 linearLayout이 있습니다 (머리글에 1 개, 확장에 1 개, 두 번째 카드가 눌러 진 경우에만 표시됨).FindViewHolderForPosition은 카드가 비전에 없을 때 null을 반환합니다.

카드의 우선 순위를 수정하면 카드가 목록의 새 위치로 이동합니다 (아이템의 "배열"에서 위치가 변경된 후 adapter.notifyItemMoved (oldPosition, newPosition)을 호출 함). 그것은 작동합니다, 나는 또한 RecyclerView.scrollToPosition (newPosition)을 호출하여리스트의 새로운 위치를 보여줍니다.

이제는 문제가 생겼습니다. 새로운 위치로 이동 한 후 카드를 확장하고 싶습니다. 그래서 카드 내부에 linearLayout이 필요합니다. 카드를 보유하고있는 ViewHolder에 있습니다. RecyclerView.findViewHolderAtPosition (newPosition)을 사용하려고하는데 ViewHolder가 반환되는 것은 카드가 "visibleTo"앞에 나오면 항상 "scrollTo"앞에 있었기 때문입니다. )은 (

public void moveTask(int oldPosition, int position, Task task) { 
    if (oldPosition < position) { 
     myDataset.add(position, task); 
     myDataset.remove(oldPosition); 
    } else { 
     myDataset.remove(oldPosition); 
     myDataset.add(position, task); 
    } 
    mAdapter.notifyItemMoved(oldPosition, position); 
    mAdapter.notifyDataSetChanged(); 
    mRecyclerView.smoothScrollToPosition(position); 
    MyViewHolder holder =(MyViewHolder)mRecyclerView.findViewHolderForPosition(position); 
    mAdapter.expandCard(holder); 
} 

이 mAdapter.notifyDataSetChanged 안 (I는 또한 비전에없는 경우에도 내가 올바른 ViewHolder를 기대 그래서 다른 문제를 해결하기 위해 mRecyclerView.setItemViewCacheSize (myDataset.size을()) 사용하고 있습니다) 호출 (notifyItemMoved 충분해야합니다)하지만 때로는 그것 없이는 작동하지 않습니다.

expandCard는 linearLayout "visibility"의 Visibility를 Visible로 설정하고 다른 linearLayout은 "Gone"에 이미 표시되도록 설정합니다.

어떻게 작동합니까? 내가 완전히 잘못하고있는거야? 나는이 문제를 이해하기 쉬운 방식으로 설명하기를 희망한다. 나가 나가 무언가를하고있는 까라고 나 더 잘 설명 할 필요가있는 경우에 나는 항상 여기있다, 도움을 위해 감사.

+0

나는 똑같은 상황에 처해있다. –

답변

1

그래서 다소 해결되었지만 나는 잘못된 생각을하고있었습니다.

내가하고있는 것처럼 "외부"에서 올바른 ViewHolder를 찾으려고하지 말고 하나의 바인딩이 올바른 경우 OnBindViewHolder에서 "확장"하십시오.moveTask에서

내가 할 내가 전에 일이었다,하지만 난 열 수 카드의 위치를 ​​설정 : 내가 올바른 위치에있을 때 다음 어댑터의 onBindViewHolder에 내가 확인

public void moveTask(int oldPosition, int position, Task task) { 
    if (oldPosition < position) { 
     myDataset.add(position, task); 
     myDataset.remove(oldPosition); 
    } else { 
     myDataset.remove(oldPosition); 
     myDataset.add(position, task); 
    } 
    mAdapter.notifyItemMoved(oldPosition, position); 
    //this is the important line, it set the variable 
    //openPos with the right number 
    mAdapter.setOpenPos(position); 

    mAdapter.notifyItemChanged(position); 
    mRecyclerView.scrollToPosition(position); 
} 

과 :

@Override 
public void onBindViewHolder(MyViewHolder holder, int pos) { 
    --set other fields-- 
    // expand the right card 
    // if it's the first open it 
    if (pos == 0) { 
     holder.expand(holder.mHeader, holder.mExpanded); 
     // and collapse the opened one 
     if (openPos != -1 && openPos != pos) { 
      open.collapse(open.mHeader, open.mExpanded, true); 
     } 
     isFirst = holder; 
     open = holder; 
     openPos = 0; 
    } 
    // I'm in the position of the one I should open 
    // expand it 
    else if (openPos != -1 && pos == openPos) { 
     holder.expand(holder.mHeader, holder.mExpanded); 
     // and if I changed openPos with setOpenPos() 
     // collapse the "old" open card 
     if(openPos != open.getPosition()){ 
      open.collapse(open.mHeader, open.mExpanded, true); 
     } 
     open = holder; 
    } 
    // if I'm in another card just collapse it 
    else { 
     holder.collapse(holder.mHeader, holder.mExpanded, true); 
    } 

} 

그리고 이렇게하면 정상적으로 작동합니다. 그것은 "setItemViewCacheSize"를 사용하지 않아도 작동해야하지만, 다른 별다른 문제가 없으므로 그대로 두었습니다.

0

우선 mRecyclerView.setItemViewCacheSize(myDataset.size())으로 전화하지 마십시오. LinearLayout을 사용하는 것과별로 다르지 않은 목록의 각 항목에 대해 ViewHolder를 만드는 것을 의미합니다.

두 번째로, findViewHolderForPosition은 하위 만 검사합니다. 이 내용은 설명을 위해 문서에 추가됩니다.

mAdapter.notifyItemMoved이 아니며입니다. RV는 항목을 리 바인드해야한다는 것을 모르기 때문에 충분합니다. 또한 RV가보기가 리바운드되어야 함을 알 수 있도록 notifyItemChanged에 전화해야합니다.

두 가지보기 유형을 만듭니다 (간단히하기 위해 필요 없음). 하나는 접 혔고 하나는 펼쳤습니다. 당신이 이동하고 항목을 확장하고자 할 때 다음, 전화 :

public void moveTask(int oldPosition, int position, Task task) { 
    if (oldPosition < position) { 
     myDataset.add(position, task); 
     myDataset.remove(oldPosition); 
    } else { 
     myDataset.remove(oldPosition); 
     myDataset.add(position, task); 
    } 
    task.expanded = true; 
    mAdapter.notifyItemMoved(oldPosition, position); 
    mAdapter.notifyItemChanged(position); 
} 

//adapter 
getItemViewType(int position) { 
    return myDataset.get(position).expanded ? TYPE_EXPANDED : TYPE_HEADER; 
} 

을 당신이보기를 리 바인드합니다 notifyItemChanged RV를 호출하기 때문입니다.

+0

나는 setItemViewCacheSize를 호출해서는 안된다는 것을 알고 있지만, 그것 없이는 몇 가지 이상한 문제가있다. 예를 들어 첫 번째 카드를 확장하고 아래로 스크롤하면 12 번째 (내 전화기에서는 14 번째)가 확장된다. ({ \t \t \t expanded.setVisibility을 (RelativeLayout의 확장의 LinearLayout 헤더) 개인 무효가 확장 : 나는 당신이 제안처럼 내가 전환을 애니메이션 애니메이터를 사용하고 있기 때문에, 두 가지보기 유형을 사용하는 방법을 잘 모르겠어요 View.VISIBLE); \t \t \t \t \t ... \t ValueAnimator 애니메이터 = slideAnimator (header.getMeasuredHeight() \t \t \t \t \t expanded.getMeasuredHeight(), 확장 된); \t \t \t animator.start(); \t \t} –

관련 문제