【问题标题】:custom listview adapter selected item increment textview自定义列表视图适配器选定的项目增量文本视图
【发布时间】:2015-09-30 08:35:19
【问题描述】:

我使用https://github.com/wdullaer/SwipeActionAdapter 滑动列表视图上的每个项目

一旦我轻扫其中一项,textview 文本将递增到一。如果我滚动列表的问题,文本视图将返回到每个默认值,即 0 并且一些隐藏项也在递增。

onswipe 事件代码:

switch (direction) {
   case SwipeDirections.DIRECTION_FAR_LEFT:
        selectedText = (TextView) getViewByPosition(position, getListView()).findViewById(R.id.txtNumber);
        selectedText.setText(String.valueOf(Integer.parseInt(selectedText.getText().toString()) + 1));
        break;

和适配器代码:

JSONArray jsonArray = null;
try {
    jsonArray = new JSONArray(data);

} catch (JSONException e) {
    e.printStackTrace();
}
String[] strArr = new String[jsonArray.length()];
ArrayList<String> arrayList = new ArrayList<String>();

for (int i = 0; i < jsonArray.length(); i++) {
    try {

        strArr[i] = jsonArray.getJSONObject(i).getString("name");
        arrayList.add(jsonArray.getString(i));

        stringAdapter = new ArrayAdapter<String>(
                this,
                R.layout.items,
                R.id.txtName,
                new ArrayList<String>(Arrays.asList(strArr))
        );

        setListAdapter(stringAdapter);
        stringAdapter.notifyDataSetChanged();


    } catch (JSONException e) {
        e.printStackTrace();
    }
}

items.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="100sp"
    android:background="@drawable/listview_style"
    android:padding="8dp"
    android:descendantFocusability="blocksDescendants">

    <ImageView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/imageView"
        android:src="@mipmap/ic_launcher"
        android:layout_centerVertical="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="New Text"
        android:id="@+id/txtName"
        android:textSize="20sp"
        android:gravity="center"
        android:ellipsize="none"
        android:singleLine="false"
        android:scrollHorizontally="false"
        android:layout_centerVertical="true"
        android:layout_marginLeft="20sp"
        android:layout_marginRight="20sp"
        android:layout_toRightOf="@+id/imageView"
        android:layout_toLeftOf="@+id/txtNumber"
        android:layout_toStartOf="@+id/txtNumber"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="0"
        android:id="@+id/txtNumber"
        android:textSize="25sp"
        android:layout_centerVertical="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="40dp"
        android:layout_marginEnd="40dp"
        />

</RelativeLayout>

我认为项目位置无效或视图无效。 知道如何解决这个问题。谢谢

更新 增量现在正常工作,但项目名称未填充。见附件

【问题讨论】:

    标签: android listview android-listview


    【解决方案1】:

    问题在于 listview 作弊。这是一个回收视图,所以发生的情况是您实际上只是拥有与您当前看到的 10 个视图相同的视图。当您滚动到足够远以至于视图消失时,它会再次显示为刚刚进入视图的视图。为此,它摆脱了旧视图,要求适配器将这个废弃的视图变成看起来像新视图的东西(这对于内存和快速创建视图来说非常棒)。

    这就是您的项目消失的原因,因为在您滚动离开后,列表视图会使用适配器回收视图。如果您真的想看到这一点,请尝试通过滑动将您的视图的可见性变为 INVISIBLE,然后您会注意到整个地方的视图都丢失了。因为它们是相同的视图。

    简而言之,滑动必须更改用于构建视图的数据。对视图本身的任何更改要么被抹去,要么弄乱其他视图(可见性和 .transform() 之类的东西通常不会被适配器重置),它们实际上又是同一个视图。

    public class SwipeActivity extends AppCompatActivity {
    
    SwipeActionAdapter mAdapter;
    
    private class YourCustomRowEntry {
        String displayString;
        int swipes;
    
        public YourCustomRowEntry( String displayString, int swipes) {
            this.swipes = swipes;
            this.displayString = displayString;
        }
    }
    
    private class Holder {
        public TextView textName, textNumber;
        public ImageView imageView;
        public Holder(TextView textName, TextView textNumber, ImageView imageView) {
            this.textName = textName;
            this.textNumber = textNumber;
            this.imageView = imageView;
        }
    }
    
    ArrayList<YourCustomRowEntry> mDataYouEditThatBacksTheAdapter = new ArrayList<>();
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_swipe);
    
        for (int i = 1; i <= 200; i++) {
            mDataYouEditThatBacksTheAdapter.add(new YourCustomRowEntry("Row " + i,0));
        }
    
        BaseAdapter customAdapter = new BaseAdapter() {
            @Override
            public int getCount() {
                return mDataYouEditThatBacksTheAdapter.size();
            }
    
            @Override
            public Object getItem(int position) {
                return mDataYouEditThatBacksTheAdapter.get(position);
            }
    
            @Override
            public long getItemId(int position) {
                return position;
            }
    
            @Override
            public View getView(int position, View convertView, ViewGroup parent) {
                View itemView;
                Holder viewHolder;
                if (convertView != null) {
                    itemView = convertView; //if you already made this view, and it's being recycled use that.
                    viewHolder = (Holder)convertView.getTag(); //And fetch the already findByViews things.
                }
                else {
                    //if this is the first time, inflate the view.
                    itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.items, parent, false);
                    TextView textName = (TextView)itemView.findViewById(R.id.txtName);
                    TextView textNumber = (TextView)itemView.findViewById(R.id.txtNumber);
                    ImageView imageView =  (ImageView)itemView.findViewById(R.id.imageView);
                    viewHolder = new Holder(textName,textNumber,imageView);
                    itemView.setTag(viewHolder); //store the data in the view's tag.
                }
                YourCustomRowEntry ycre = mDataYouEditThatBacksTheAdapter.get(position);
                viewHolder.textName.setText(ycre.displayString);
                viewHolder.textNumber.setText("" + ycre.swipes); // Gotta tell it that this is a string and not a resource.
                //You would also set the imageView from the saved set of data here too.
                return itemView;
            }
        };
    
        ListView listView = (ListView)findViewById(R.id.myActivitysListView);
    
        // Wrap your content in a SwipeActionAdapter
        mAdapter = new SwipeActionAdapter(customAdapter);
    
        // Pass a reference of your ListView to the SwipeActionAdapter
        mAdapter.setListView(listView);
    
        // Set the SwipeActionAdapter as the Adapter for your ListView
        listView.setAdapter(mAdapter);
    
        // Listen to swipes
        mAdapter.setSwipeActionListener(new SwipeActionAdapter.SwipeActionListener() {
            @Override
            public boolean hasActions(int position) {
                // All items can be swiped
                return true;
            }
    
            @Override
            public boolean shouldDismiss(int position, int direction) {
                // Only dismiss an item when swiping normal left
                return false;
                //return direction == SwipeDirections.DIRECTION_NORMAL_LEFT;
            }
    
            @Override
            public void onSwipe(int[] positionList, int[] directionList) {
                for (int i = 0; i < positionList.length; i++) {
                    int direction = directionList[i];
                    int position = positionList[i];
                    switch (direction) {
                        case SwipeDirections.DIRECTION_FAR_LEFT:
                            mDataYouEditThatBacksTheAdapter.get(position).swipes++; //add 1 to swipes;
                            mAdapter.notifyDataSetChanged();
                            break;
                        case SwipeDirections.DIRECTION_FAR_RIGHT:
                            mDataYouEditThatBacksTheAdapter.get(position).swipes--; //subtract 1 to swipes;
                            mAdapter.notifyDataSetChanged();
                            break;
                    }
                }
            }
        });
    
    
    }
    
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_swipe, menu);
        return true;
    }
    
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
    
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
    
        return super.onOptionsItemSelected(item);
    }
    

    }

    它的工作视频: https://youtu.be/6wPF2OOKu2U

    保存用于支持列表视图的数组。您需要拥有它,以便您可以更改它并让适配器构建新视图。 notifyDataSetChanged() 它从它保存的原始数据结构更新并重建视图。这意味着您需要修改该数据,而不是视图。这会正确地编写一个类并使用它来构建视图。

    【讨论】:

    • 没有。您需要使滑动更改用于构建列表的对象,而不是用于显示它的视图。
    • 谢谢,使用您的代码递增现在可以工作,但项目名称未填充。请查看我对我的问题的更新。附上截图。有没有办法使用简单的适配器而不是数组适配器?
    • 您需要自己实际实现适配器。字符串适配器有效,但一次只做一件事。所以另一个值没有正确给出正确的字符串。它只会让那些观点被给予和夸大,观点中重要的部分被替换,而另一部分则不被替换。这是麻烦而不是 StringAdapter 可以做的事情,它们真的很轻。给我一秒钟。
    • 我要做的不仅仅是指出一个错误。如果没有支持该结构的类和适当的完整实现的 BaseAdapter,很明显会有更多问题。一个真正合适的版本会做持有人模式。与其每次都使用 itemView.findViewById(R.id.txtName) 来查找这些视图,不如将它们存储在一个 holder 类中并将它们添加到视图的标签中。
    • 显然没有接受肯定的答案,我在其中添加了持有人模式。所以它对于滚动来说是超级轻量级​​的。
    猜你喜欢
    • 1970-01-01
    • 2011-12-31
    • 2012-10-15
    • 2015-12-20
    • 1970-01-01
    • 2012-02-21
    • 2014-05-02
    相关资源
    最近更新 更多