【问题标题】:Spinner value disappear after layout visibility is changed + specific flows更改布局可见性+特定流程后微调器值消失
【发布时间】:2015-09-02 16:19:54
【问题描述】:

我有一个自定义的list view 布局包含两个布局,称为上部和底部。

上部布局包含微调器、设置和删除按钮。 底部布局包含text view 和返回按钮。

默认底部布局为GONE状态,当用户点击set按钮upper时,布局为GONE,底部为VISIBLE(点击底部布局中的返回按钮将返回上底部返回)。

我的问题是微调器值在特定流程后消失:

流程 1:

  1. 添加两项
  2. 点击第一项上的SET按钮
  3. 删除第二项
  4. 点击第一项上的“返回”按钮

流程 2:

  1. 点击设置
  2. 旋转屏幕
  3. 点击返回

为了清楚起见,微调器值是存在的,如果将其下拉,您会找到名称(我的清单中有 android:configChanges="keyboardHidden|orientation|screenSize")。

那么,为什么微调器值在这些流之后消失了?

这是我的代码:

Names.java

public class Names
{
    private String name;
    private int nameIndex;
    private Boolean isNameOnTop;


    public Names()
    {
        name = "";
        isNameOnTop = true;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getNameIndex() {
        return nameIndex;
    }

    public void setNameIndex(int nameIndex) {
        this.nameIndex = nameIndex;
    }

    public Boolean getIsNameOnTop() {
        return isNameOnTop;
    }

    public void setIsNameOnTop(Boolean isNameOnTop) {
        this.isNameOnTop = isNameOnTop;
    }
}

MainActivity.Java

public class MainActivity extends Activity
{
    ArrayList<Names> namesArray = new ArrayList<>();
    ListView lvNames;
    ListviewAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lvNames = (ListView) findViewById(R.id.listView);
        adapter = new ListviewAdapter(this, namesArray);
        lvNames.setAdapter(adapter);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_add)
        {
            namesArray.add(new Names());
            adapter.notifyDataSetChanged();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

ListviewAdapter.java

public class ListviewAdapter extends BaseAdapter
{
    public Activity context;
    public LayoutInflater inflater;
    private ArrayList<Names> namesID;
    private boolean isDeleted;

    public ArrayList<Names> getNamesID() {
        return namesID;
    }

    public void setNamesID(ArrayList<Names> namesID) {
        this.namesID = namesID;
    }

    // Constructor
    public ListviewAdapter(Activity context, ArrayList<Names> names)
    {
        super();
        setNamesID(names);

        this.context = context;
        this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

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

    @Override
    public Names getItem(int position) {
        return getNamesID().get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }
public class ViewHolder
    {
        RelativeLayout relativeLayout_Upper;
        RelativeLayout relativeLayout_Bottom;

        Spinner spNames;
        Button btn_set, btn_remove, btn_back;
        TextView tvChosen;

        int index;
    }

    @Override
    public View getView(final int i, View view, final ViewGroup viewGroup) {
        final ViewHolder holder;
        if (view == null) {
            holder = new ViewHolder();
            view = inflater.inflate(R.layout.listview_row, null);

            holder.relativeLayout_Upper = (RelativeLayout) view.findViewById(R.id.lvRow_upper_layout);
            holder.relativeLayout_Bottom = (RelativeLayout) view.findViewById(R.id.lvRow_bottom_layout);
            holder.spNames = (Spinner) view.findViewById(R.id.spNames);
            holder.btn_set = (Button) view.findViewById(R.id.btn_set);
            holder.btn_remove = (Button) view.findViewById(R.id.btn_remove);
            holder.btn_back = (Button) view.findViewById(R.id.btn_back);
            holder.tvChosen = (TextView) view.findViewById(R.id.tv_chosen);
            view.setTag(holder);
        }
        else
            holder = (ViewHolder) view.getTag();
        holder.index = i;

        if (isDeleted)
        {
            holder.spNames.setSelection(getItem(holder.index).getNameIndex());
            holder.tvChosen.setText("Chosen: " + getItem(holder.index).getName());

            if (getItem(holder.index).getIsNameOnTop())
            {
                holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
                holder.relativeLayout_Bottom.setVisibility(View.GONE);
            }
            else
            {
                holder.relativeLayout_Upper.setVisibility(View.GONE);
                holder.relativeLayout_Bottom.setVisibility(View.VISIBLE);
            }
        }

        // pop spinner names
        String[] names = new String[]{"Tom", "Ben", "Gil", "Adam", "Moshe", "Adi", "Michael", "Yasmin", "Jessica", "Caroline", "Avi", "Yael"};
        final ArrayAdapter<String> spNamesAdapter = new ArrayAdapter<String>
                (view.getContext(), android.R.layout.simple_spinner_dropdown_item, names);
        spNamesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        holder.spNames.setAdapter(spNamesAdapter);

        holder.spNames.setSelection(getItem(holder.index).getNameIndex());
        holder.spNames.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                //holder.spNames.setTag(position);
                getItem(holder.index).setNameIndex(position);
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });

        holder.btn_set.setTag(i);
        holder.btn_set.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getItem(holder.index).setName(holder.spNames.getSelectedItem().toString());
                int position = (Integer) v.getTag();
                holder.tvChosen.setText("Chosen: " + getItem(position).getName());
                holder.relativeLayout_Upper.setVisibility(View.GONE);
                holder.relativeLayout_Bottom.setVisibility(View.VISIBLE);
                getItem(holder.index).setIsNameOnTop(false);
            }
        });

        // remove
        holder.btn_remove.setTag(i);
        holder.btn_remove.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = (Integer) v.getTag();
                namesID.remove(position);
                notifyDataSetChanged();
                isDeleted = true;
            }
        });

        // back
        holder.btn_back.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
                holder.relativeLayout_Bottom.setVisibility(View.GONE);
                getItem(holder.index).setIsNameOnTop(true);
            }
        });

        return view;
    }
}

activity_main.xml:仅包含ListView

upper_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Spinner
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/spNames" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="SET"
        android:id="@+id/btn_set" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="REMOVE"
        android:id="@+id/btn_remove" />
</LinearLayout>

bottom_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Chosen:"
        android:id="@+id/tv_chosen"
        android:layout_marginRight="20dp" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="BACK"
        android:id="@+id/btn_back" />
</LinearLayout>

listview_row.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/lvRow_upper_layout">

        <include
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            layout="@layout/upper_view"
            android:id="@+id/includeRow_register"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="0dp"
            android:layout_alignParentTop="true"
            android:layout_marginTop="0dp" />
    </RelativeLayout>

    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/lvRow_bottom_layout"
        android:visibility="gone">

        <include
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            layout="@layout/bottom_view"
            android:id="@+id/includeRow_showData"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="0dp"
            android:layout_alignParentTop="true"
            android:layout_marginTop="0dp" />
    </RelativeLayout>
</LinearLayout>

【问题讨论】:

  • 使用 INVISIBLE 代替消失
  • @meda,谢谢,但 INVISIBLE 这不是一个好主意,因为它保留了布局空间(导致行之间有空白)
  • 你的意思是说数据一直在spinner里面,你点进去就显示出来了吧??
  • @rj,是的,数据在那里。

标签: android listview spinner


【解决方案1】:

在您的 ListviewAdapter 中,更改:

    // back
    holder.btn_back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
            holder.relativeLayout_Bottom.setVisibility(View.GONE);
            getItem(holder.index).setIsNameOnTop(true);
        }
    });

到:

    // back
    holder.btn_back.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            holder.relativeLayout_Upper.setVisibility(View.VISIBLE);
            holder.relativeLayout_Bottom.setVisibility(View.GONE);
            getItem(holder.index).setIsNameOnTop(true);
            notifyDataSetChanged();
            // OR you can use this
            // holder.spNames.requestLayout();
        }
    });

【讨论】:

  • 非常感谢!我必须等待 23 小时才能获得赏金......你知道(请)解释为什么我需要在这里使用 notify 方法吗?
  • 好吧,我不会撒谎,但你的代码有点乱,所以我没有阅读每一行,但我注意到了这一行:holder.spNames.setSelection(getItem(holder.index).getNameIndex());。所以我当你删除第二个项目时,第二个项目的视图被第一个项目重用,这就是你的Spinner 丢失选择的原因。所以我用notifyDataSetChanged();触发getView()再次设置正确的选择。给我一分钟,我会检查我的猜测是否属实:D
  • 很遗憾,我的猜测是错误的,第一项仍然使用它的旧视图。实际上,我认为您的代码没有问题,但渲染系统(我再次猜测)因为在删除第二个项目后,按回,然后点击 Spinner,展开的列表仍然滚动到所选项目的正确位置,它只是折叠时不显示所选项目(这真的很奇怪!)。所以基本上我们通过notifyDataSetChanged()再次调用Spinner的setSelection来解决这个奇怪的问题。
  • :) 非常感谢!特别是为了你的诚实
  • 伙计,我终于明白了。确实是安卓的bug。你可以干脆不使用notifyDataSetChanged()(如果你关心性能)但是holder.spNames.requestLayout();
【解决方案2】:

每当您在 onOptionsItemSelected() 方法中单击“添加”时,都会将对象 new names() 添加到列表中,并且在 Names 类中,属性 name 的值设置为“” 我想这就是你在微调器中得到一个空项目的原因。

【讨论】:

  • 不不不,当用户添加新项目时,您会重置所有微调器。请下次检查自己
猜你喜欢
  • 1970-01-01
  • 2020-12-24
  • 1970-01-01
  • 2021-10-02
  • 1970-01-01
  • 2011-03-28
  • 1970-01-01
  • 2013-07-31
  • 1970-01-01
相关资源
最近更新 更多