为什么项目在Android GridView中滚动时更改顺序?

Ham*_*eni 12 android android-gridview

我在android中有一个GridView,我用从xml资源中检索的数据填充它.
例如,我在GridView中有15个项目按顺序放置.整体高度超过屏幕高度,所以我必须滚动以查看其余项目.
问题是当我向上滚动时,不可见行的顺序已经改变.这是一种神秘的行为,因为有时项目互相交换行.这是我的getView方法:

public class ImageAdapter extends BaseAdapter {
        public ImageAdapter(Context c, NodeList cuu) {
                cu = cuu;
        }
        public int getCount() {
                Log.d("Node Count",cu.getLength()+"");
                return cu.getLength();
        }
        public Object getItem(int position) {
                return position;
        }
        public long getItemId(int position) {
                return position;
        }
        public View getView(int position, View convertView, ViewGroup parent) {
                View myView = convertView;
                if (convertView == null) {
                    Node nd = cu.item(position);
                    Log.d("nodes","Pos: "+(position)+" Name: "+nd.getNodeName()+" Title: "+nd.getAttributes().getNamedItem("title").getTextContent());
                    int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id").getTextContent());
                    LayoutInflater li = getLayoutInflater();
                    myView = li.inflate(R.layout.grid_item, null);
                   ImageView imageView = (ImageView) myView.findViewById(R.id.grid_item_image);
                   myView.setLayoutParams(new GridView.LayoutParams(70, 100));
                   id.download(nd.getAttributes().getNamedItem("icon").getTextContent(),imageView);
                   TextView textView = (TextView) myView.findViewById(R.id.grid_item_text);
                   textView.setText(nd.getAttributes().getNamedItem("title").getTextContent());
                   myView.setTag((Object) catID);
                }else{
                    //Log.d("nodes","Pos: "+(position));
                }
                return myView;
        }
        private NodeList cu = null;
    }
Run Code Online (Sandbox Code Playgroud)

更新:嗯,这很奇怪.经过一些调试后,我注意到在GridView中,适配器跳过了第13个位置,这意味着它返回1而不是13,然后继续前进到14!(我猜13号运气不好!)

Abh*_*ane 11

public View getView(int position, View convertView, ViewGroup parent) {
    View view;
    if (convertView == null) {
        view= inflate your xml
    } else {
        view=convertView;
    }
    // all remaining code like 
    // view.findViewById(R.id.btn).setText("MyButton");                            
    // must be outside if-else
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*rog 7

如果这是您在getView方法中拥有的所有代码,那么您没有正确实现它:

public View getView(int position, View convertView, ViewGroup parent) {
        View myView = convertView;
        if (myView == null) {           
            Node nd = cu.item(position);
            int catID = Integer.parseInt(nd.getAttributes().getNamedItem("id")
                    .getTextContent());
            LayoutInflater li = getLayoutInflater();
            myView = li.inflate(R.layout.grid_item, null);
            myView.setLayoutParams(new GridView.LayoutParams(70, 100));         
            myView.setTag((Object) catID);
        } 
        Node nd = cu.item(position);
        Log.d("nodes", "Pos: " + (position) + " Name: " + nd.getNodeName()
                + " Title: "
                + nd.getAttributes().getNamedItem("title").getTextContent());
        ImageView imageView = (ImageView) myView
                .findViewById(R.id.grid_item_image);
        id.download(nd.getAttributes().getNamedItem("icon")
                .getTextContent(), imageView);
        TextView textView = (TextView) myView
                .findViewById(R.id.grid_item_text);
        textView.setText(nd.getAttributes().getNamedItem("title")
                .getTextContent());
        return myView;
    }
Run Code Online (Sandbox Code Playgroud)

我不知道上面的代码是否有效,你的有点奇怪.无论如何,我认为您看到它的正常行为是因为您在适配器中所做的只是填充第一个可见元素,然后当您因回收而向上和向下滚动时,适配器将重复使用完全相同的元素.在getView你应该:

  • 检查convertViewIS null:
    • 如果是null时候View为这个GridView元素充气了.您还可以使用持有者模式来缓存查找组合Views(而不是findViewById每次搜索)(您使用setTag元素作为膨胀的视图,但它是来自Node数据元素的一段数据?!?您打算如何处理它? ?!?)
    • 如果不是null你什么都不做(或者如果你实现了持有者模式,你会得到已经搜索过的标签Views)

这就是你应该在if/else语句中做的事情

  • 在上面的部分之后,您将填充Viewswith数据(因此它们保存该位置的适当数据).