【问题标题】:Selected Spinner Item getting replaced by First row in the spinner选定的微调器项目被微调器中的第一行替换
【发布时间】:2016-10-10 05:30:15
【问题描述】:

我一直在研究具有自定义下拉菜单布局的微调器。这是我的问题,当我选择时,假设下拉列表中的第二项,它被选中并且下拉列表关闭。当我重新打开下拉菜单时,第一行保持不变,但第二行被重命名为第一行。但它告诉我当我将 log.d 打印到控制台时,选择了 position:2。

这是我的代码,

    @Override
    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        return getCustomView(position, convertView, parent);
    }

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

        TextView textView = (TextView) convertView.inflate(getContext(), android.R.layout.simple_spinner_item, null);
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
        textView.setTextColor(ContextCompat.getColor(getActivity().getApplicationContext(), R.color.blue));
        if(list.getIsRecent()){
            textView.setText("Most Recent ");
        } else {
            textView.setText(list.get(position).getName());
        }
        return textView;
    }

    public View getCustomView(final int position, View convertView, ViewGroup parent) {
        boolean isRecent;
        isRecent = list.get(position).getIsRecent();
        if (convertView == null) {
                convertView = inflater.inflate(R.layout.custom_spinner_layout, parent, false);
                savedSearchName = (TextView) convertView
                        .findViewById(R.id.custom_spinner_layout_text_view);


            btnDelete = (ImageButton) convertView
                        .findViewById(R.id.custom_spinner_layout_button);

            relativeLayoutContainer = (RelativeLayout) convertView.findViewById(R.id.relativeLayout_item_name_container);
            relativeLayoutContainer.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.d(TAG,"relativeLayoutContainer: setOnClickListener: position"+position);
                    Method method = null;
                    if(mSavedSearchCriteriaSpinner != null) {
                        mSavedSearchCriteriaSpinner.setSelection(position);
                        try {
                            method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
                            method.setAccessible(true);
                            method.invoke(mSavedSearchCriteriaSpinner);
                        } catch (Exception  e) {
                            e.printStackTrace();
                        }
                    }
                }
            });


            if(isRecent){
                btnDelete.setVisibility(View.INVISIBLE);
                savedSearchName.setText(list.get(position).getName() + "MOSTRECENT");
            } else {
                savedSearchName.setText(list.get(position).getName());
                btnDelete.setVisibility(View.VISIBLE);

                btnDelete.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //AlertDialog
                });
            }

        }
        return convertView;
    }

截图: 初始微调器

微调器下拉

已选择位置 1:Qwerty

重新打开下拉菜单

不,这不是家庭作业问题。

【问题讨论】:

    标签: android android-spinner android-adapter


    【解决方案1】:

    getView() 中,您使用的 convertView 错误。这可以是null 或需要回收的旧视图。如果是null,你必须像你正在做的那样扩充一个新视图。如果不是,这是一个需要回收的旧项目(即你需要修改文本,你甚至不需要重新设置文本大小和颜色):

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView textView = convertView;
            if (convertView == null) {
                LayoutInflater li = LayoutInflater.from(parent);
                textView = (TextView) li.inflate(getContext(), android.R.layout.simple_spinner_item, null);
                textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
                textView.setTextColor(ContextCompat.getColor(getActivity().getApplicationContext(), R.color.blue));
            }
            if(list.getIsRecent()){
                textView.setText("Most Recent ");
            } else {
                textView.setText(list.get(position).getName());
            }
            return textView;
        }
    

    此外,getCustomView 将 btnDelete 和 savedSearchName 存储在对象的字段中,这可能会与旧内容混淆。此外,始终更新 convertView(现在,如果 convertView 不为空,则不要更新它):

    public View getCustomView(final int position, View convertView, ViewGroup parent) {
        boolean isRecent;
        isRecent = list.get(position).getIsRecent();
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.custom_spinner_layout, parent, false);
        }
    
        TextView savedSearchName = (TextView) convertView.findViewById(R.id.custom_spinner_layout_text_view);
    
    
        ImageButton btnDelete = (ImageButton) convertView.findViewById(R.id.custom_spinner_layout_button);
    
        RelativeLayout relativeLayoutContainer = (RelativeLayout) convertView.findViewById(R.id.relativeLayout_item_name_container);
        relativeLayoutContainer.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.d(TAG,"relativeLayoutContainer: setOnClickListener: position"+position);
                Method method = null;
                if(mSavedSearchCriteriaSpinner != null) {
                    mSavedSearchCriteriaSpinner.setSelection(position);
                    try {
                        method = Spinner.class.getDeclaredMethod("onDetachedFromWindow");
                        method.setAccessible(true);
                        method.invoke(mSavedSearchCriteriaSpinner);
                    } catch (Exception  e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    
    
        if(isRecent){
            btnDelete.setVisibility(View.INVISIBLE);
            savedSearchName.setText(list.get(position).getName() + "MOSTRECENT");
        } else {
            savedSearchName.setText(list.get(position).getName());
            btnDelete.setVisibility(View.VISIBLE);
    
            btnDelete.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                        //AlertDialog
                });
        }
    
        return convertView;
    }
    

    关于在字段中存储savedSearchNamebtnDelete,我猜是因为您想避免再次搜索它们。在这种情况下,我建议使用持有人模式。例如,请参阅以下Google guide 中的 Hold View Objects in a View Holder

    【讨论】:

    • 是的,我同意。但是下拉的问题仍然存在。当我选择 item1 时,再次重新打开下拉菜单时,item0 会重复两次。
    • 啊,对不起,我读的例子太快了。再次查看后,看起来可能是因为您将btnDeletesavedSearchName 存储在getCustomView() 的对象的字段中,这可能与旧内容混淆。此外,始终更新视图(现在,如果 convertView 不为空,则不要更新它)。我会更新答案。
    • 谢谢。是的,这就是问题所在。使用 ViewHolder 模式后,问题已解决。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多