2014-10-23 3 views
0

사용자가 목록보기에서 항목을 클릭하면 선택한 listView 항목의 배경색이 수동으로 변경됩니다. 배경을 변경하는 것 이상의 계획을 세우므로 목록보기가 필요합니다.Android : notifydatachanged 목록보기를 업데이트하지 않음

문제점은 notifyDataChanged가 발생하지 않는 경우입니다. 기능에 배치 된 로그 때문에 항목을 클릭하면 onItemClick이 트리거되고 어댑터에 notifyDataSetChanged 호출이 수행되는지 확인할 수 있습니다.

데이터가 뷰에 링크되는 각 위치에 대해 "getView"를 다시 호출해야한다고 생각합니다. 그러나 이것은 발생하지 않습니다. 아무 일도 일어나지 않을 것입니다. 내가 여기서 무엇을 놓치고 있니?

class MyOnItemClickListener implements AdapterView.OnItemClickListener{ 

    @Override 
    public void onItemClick(final AdapterView<?> parent, View view, 
      final int position, long id) { 

      Log.i(TAG, "listview on click " + position); 

      MyListAdapter adapter = (MyListAdapter) parent.getAdapter(); 

      adapter.mSelected = position; 
      adapter.notifyDataSetChanged(); 
    } 
} 


class MyListAdapter extends BaseAdapter{ 

    public List<String> mTxtContents; 

    public int mGroupCount; 
    public int mSelected; 

    public void setData(List<String> txtContents){ 

     mTxtContents = txtContents; 
     mGroupCount = txtContents.size(); 
    } 

    @Override 
    public void registerDataSetObserver(DataSetObserver observer) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public void notifyDataSetChanged() { 

     Log.i(TAG, "notify data set changed"); 

     // TODO Auto-generated method stub 
     super.notifyDataSetChanged(); 
    } 

    @Override 
    public void unregisterDataSetObserver(DataSetObserver observer) { 
     // TODO Auto-generated method stub 

    } 

    @Override 
    public int getCount() { 

     Log.i(TAG, "nva panel group count " + mGroupCount); 

     return mGroupCount; 
    } 

    @Override 
    public Object getItem(int position) { 
     // TODO Auto-generated method stub 
     return null; 
    } 

    @Override 
    public long getItemId(int position) { 
     return position; 
    } 

    @Override 
    public boolean hasStableIds() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @SuppressLint("InflateParams") 
    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     Log.i(TAG, "get view, " + position); 

     if(convertView == null){ 
      LayoutInflater li = LayoutInflater.from(getActivity()); 
      convertView = li.inflate(R.layout.lvitem_navpanel, parent, false); 
     } 

     TextView tv = (TextView) convertView.findViewById(R.id.tv_txtData); 
     tv.setText(mTxtContents.get(position)); 

     if(mSelected == position){ 
      convertView.setBackgroundColor(Color.parseColor("#00FF00")); 
     }else{ 
      convertView.setBackgroundColor(getResources().getColor(android.R.color.transparent)); 
     } 

     return convertView; 
    } 

    @Override 
    public int getItemViewType(int position) { 
     // TODO Auto-generated method stub 
     return 0; 
    } 

    @Override 
    public int getViewTypeCount() { 
     // TODO Auto-generated method stub 
     return 1; 
    } 

    @Override 
    public boolean isEmpty() { 
     // TODO Auto-generated method stub 
     return false; 
    } 

    @Override 
    public boolean areAllItemsEnabled() { 
     // TODO Auto-generated method stub 
     return true; 
    } 

    @Override 
    public boolean isEnabled(int position) { 
     // TODO Auto-generated method stub 
     return true; 
    } 
} 
+1

을 할 수 있습니다. 또한, 필요하지 않으면 registerDataSetObserver 및 unregisterDataSetObserver를 겹쳐 쓰지 마십시오. ListView는이 옵저버 메커니즘을 사용하여 notifyDataSetChanged를 호출 한 시점을 알 수 있지만 이러한 메서드를 비공개로 구현하면이 문제가 발생하지 않습니다. BaseAdapter가 당신을 대신해 주도록하십시오. –

+0

나는 당신의 대답이 작동하지 않을 것이라고 생각했지만 ... :) 그 일을 한 부분은 register/unreigster 함수의 재정의를 삭제하는 것입니다. getItem() 함수를 삭제해도 Log에 영향을주지 않았습니다. 이클립스는 super 함수를 호출하지 않고 unregister/register 함수를 자동으로 채웠다. 그리고리스트 뷰를 깨뜨렸다 고 생각한다. 이 질문을 답으로 쓰려면 올바른 것으로 표시하겠습니다. – NameSpace

답변

1

어댑터를 수정 한 후에 다시 설정하십시오. 좋아요 :

MyListAdapter adapter = (MyListAdapter) parent.getAdapter(); 
adapter.mSelected = position; 
parent.setAdapter(adapter); 

새로운 어댑터를 호출하면 리사이클 러가 지워집니다. (불필요한 보일러 및 처리처럼 보이지만 어쩌면 당신은 특별한 필요가있는 나에게) 난 당신이 위의 게시 된 패턴을 사용하는 이유는 확실하지 않다

, 다음 힘 : 편집

당신이 당신의 온 클릭 리스너에서

당신이 자동으로 목록 항목에 대한 변경 사항을 적용합니다

TextView txtView = (TextView)listView.getChildAt(position); 
txtView.setBackgroundColor(Color.RED); 
txtView.setText("New Text"); 

같은 것을 할 수 있습니다에 도움이 될. 당신은 전체 행을 새로 필요한 경우

당신은 당신이 당신의 MyListAdapter의의 getItem (INT 위치)를 구현 완료 할 필요가

View view = list.getChildAt(position); 
list.getAdapter().getView(position, view, list); 

Source

+0

이것은 +1에서도 작동합니다. 현재 설정되어있는 어댑터로 listview를 설정하면 getView를 강제로 호출하고 모든 하위 항목을 다시 그립니다. 나는이 일을하는 데 드는 비용을 알지 못하기 때문에 이것을 가장 좋은 대답으로 표시 할 수는 없습니다. 예를 들어, listView의 자식 (예 : viewHolders)에 캐시 된 값이 손실되는지, 확장 가능한 목록보기의 경우 어떤 그룹이 확장되었는지와 같은 상태 정보 또는 동일한 경우에도 어댑터를 다시 설정하는 오버 헤드 어댑터). – NameSpace

+0

다른 것들이 당신에게 효과가 있었습니까? 어댑터를 재설정하는 것 외에는? 행운을 빌어 요. – prettyvoid

+0

대답은 @Michael Krause에게 의견을 제공했습니다. 이 문제는 super 함수를 호출하지 않고 등록자/등록 데이터 관찰자에 대한 스텁을 작성하여 "구현되지 않은 메소드"를 대체하는 것이 좋습니다. – NameSpace

관련 문제