2017-05-29 59 views
-1

我創建了一個自定義的ArrayAdapter,在ArrayAdapter內部有一個LinearLayout,它通過迭代添加視圖。在顯示需要在ListView上顯示的數據之後,所有這些都會很好,直到我向下滾動或向上滾動列表,當一行進行回收並綁定新視圖以顯示在回收行上時,我會得到重複的副本,但是這些副本具有在視圖上不顯示任何數據(文本)。這裏是滾動滾動列表後重復的ArrayAdapter視圖

https://postimg.org/image/z36eqhacd/

前視圖ListView和這裏是ListView的滾動

https://postimg.org/image/dzv28kj9t/

我試過多種方法,但似乎無法得到它的工作後。

public class SurveyAdapter extends ArrayAdapter<SurveyModel> { 

public SurveyAdapter(Context context, ArrayList<SurveyModel> objects) { 
    super(context, R.layout.survey_card, objects); 
} 

@NonNull 
@Override 
public View getView(int position, View convertView, @Nullable ViewGroup parent) { 
    //Get the data item for this position 
    SurveyModel surveyModel = getItem(position); 

    //Construct the ViewHolder 
    ViewHolder viewHolder = new ViewHolder(); 

    //Check if an existing view is being reused, otherwise inflate the view 
    if (convertView == null) { 
     //If there's no view to re-use, inflate a new view for a row 
     LayoutInflater inflater = LayoutInflater.from(getContext()); 
     convertView = inflater.inflate(R.layout.survey_card, parent, false); 
     viewHolder.mContainer = (LinearLayout) convertView.findViewById(R.id.choice_container); 
     viewHolder.question = (TextView) convertView.findViewById(R.id.question); 
     //Cache the viewHolder object inside the new view 
     convertView.setTag(viewHolder); 
    } else { 
     //View is being recycled, retrieve the viewHolder object from tag 
     viewHolder = (ViewHolder) convertView.getTag(); 
    } 

    assert surveyModel != null; 

    //Populate the data from the data object 
    String choices = surveyModel.getChoice(); 

    //Scan each string separately 
    //Strings are separated with a comma ',' 
    Scanner scanner = new Scanner(choices).useDelimiter(",\\s*"); 

    //Create an array list to store each string separately 
    ArrayList<String> choiceList = new ArrayList<>(); 

    //Get all strings from scanner separately 
    while (scanner.hasNext()) { 
     String choice = scanner.next(); //Get each string from scanner 
     choiceList.add(choice); //Store the string in an ArrayList(choiceList) 
    } 

    //Convert choiceList(ArrayList) to a StringArray(choiceArray) 
    String[] choiceArray = choiceList.toArray(new String[choiceList.size()]); 

    int choiceNum; //Will store number of choices to be displayed 
    if (choices.contains("Other,true") || choices.contains("Other,false")) { 
     //Set number or choices to the length(number of items) of the choiceList(ArrayList) 
     //Minus 1 to avoid showing "true" as an option 
     choiceNum = choiceArray.length - 1; 
    } else { 
     //Set number or choices to the length(number of items) of the array 
     choiceNum = choiceArray.length; 
    } 

    //Get number of choices from choiceNum 
    final int numOfChoices = choiceNum; 

    //Populate each choice string from choiceArray 
    for (int i = 0; i < numOfChoices; i++) { 
     //Create a new CheckBox for each choice 
     AppCompatCheckBox checkBox = new AppCompatCheckBox(getContext()); 
     checkBox.setLayoutParams(new LinearLayoutCompat.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); 

     //Add the CheckBox to its survey_view_list view(mContainer) 
     viewHolder.mContainer.addView(checkBox); 

     if (viewHolder.mContainer.getChildAt(i) instanceof AppCompatCheckBox) { 
      //Set each data item in the choiceArray on its own CheckBox according to position 
      ((AppCompatCheckBox) viewHolder.mContainer.getChildAt(i)).setText(choiceArray[i]); 

      final ViewHolder finalViewHolder = viewHolder; //Get viewHolder for inner class access 
      final int checkBoxPosition = i; //Set position of the checked CheckBox 

      ((AppCompatCheckBox) viewHolder.mContainer.getChildAt(i)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
       @Override 
       public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { 
        if (checked) { 
         for (int i = 0; i < numOfChoices; i++) { 
          //Disable all CheckBoxes when a CheckBox is checked 
          finalViewHolder.mContainer.getChildAt(i).setEnabled(false); 
          //Re-enable the checked CheckBox only 
          finalViewHolder.mContainer.getChildAt(checkBoxPosition).setEnabled(true); 
         } 
        } else { 
         for (int i = 0; i < numOfChoices; i++) { 
          //Enable all CheckBoxes when the checked CheckBox is unchecked 
          finalViewHolder.mContainer.getChildAt(i).setEnabled(true); 
         } 
        } 
       } 
      }); 
     } 
    } 

    //Populate the data from the data object via the viewHolder object into the view 
    viewHolder.question.setText(surveyModel.getQuestion()); 

    //Return the completed view to render on screen 
    return convertView; 
} 

//View lookup cache 
private static class ViewHolder { 
    LinearLayout mContainer; 
    TextView question; 
}` 

這裏是對象模型

public class SurveyModel { 

private String question, choice; 

public String getQuestion() { 
    return question; 
} 

public void setQuestion(String question) { 
    this.question = question; 
} 

public String getChoice() { 
    return choice; 
} 

public void setChoice(String choice) { 
    this.choice = choice; 
} 
} 

下面是從活動的方法我一個ArrayAdapter連接到ListView

//Method to populate and display data populated from the database 
private void populateAndDisplayData() { 

//Construct ArrayList 
    ArrayList<SurveyModel> surveyModelArrayList = new ArrayList<>(); 

    //Construct adapter 
    SurveyAdapter adapter = new SurveyAdapter(CreateFromScratch.this, surveyModelArrayList); 

    //Attach the adapter to the ListView 
    binding.list.setAdapter(adapter); 

    //Create a ListView 
    ListView listView = new ListView(CreateFromScratch.this); 

    //Get all the data from the database 
    Cursor allDataCursor = tempSurveyDatabase.fetchAllData(); 

    //StringArray to hold the strings from the database 
    String[] from = new String[]{CustomSurveyDatabase.QUESTION, CustomSurveyDatabase.CHOICES}; 

    //Views to display the string data from StringArray(from) 
    int[] to = new int[]{R.id.question, R.id.choices}; 

    //Construct a SimpleCursorAdapter 
    SimpleCursorAdapter simpleCursorAdapter = new SimpleCursorAdapter(CreateFromScratch.this, R.layout.survey_card, allDataCursor, from, to); 

    // /Attach the adapter to the ListView 
    listView.setAdapter(simpleCursorAdapter); 

    //Construct StringBuilder 
    StringBuilder jsonBuilder = new StringBuilder(); 

    //Strings to hold the item's data from the database 
    String question = null; 
    String choices = null; 

    //Proceed with collecting each item's data if the SimpleCursorAdapter is not empty 
    if (simpleCursorAdapter.getCount() > 0) { 
     //Get every item's id from the database 
     for (int i = 0; i < simpleCursorAdapter.getCount(); i++) { 

      //Get each item's database id 
      long itemId = listView.getAdapter().getItemId(i); 

      //Get each item from the database 
      try { 
       //Construct cursor to fetch an item's data from the database 
       Cursor cursor = tempSurveyDatabase.fetchItem(itemId); 
       question = tempSurveyDatabase.questionHolder; 
       choices = tempSurveyDatabase.choiceHolder; 
      } catch (SQLException e) { 
       Log.v(TAG, e.getMessage()); 
      } 

      if (i == 0) { 
       jsonBuilder.append("{\"survey\": [").append("{\"question\":\"").append(question).append("\","); 
       jsonBuilder.append("\"choices\":\"").append(choices).append("\"},"); 
      } else { 
       jsonBuilder.append("{\"question\":\"").append(question).append("\","); 
       jsonBuilder.append("\"choices\":\"").append(choices).append("\"},"); 
      } 
     } 

     //Remove the last comma from the StringBuilder 
     jsonBuilder.deleteCharAt(jsonBuilder.length() - 1); 
     //Close JSON file scopes 
     jsonBuilder.append("]}"); 

     //Save temporary survey file on the SDCARD 
     try { 
      //Delete existing temporary survey 
      if (TEMP_SURVEY.exists()) { 
       //noinspection ResultOfMethodCallIgnored 
       TEMP_SURVEY.delete(); 
      } 
      FileWriter fileWriter = new FileWriter(TEMP_SURVEY); 
      BufferedWriter bufferedWriter = new BufferedWriter(fileWriter); 
      bufferedWriter.write(String.valueOf(jsonBuilder)); 
      bufferedWriter.close(); 
     } catch (IOException e) { 
      Log.v(TAG, "Temp Survey JSON file failed to write.\nReason: " + e.getMessage()); 
     } 

     //Check if the temporary survey file exists 
     if (TEMP_SURVEY.exists()) { 
      //Read the temporary survey file if it exists 
      new ReadFile(ReadFile.data, ReadFile.output, TEMP_SURVEY); 
      //Parse JSON string from StringBuilder 
      try { 
       JSONObject jsonObjectMain = new JSONObject(ReadFile.output); 
       JSONArray jsonArray = jsonObjectMain.getJSONArray(SurveyJSONKeys.ARRAY_KEY); 
       for (int i = 0; i < jsonArray.length(); i++) { 
        JSONObject jsonObject = jsonArray.getJSONObject(i); 
        SurveyModel surveyModel = new SurveyModel(); 
        surveyModel.setQuestion(jsonObject.getString(SurveyJSONKeys.QUESTION_KEY)); 
        surveyModel.setChoice(jsonObject.getString(SurveyJSONKeys.CHOICES_KEY)); 
        surveyModelArrayList.add(surveyModel); 
       } 
      } catch (JSONException e) { 
       Log.v(TAG, "Unable to parse JSON file.\nReason: " + e.getMessage()); 
      } 
      //Notify the adapter for changes in order to refresh views 
      adapter.notifyDataSetChanged(); 
     } 
    } 
}` 
+0

在您滾動時動態構建視圖看起來像是解決方案的一個糟糕方法。你想要做什麼? –

+0

我同意,我可以簡單地誇大佈局,而不是動態地創建視圖。每當一行被回收並且它已被修復時,我想修復重複的視圖。 –

回答

0

由於您的項目視圖被回收的每一次,你的答案的容器只是附加更多的答案。你有兩個選擇:

  1. 刪除您的容器中的所有子視圖與答案
  2. 填充不要使用getViewTypeCount()getItemViewType(int)強制回收之前。
+0

非常感謝。我知道在填充數據之前刪除所有視圖是關鍵,而且我之前嘗試過,但是我在迭代開始時實現了「viewHolder.mContainer.removeAllViews()」語句,這是錯誤的,因爲它保留刪除了意見,所以我按照第一點建議的方式進行了操作,並將陳述放在所有數據人口陳述之前,並且在回收後不再有重複。 –

+0

很高興幫助! :) – tompee