码迷,mamicode.com
首页 > 其他好文 > 详细

ScrollView+Fragment+ListView嵌套ListView,麻麻再也不用担心我不会写嵌套

时间:2015-08-27 18:43:45      阅读:817      评论:0      收藏:0      [点我收藏+]

标签:android   listview嵌套   滑动冲突   

前言

之前写了一篇文章
android ListView/GridView与ScrollView嵌套的滑动冲突解决
介绍了如何解决ScrollView与AdapterView的嵌套,但是没有给出demo,那是因为那些代码比较多,而且是在手头的项目里,业务逻辑代码比较多,所以第一时间没有分享给大家。
今天终于有空把这些代码全部抽离了出来,并且去掉了业务代码和不必要的内容,以便大家能够更好的学习这个知识。
先贴一个效果图吧:
技术分享
之前项目里我是使用复写ScrollView的onInterceptTouchEvent方法来接管滑动事件的,而有小伙伴@liu告诉我可以使用

android:focusable="true"
android:focusableInTouchMode="true"

来设置ScrollView接管事件。于是本Demo就使用了这个方法,结果与前一种方法效果上没有发现区别。

ListView嵌套

前一篇文章只写了滑动冲突解决的问题,本文也不再多赘述了,而ListView与ListView的嵌套里面还有其他的一些极易出错之处。
其中ListView中数据混乱(不是指图片)的问题应该来说是最重要也是比较烦人的bug

我的第一层ListView 的Adapter:


public class QuestionCLAdapter extends MyBaseAdapter<QuestionCL> {

    //将下级Adapter放到上级Adapter中维护起来,防止new多个Adapter导致数据错乱
    private HashMap<Integer,QuestionCLOptionAdapter> ads = new HashMap<Integer, QuestionCLOptionAdapter>();

    public QuestionCLAdapter(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void setItems(List<QuestionCL> itemList) {
        // TODO Auto-generated method stub
        super.setItems(itemList);
        for (int i = 0; i < itemList.size(); i++) {
            ads.put(i,new QuestionCLOptionAdapter(context,itemList.get(i)));
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;
        if(convertView == null){
            convertView = inflater.inflate(R.layout.item_error_question_detail_c, null);
            holder = new ViewHolder();
            holder.ansysLayout = (LinearLayout) convertView.findViewById(R.id.layout_question_ansys);
            holder.questionTitleNum = (TextView) convertView.findViewById(R.id.tv_error_questioncl_titlenum);
            holder.questionclTxt = (TextView) convertView.findViewById(R.id.tv_error_questioncl_text);
            holder.questionRightTxt = (TextView) convertView.findViewById(R.id.tv_question_rightTxt);
            holder.questionansysTxt = (TextView) convertView.findViewById(R.id.txt_question_ansys);
            holder.questionclOptionsLv = (ListView) convertView.findViewById(R.id.lv_error_detail_c_option);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        final QuestionCL item = itemList.get(position);
        //初始化界面与监听器......
        if (item.isSubmit()) {
            holder.ansysLayout.setVisibility(View.VISIBLE);
            int temp = 65;
            for (int i = 0; i < item.getItems().size(); i++) {
                if (item.getItems().get(i).getIsTrue() == 1) {
                    temp += i;
                }
            }
            holder.questionRightTxt.setText((char)temp +"");
            Log.i(TAG, (char)temp +"");
            if (null != item.getAnalysis()) {
                holder.questionansysTxt.setText(Html.fromHtml(item.getAnalysis()));
            }
        }else {
            holder.ansysLayout.setVisibility(View.GONE);
        }

        holder.questionTitleNum.setText(item.getQustionid());
        holder.questionclTxt.setText(Html.fromHtml(item.getQustiontext()));
        if (null != ads.get(position)) {
            holder.questionclOptionsLv.setAdapter(ads.get(position));
        }
        return convertView;
    }

    public class ViewHolder{
        LinearLayout ansysLayout;
        TextView questionTitleNum;
        TextView questionRightTxt;
        TextView questionansysTxt;
        TextView questionclTxt;
        ListView questionclOptionsLv;
    }
}

应该来说是一个很经典很常规的自定义Adapter实现吧,继承的是自定义的虚基类。
可以看到我用一个容器作为类变量去管理其下级Adapter,在每次getView的时候都确保用的是它自己的数据而不是 重新new一个Adapter出来。

虚基类:

public abstract class MyBaseAdapter<T> extends BaseAdapter {
    protected Context context;
    protected String TAG = null;
    protected LayoutInflater inflater;
    protected List<T> itemList = new ArrayList<T>();

    public MyBaseAdapter(Context context) {
        this.context = context;
        inflater = LayoutInflater.from(context);
        TAG = this.getClass().getName();
    }

    /**
     * 判断数据是否为空
     *
     * @return 为空返回true,不为空返回false
     */
    @Override
    public boolean isEmpty() {
        return itemList.isEmpty();
    }

    /**
     * 在原有的数据上添加新数据
     *
     * @param itemList
     */
    public void addItems(List<T> itemList) {
        this.itemList.addAll(itemList);
        notifyDataSetChanged();
    }

    /**
     * 设置为新的数据,旧数据会被清空
     *
     * @param itemList
     */
    public void setItems(List<T> itemList) {
        this.itemList.clear();
        this.itemList = itemList;
        notifyDataSetChanged();
    }

    /**
     * 清空数据
     */
    public void clearItems() {
        itemList.clear();
        notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        return itemList.size();
    }

    @Override
    public Object getItem(int position) {
        return itemList.get(position);
    }

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

    @Override
    abstract public View getView(int position, View view, ViewGroup viewGroup);
}

下级Adapter:

public class QuestionCLOptionAdapter extends MyBaseAdapter<QuestionOptionInfo> {

    /** 当前被选中的位置 -1表示未作答 **/
    private int selected;
    /** 答案是否已提交  **/
    private boolean isSubmmit;

    private QuestionCL parentItem;

    /** -1未作答,0答错,1答对   **/
    private int isrightAnswered;

    public QuestionCLOptionAdapter(Context context) {
        super(context);
        selected = -1;
        isSubmmit = false;
        isrightAnswered = -1;
    }   

    public QuestionCLOptionAdapter(Context context,QuestionCL parentItem) {
        super(context);
        selected = -1;
        isSubmmit = parentItem.isSubmit();
        this.parentItem = parentItem;
        this.setItems(parentItem.getItems());
        isrightAnswered = -1;
    }

    @Override
    public View getView(final int position, View convertView, final ViewGroup parent) {
        // TODO Auto-generated method stub
        ViewHolder holder = null;
        if(convertView == null){
            convertView = inflater.inflate(R.layout.item_list_error_question_option, null);
            holder = new ViewHolder();
            holder.rightImg = (ImageView) convertView.findViewById(R.id.img_question_option_true);
            holder.wrongImg = (ImageView) convertView.findViewById(R.id.img_question_option_false);
            holder.checkBox = (CheckBox) convertView.findViewById(R.id.cb_question_option_select);
            holder.layout = (LinearLayout) convertView.findViewById(R.id.layout_question_option);
            holder.optionTitle = (TextView) convertView.findViewById(R.id.tv_question_option_title);
            holder.optionTxt = (TextView) convertView.findViewById(R.id.tv_question_option_text);
            convertView.setTag(holder);
        }else{
            holder = (ViewHolder)convertView.getTag();
        }
        final QuestionOptionInfo item = itemList.get(position);
        //初始化界面与监听器......
        holder.checkBox.setVisibility(View.VISIBLE);
        int num = item.getOptionId()+65;
        holder.optionTitle.setText((char)num+".");
        holder.optionTxt.setText(Html.fromHtml(item.getOptionText()));
        holder.layout.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                if (isSubmmit) {
                    return;
                }else {
                    if (position == selected) {
                        selected = -1;
                    } else {
                        selected = position;
                        isSubmmit = true;
                        if (null != parentItem && !parentItem.isSubmit() && isSubmmit) {
                            parentItem.setSubmit(true);
                        }
                        QuestionCLOptionAdapter.this.notifyDataSetChanged();
                    }
                }
            }
        });
        if (position == selected) {
            holder.checkBox.setChecked(true);
        } else {
            holder.checkBox.setChecked(false);
        }

        //判断是否答对
        if (isSubmmit) {
            if (position == selected && item.getIsTrue() == 1) {
                // 答对了
                holder.rightImg.setVisibility(View.VISIBLE);
//              Log.i(TAG, "true!!!!!!!!!!!!!!!!");
            } else if (position == selected) {
                // 答错了
                holder.wrongImg.setVisibility(View.VISIBLE);
//              Log.i(TAG, "false!!!!!!!!!!!!!!!");
            } else {
                holder.rightImg.setVisibility(View.GONE);
                holder.wrongImg.setVisibility(View.GONE);
            }
        }
        return convertView;
    }

    /** -1未作答,0答错,1答对
     * @return the isrightAnswered
     */
    public int getIsrightAnswered() {
        if (isSubmmit) {
            return isrightAnswered;
        }else {
            return -1;
        }
    }

    /**-1未作答,0答错,1答对
     * @param isrightAnswered the isrightAnswered to set
     */
    public void setIsrightAnswered(int isrightAnswered) {
        if (isSubmmit) {
            this.isrightAnswered = isrightAnswered;
        }
    }

    public class ViewHolder{
        CheckBox checkBox;
        ImageView rightImg;
        ImageView wrongImg;
        LinearLayout layout;
        TextView optionTitle;
        TextView optionTxt;
    }
}

两个Adapter之间 你可以用类变量进行数据交互,可以通过bean的某一个值进行交互判断。在这里我都有用到。

Activity

public class MainActivity extends FragmentActivity {
    private Bundle bundle;
    private ScrollView sv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        sv = (ScrollView) findViewById(R.id.sv_main);
        setFragment(new QuestionFragment(),initData());
        //显示在顶端
        sv.smoothScrollTo(0,0);
    }

    private QuestionC initData(){
        // 生成测试数据
        QuestionC questionC = new QuestionC();
        //塞大题题干等信息
        questionC.setMaintext("从前有座山,山里有座庙,庙里有个老和尚在讲故事。");
        List<QuestionCL> cList = new ArrayList<QuestionCL>();
        //2小题
        for (int i = 1; i < 3; i++) {
            QuestionCL cltemp = new QuestionCL();
            //塞小题题干等信息
            cltemp.setQustionid(i+"");
            cltemp.setQustiontext("老和尚"+i+"是谁?");
            cltemp.setRightitem("释永信"+i+i);
            List<QuestionOptionInfo> optionList = new ArrayList<QuestionOptionInfo>();
            //5选项
            for (int j = 1; j < 6; j++) {
                QuestionOptionInfo otemp = new QuestionOptionInfo();
                //塞选项Id,String等
                otemp.setOptionId(j-1);
                otemp.setOptionText("释永信"+i+j);
                if (otemp.getOptionText().equals(cltemp.getRightitem())) {
                    otemp.setIsTrue(1);
                }else {
                    otemp.setIsTrue(0);
                }
                optionList.add(otemp);
            }
            cltemp.setItems(optionList);
            cList.add(cltemp);
        }
        questionC.setQuestioncls((ArrayList<QuestionCL>) cList);
        return questionC;
    }

    private void setFragment(Fragment fragment,QuestionC question) {
        FragmentManager fragManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragManager.beginTransaction();
        bundle = new Bundle();
        bundle.putSerializable("bean", question);
        fragment.setArguments(bundle);
        transaction.replace(R.id.layout_fragment, fragment);
        if (!MainActivity.this.isFinishing()) {
            transaction.commitAllowingStateLoss();
        }
    }
}

Fragment

public class QuestionFragment extends Fragment{
    private Context context;
    /** 实体  **/
    private QuestionC questionC;
    /** 大题干文本   **/
    private TextView questionTxt;
    /** 小题ListView  **/
    private ListView xiaotiLv;
    private QuestionCLAdapter ad;

    @Override
    public View onCreateView(LayoutInflater inflater,
        ViewGroup container, Bundle savedInstanceState) {
        context = getActivity();
        return inflater.inflate(R.layout.fragment_error_detail_c, container,false);
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        initWidget();
        initData();
    }

    public void onAttach(Activity activity) {
        // TODO Auto-generated method stub
        super.onAttach(activity);
        getIntentData();
    }

    protected void getIntentData() {
        //取得Bean等信息
        if (null != getArguments()) {
            questionC = (QuestionC) getArguments().get("bean");
        };
    }

    protected void initData() {
        ad = new QuestionCLAdapter(context);
        if (null == questionC) {
            Log.i("questionC", "no data!!!");
        } else {
            ad.setItems(questionC.getQuestioncls());
            xiaotiLv.setAdapter(ad);
            questionTxt.setText(Html.fromHtml(questionC.getMaintext()));
        }
    }

    protected void initWidget() {
        questionTxt = (TextView) getView().findViewById(R.id.tv_error_question_txt);
        xiaotiLv = (ListView) getView().findViewById(R.id.lv_error_detail_c_secondary_question);
    }

}

补上activity的布局

<ScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/sv_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#f3f3f3"    
    android:scrollbars="none"
    android:focusable="true"
    android:focusableInTouchMode="true" 
    tools:context="com.ysdemo.nestdemo.MainActivity" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content" >

        <FrameLayout
            android:id="@+id/layout_fragment"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>

</ScrollView >

Demo下载地址
积分不够的小伙伴可以留下邮箱,我会另外发。

版权声明:本文为YS尘笑原创文章,未经本人允许不得转载。

ScrollView+Fragment+ListView嵌套ListView,麻麻再也不用担心我不会写嵌套

标签:android   listview嵌套   滑动冲突   

原文地址:http://blog.csdn.net/yaosongqwe/article/details/48030359

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!