简体   繁体   English

自定义listview适配器所选项目增量textview

[英]custom listview adapter selected item increment textview

I used https://github.com/wdullaer/SwipeActionAdapter to swipe each items on listview 我使用https://github.com/wdullaer/SwipeActionAdapter滑动列表视图上的每个项目

once i swipe one of the item, textview text will increment to one. 一旦我滑动项目之一,textview文本将增加为1。 The problem if i will scroll the list, the textview will return to each default value which is 0 and some hidden items also incrementing. 问题是,如果我将滚动列表,则textview将返回到每个默认值0,并且某些隐藏项也在增加。

Code for onswipe event: 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;

and adapter code: 和适配器代码:

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 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>

i'm thinking of item position is not valid or view is not valid. 我认为项目位置无效或视图无效。 anyidea how to solve this. anyidea如何解决这个问题。 thanks 谢谢

UPDATE Incrementing now working properly, but item name is not populating. UPDATE增量现在可以正常工作,但是项名称没有填充。 See attached 见附件 项目名称未填充

The problem is that listview cheats. 问题是listview作弊。 It's a recycling view so what happens is that you actually just have the same like 10 views you are currently seeing. 这是一个回收视图,因此发生的事情就是您实际上拥有与当前所见的10个视图相同的视图。 When you scroll far enough that the view goes away, it appears again as the view that just came into view. 当您滚动到足以使视图消失时,它将再次显示为刚刚进入的视图。 To do this, it got rid of the old view, asked the adapter to make this trashed view into something that will look like the new view (which is awesome for memory and quick view creation). 为此,它摆脱了旧视图,要求适配器将已废弃的视图制作成看起来像新视图的外观(这对于存储和快速创建视图来说非常棒)。

This is why your items go away, because the views are recycled by the listview using the adapter after you scroll away. 这就是您的项目消失的原因,因为滚动后,列表视图会使用适配器回收列表视图。 If you really want to see this, try making swipe turn the visibility of your view to INVISIBLE, then you'll notice views all over the place just being missing. 如果您确实希望看到此图像,请尝试通过滑动将视图的可见性变为“不可见”,然后您会发现整个地方的视图都丢失了。 Because they are the same view. 因为他们是同一观点。

In short, swipe must change the data used to build the view. 简而言之,滑动必须更改用于构建视图的数据。 Any changes to the view itself will either be wiped away, or mess up the other views (things like visibility and .transform() are not often reset by adapters), which are really just the same view again. 对视图本身的任何更改都将被抹去,或者弄乱其他视图(例如,可视性和.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);
}

} }

Video of it working: https://youtu.be/6wPF2OOKu2U 正常工作的视频: https : //youtu.be/6wPF2OOKu2U

Save the array you use to back your listview. 保存用于支持列表视图的数组。 You need to have that so you can change it and get the Adapter to build new views. 您需要具有该属性,以便可以对其进行更改并获取适配器以构建新视图。 notifyDataSetChanged() and it updates the and rebuilds the views, from the original data structure it saved. notifyDataSetChanged()并根据保存的原始数据结构更新和重建视图。 Meaning you need to modify that data, not the view. 这意味着您需要修改该数据,而不是视图。 This properly writes a class and uses that to build the views. 这样可以正确地编写一个类,并使用该类来构建视图。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM