探究Android中ListView複用導致布局錯亂的解決方案_Android

來源:互聯網
上載者:User

首先來說一下具體的需求是什麼樣的:

需求如圖所示,這裡面有ABCD四個選項的題目,當點擊A選項,如果A是正確的答案,則變成對勾的圖案,如果是錯誤答案,則變成錯誤的圖案,這裡當時在寫的時候覺得很簡單,只要是在點擊的時候判斷我點擊的選項與正確答案是否一樣,是一樣就將圖片換成正確的樣式,如果不一樣就換成錯誤的樣式,於是我便寫了下面的代碼(只貼出了核心Adapter中的代碼)

package com.fizzer.anbangproject_dahuo_test.Adapter; import android.annotation.TargetApi; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.fizzer.anbangproject_dahuo_test.Model.ConvertModel; import com.fizzer.anbangproject_dahuo_test.R; import java.util.List; /** * Created by Fizzer on 2016/10/8. * Email: doraemonmqq@sina.com */ public class ConvertViewAdapter extends BaseAdapter { private List<ConvertModel> list; private Context mContext; public ConvertViewAdapter(Context context, List<ConvertModel> list) { mContext = context; this.list = list; } @Override public int getCount() { if (list == null) { return 0; } else { return list.size(); } } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder mViewHolder; if (convertView == null) { convertView = View.inflate(mContext, R.layout.view_upgradepartnet_topic_layout, null); mViewHolder = new ViewHolder(); mViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle); mViewHolder.tvSelectA = (TextView) convertView.findViewById(R.id.tvSelectA); mViewHolder.tvSelectB = (TextView) convertView.findViewById(R.id.tvSelectB); mViewHolder.tvSelectC = (TextView) convertView.findViewById(R.id.tvSelectC); mViewHolder.tvSelectD = (TextView) convertView.findViewById(R.id.tvSelectD); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } ConvertModel module = list.get(position); mViewHolder.tvTitle.setText("Q" + (position + 1) + ":" + module.title); mViewHolder.tvSelectA.setText(module.optionA); mViewHolder.tvSelectB.setText(module.optionB); mViewHolder.tvSelectC.setText(module.optionC); mViewHolder.tvSelectD.setText(module.optionD); initListener(mViewHolder, module.rightOption, position, module); return convertView; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } private void initListener(final ViewHolder mViewHolder, final String select, final int position, final ConvertModel module) { mViewHolder.tvSelectA.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { judgeSelect(mViewHolder, mViewHolder.tvSelectA, "A", select, position); } }); mViewHolder.tvSelectB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { judgeSelect(mViewHolder, mViewHolder.tvSelectB, "B", select, position); } }); mViewHolder.tvSelectC.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { judgeSelect(mViewHolder, mViewHolder.tvSelectC, "C", select, position); } }); mViewHolder.tvSelectD.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { judgeSelect(mViewHolder, mViewHolder.tvSelectD, "D", select, position); } }); } private void clearSelectState(ViewHolder mViewHolder) { mViewHolder.tvSelectA.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_a), null, null, null); mViewHolder.tvSelectB.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_b), null, null, null); mViewHolder.tvSelectC.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_c), null, null, null); mViewHolder.tvSelectD.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_d), null, null, null); } private void judgeSelect(ViewHolder viewHolder, TextView text, String select, String rightSelect, int position) { //清楚之前的狀態 clearSelectState(viewHolder); if (select.equals(rightSelect)) { text.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_right), null, null, null); } else { text.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_error), null, null, null); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private Drawable getDrawableResource(int res) { Drawable drawable = mContext.getDrawable(res); drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); return drawable; } class ViewHolder { TextView tvTitle; TextView tvSelectA; TextView tvSelectB; TextView tvSelectC; TextView tvSelectD; } }

寫完這段代碼信心滿滿,覺得沒問題了,但是在手機上一運行,發現出問題了,效果如下:

是的,由於listview的布局複用機制,導致下面沒有選擇的條目也因為複用而選擇了選項

其實解決的方法很簡單,就是將這個選中的條目與該條目對應的model相關聯起來,具體怎麼做呢,下面來仔細的分析分析,

首先在建立model的時候添加一個預設的欄位,這個欄位就是你選擇的選項,當然初始值是沒有的,在getView中對布局進行初始化的時候,就去判斷這個欄位是否有值,並且值為多少,如果有值,就去判斷值為正確還是為錯誤,為正確則替換成正確的圖片,如果為錯誤,則替換成錯誤的圖片,如果沒有值,則顯示原始的ABCD四種初始化圖片,這樣,問題就迎刃而解了

下面貼出完整的代碼,其實就跟上面的代碼是差不多的,只不過在對model中添加的那個欄位進行了一些複製與判斷

package com.fizzer.anbangproject_dahuo_test.Adapter; import android.annotation.TargetApi; import android.content.Context; import android.graphics.drawable.Drawable; import android.os.Build; import android.text.TextUtils; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; import com.fizzer.anbangproject_dahuo_test.Model.ConvertModel; import com.fizzer.anbangproject_dahuo_test.R; import java.util.List; /** * Created by Fizzer on 2016/10/8. * Email: doraemonmqq@sina.com */ public class ConvertViewAdapter extends BaseAdapter { private List<ConvertModel> list; private Context mContext; public ConvertViewAdapter(Context context, List<ConvertModel> list) { mContext = context; this.list = list; } @Override public int getCount() { if (list == null) { return 0; } else { return list.size(); } } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder mViewHolder; if (convertView == null) { convertView = View.inflate(mContext, R.layout.view_upgradepartnet_topic_layout, null); mViewHolder = new ViewHolder(); mViewHolder.tvTitle = (TextView) convertView.findViewById(R.id.tvTitle); mViewHolder.tvSelectA = (TextView) convertView.findViewById(R.id.tvSelectA); mViewHolder.tvSelectB = (TextView) convertView.findViewById(R.id.tvSelectB); mViewHolder.tvSelectC = (TextView) convertView.findViewById(R.id.tvSelectC); mViewHolder.tvSelectD = (TextView) convertView.findViewById(R.id.tvSelectD); convertView.setTag(mViewHolder); } else { mViewHolder = (ViewHolder) convertView.getTag(); } ConvertModel module = list.get(position); mViewHolder.tvTitle.setText("Q" + (position + 1) + ":" + module.title); mViewHolder.tvSelectA.setText(module.optionA); mViewHolder.tvSelectB.setText(module.optionB); mViewHolder.tvSelectC.setText(module.optionC); mViewHolder.tvSelectD.setText(module.optionD); initListener(mViewHolder, module.rightOption, position, module); <span style="color:#cc0000;">if (TextUtils.isEmpty(module.check)) { clearSelectState(mViewHolder); } else { judgeSelect(mViewHolder, getCheckTextView(mViewHolder, module.check), module.check, module.rightOption, position); }</span> return convertView; } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } private void initListener(final ViewHolder mViewHolder, final String select, final int position, final ConvertModel module) { mViewHolder.tvSelectA.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { <span style="color:#cc0000;">module.check = "A";</span> judgeSelect(mViewHolder, mViewHolder.tvSelectA, "A", select, position); } }); mViewHolder.tvSelectB.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { <span style="color:#cc0000;">module.check = "B";</span> judgeSelect(mViewHolder, mViewHolder.tvSelectB, "B", select, position); } }); mViewHolder.tvSelectC.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { <span style="color:#cc0000;">module.check = "C"; </span> judgeSelect(mViewHolder, mViewHolder.tvSelectC, "C", select, position); } }); mViewHolder.tvSelectD.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { <span style="color:#cc0000;">module.check = "D";</span> judgeSelect(mViewHolder, mViewHolder.tvSelectD, "D", select, position); } }); } private void clearSelectState(ViewHolder mViewHolder) { mViewHolder.tvSelectA.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_a), null, null, null); mViewHolder.tvSelectB.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_b), null, null, null); mViewHolder.tvSelectC.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_c), null, null, null); mViewHolder.tvSelectD.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_d), null, null, null); } private void judgeSelect(ViewHolder viewHolder, TextView text, String select, String rightSelect, int position) { //清楚之前的狀態 clearSelectState(viewHolder); if (select.equals(rightSelect)) { text.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_right), null, null, null); } else { text.setCompoundDrawables(getDrawableResource(R.drawable.ic_select_error), null, null, null); } } @TargetApi(Build.VERSION_CODES.LOLLIPOP) private Drawable getDrawableResource(int res) { Drawable drawable = mContext.getDrawable(res); drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight()); return drawable; } <span style="color:#cc0000;">private TextView getCheckTextView(ViewHolder mViewHolder, String rightSelect) { if ("A".equals(rightSelect)) { return mViewHolder.tvSelectA; } else if ("B".equals(rightSelect)) { return mViewHolder.tvSelectB; } else if ("C".equals(rightSelect)) { return mViewHolder.tvSelectC; } else if ("D".equals(rightSelect)) { return mViewHolder.tvSelectD; } return null; }</span> class ViewHolder { TextView tvTitle; TextView tvSelectA; TextView tvSelectB; TextView tvSelectC; TextView tvSelectD; } }

其中標紅的就是新添的代碼,加上這些後,問題就解決了,來看一下解決後的代碼運行情況:

總結:

最後來總結一下這個問題的解決思路吧:

首先就是需要在該填充器對應的實體類中添加一個選中的(check)欄位,在進行getview操作中,去根據這個check欄位來進行相應的操作,如過有值,則設定成對應的樣式,如果沒有值,則設定成沒有值得樣式,當然,在使用者點擊的時候,要及時的對該欄位進行賦值,類似的,像Listview中有checkbox也可以採用同樣的方法來進行解決。

以上所述是小編給大家介紹的探究Android中ListView複用導致布局錯亂的解決方案,希望對大家有所協助,如果大家有任何疑問請給我留言,小編會及時回複大家的。在此也非常感謝大家對雲棲社區網站的支援!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.