Android电商类项目添加多组物品规格

前两年互联网行业火热的时候,大多数移动端的项目以电商为主,而电商中添加商品又是一个不可缺少的环节,前段时间做了一个小型的电商项目,其中有一个添加物品规格的需求,可以看下面的展示图。

nullpoint Exception

限于图片上传大小,尺寸略小,并只能展示添加和删除的部分逻辑,感兴趣的同学可以下载项目运行看下效果;
github地址:https://github.com/LzyChonger/CreateGoodsSpec

业务需求分析

业务需求是在界面上输入一个规格名称,下面再出现规格的具体值【举个例子:输入: 颜色 — 红色,黄色等】,并继续在下面展示出此规格的价钱和库存(ps:或者其他的任何参数),规格可以删除,并且对应的价格库存也要删除,点击保存将数据回传到前一个商品添加界面,再次点击进来数据要回显,点击返回按钮将数据清空,最后服务器要求将数据以json的形式传递过去。

难点在于添加两个及两个以上规格的时候,下面要求物品规格必须要去重组合起来,【举个例子: 尺寸(xl):颜色(red), 尺寸(xxl):颜色(yellow) ,尺寸(xxl):颜色(red),尺寸(xxl):颜色(yellow)】并输入相应的价钱和库存,并将规格的参数携带回到上一个界面。(也有可能是三组以上的参数 [手动滑稽])

demo中便于展示,省略了商品添加界面,只做了规格添加,并把数据转换成json传到前一个界面,放在TextView中展示。

技术分析

我的思路首先是想到,需要用两个RecylerView,上面添加商品的一个,下面展示组合的是一个,需要将上面手动输入的数据拿到,通过排列组合去重(技术有限只能想到有遍历的方式,大佬们有优秀的算法烦请指点[手动膜拜大佬]),展示到下面,一些对应删除操作和添加操作需要用到接口回调。

代码展示

限于篇幅这里只展示主要代码逻辑
首先MainActivity.java,没有复杂的东西,都是常规代码,JSON用的是fastjson,布局文件就不贴了,一个Button,一个TextView;

public class MainActivity extends AppCompatActivity {
    private static final int SELECT_SPEC = 102;

    private Button mBtn;
    private TextView mTv_goods_spec;
    private List<StoreManagerListEntity.GuigesEntity> mGuiges;
    private List<StoreManagerListEntity.SkuListEntity> mGood_spec;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mBtn = (Button) findViewById(R.id.btn);
        mTv_goods_spec = (TextView) findViewById(R.id.tv_goods_spec);

        mBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, GoodsSpecActicity.class);
                //做非空判断,回显数据
                if (mGood_spec != null) {
                    intent.putExtra("good_spec", (Serializable) mGood_spec);
                }
                if(mGuiges !=null){
                    intent.putExtra("good_guige", (Serializable) mGuiges);
                }
                startActivityForResult(intent, SELECT_SPEC);
            }
        });

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode != RESULT_OK) {
            return;
        }
        switch (requestCode) {
            case SELECT_SPEC:
                mGood_spec = (List<StoreManagerListEntity.SkuListEntity>) data.getSerializableExtra("good_spec");
                mGuiges = (List<StoreManagerListEntity.GuigesEntity>) data.getSerializableExtra("good_guige");
                if (mGood_spec == null || mGood_spec.size() == 0) {
                    mTv_goods_spec.setHint("未填写");
                } else {
                    mTv_goods_spec.setText("Guiges:" + JSON.toJSONString(mGuiges)
                            + "\nGood_spec:" + JSON.toJSONString(mGood_spec));
                }
                break;
            default:
        }
    }
}

然后是实体类,实体结构非常重要,所以贴一下代码,偷懒用了Serializable ,项目的话建议用Parcelable

public class StoreManagerListEntity implements Serializable {

    public static class SkuListEntity implements Serializable {
        /*
        "sku_id": "7",
        "spec": "绿色:10寸",
        "sku_name": "颜色,尺码",
        "price": "10.00",
        "stock": "0"库存
         */
        public String sku_id;
        public String spec;
        public String sku_name;
        public String price;
        public String stock;
    }

    public static class GuigesEntity implements Serializable {
        /*
        "title": "颜色",
        "guigeArray": ["绿色", "红色"]
         */
        public String title;
        public List<String> guigeArray= new ArrayList<>();
    }

}

添加商品规格的主界面,交互了两个RecylerView的数据,布局文件顺便也贴出来,一些资源文件就不贴了。

public class GoodsSpecActicity extends AppCompatActivity implements View.OnClickListener {
    private RelativeLayout mRlBack;
    private TextView mTvTitle;
    private TextView mTvRight;
    private RelativeLayout mRlRight;
    private EditText mEtName;
    private TextView mTvAdd;
    private View mView01;
    private RecyclerView mRvSpec;
    private RecyclerView mRvPrice;

    private List<StoreManagerListEntity.GuigesEntity> mSpecNameList = new ArrayList<>();
    private List<StoreManagerListEntity.SkuListEntity> mSpecPriceList = new ArrayList<>();
    private GoodsSpecTypeAdapter mSpecTypeAdapter;
    private GoodsSpecTypeNumberAdapter mNumberAdapter;

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

        initView();
    }

    private void initView() {
        mRlBack = (RelativeLayout) findViewById(R.id.rl_back);
        mTvTitle = (TextView) findViewById(R.id.tv_title);
        mTvRight = (TextView) findViewById(R.id.tv_right);
        mRlRight = (RelativeLayout) findViewById(R.id.rl_right);
        mEtName = (EditText) findViewById(R.id.et_name);
        mTvAdd = (TextView) findViewById(R.id.tv_add);
        mView01 = (View) findViewById(R.id.view01);
        mRvSpec = (RecyclerView) findViewById(R.id.rv_spec);
        mRvPrice = (RecyclerView) findViewById(R.id.rv_price);

        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRvSpec.setLayoutManager(layoutManager);
        mRvSpec.setHasFixedSize(true);
        LinearLayoutManager layoutManager1 = new LinearLayoutManager(this);
        mRvPrice.setLayoutManager(layoutManager1);
        mRvPrice.setHasFixedSize(true);

        mRlBack.setOnClickListener(this);
        mTvAdd.setOnClickListener(this);
        mRlRight.setOnClickListener(this);

        mTvTitle.setText("商品规格");
        mRlRight.setVisibility(View.VISIBLE);
        mTvRight.setText("完成");
        mSpecTypeAdapter = new GoodsSpecTypeAdapter(this, mSpecNameList);
        mRvSpec.setAdapter(mSpecTypeAdapter);

        mNumberAdapter = new GoodsSpecTypeNumberAdapter(this, mSpecPriceList);
        mRvPrice.setAdapter(mNumberAdapter);
        mRvPrice.setNestedScrollingEnabled(false);
        mSpecTypeAdapter.setAddItem(new RecylerViewAddItemListener() {
            @Override
            public void onAddItemListener(List<String> entity, int position) {
                mSpecPriceList.clear();
                String sku_name = "";
                for (int i = 0; i < mSpecNameList.size(); i++) {
                    if (i < mSpecNameList.size() - 1) {
                        sku_name = sku_name + mSpecNameList.get(i).title + ",";
                    } else {
                        sku_name = sku_name + mSpecNameList.get(i).title;
                    }
                }
                if (entity != null) {
                    for (int i = 0; i < entity.size(); i++) {
                        StoreManagerListEntity.SkuListEntity serverEntity = new StoreManagerListEntity.SkuListEntity();
                        serverEntity.spec = entity.get(i);
                        serverEntity.sku_name = sku_name;
                        mSpecPriceList.add(serverEntity);
                    }
                }
                mNumberAdapter.notifyDataSetChanged();
            }
        });

        List<StoreManagerListEntity.GuigesEntity> good_guige = (List<StoreManagerListEntity.GuigesEntity>) getIntent().getSerializableExtra("good_guige");
        if (good_guige != null) {
            mSpecNameList.addAll(good_guige);
        }
        List<StoreManagerListEntity.SkuListEntity> good_spec = (List<StoreManagerListEntity.SkuListEntity>) getIntent().getSerializableExtra("good_spec");
        if (good_spec != null) {
            mSpecPriceList.addAll(good_spec);
        }

    }


    private void toComplete() {
        for (int i = 0; i < mSpecPriceList.size(); i++) {
            if (TextUtils.isEmpty(mSpecPriceList.get(i).price)) {
                UIUtil.toastShort(this, "请输入价格");
                return;
            }
            if (TextUtils.isEmpty(mSpecPriceList.get(i).stock)) {
                UIUtil.toastShort(this, "请输入库存");
                return;
            }
        }
        Intent intent = new Intent();
        intent.putExtra("good_spec", (Serializable) mSpecPriceList);
        intent.putExtra("good_guige", (Serializable) mSpecNameList);
        setResult(RESULT_OK, intent);
        finish();
    }

    private void addList() {

        String name = mEtName.getText().toString().trim();
        if (!TextUtils.isEmpty(name)) {

            StoreManagerListEntity.GuigesEntity entity = new StoreManagerListEntity.GuigesEntity();
            entity.title = name;
            mSpecNameList.add(entity);
            mSpecTypeAdapter.notifyDataSetChanged();
            mEtName.setText("");
            ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
                    this.getCurrentFocus().getWindowToken(),
                    InputMethodManager.HIDE_NOT_ALWAYS);
        } else {
            UIUtil.toastShort(this, "请输入规格名称");
        }
    }


    public void saveEditData(int position, String type, String str) {

        try {
            if ("1".equals(type)) {
                mSpecPriceList.get((position - 1) / 100).price = str;
            } else if ("2".equals(type)) {
                mSpecPriceList.get((position - 2) / 100).stock = str;
            }

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

    @Override
    public void onClick(View v) {

        switch (v.getId()) {
            case R.id.rl_back:
                UIUtil.showConfirm(this, "返回将清空数据,是否确定?", new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mSpecPriceList.clear();
                        mSpecNameList.clear();
                        Intent intent = new Intent();
                        intent.putExtra("good_spec", (Serializable) mSpecPriceList);
                        intent.putExtra("good_guige", (Serializable) mSpecNameList);
                        setResult(RESULT_OK, intent);
                        finish();
                    }
                });
                break;
            case R.id.tv_add:
                addList();
                break;
            case R.id.rl_right:
                toComplete();
                break;
            default:
                break;
        }

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

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">


            <RelativeLayout
                android:id="@+id/rl_title"
                android:layout_width="match_parent"
                android:layout_height="48dp"
                android:background="#F3F3F3">

                <RelativeLayout
                    android:id="@+id/rl_back"
                    android:layout_width="48dp"
                    android:layout_height="match_parent">

                    <ImageView
                        android:layout_width="17dp"
                        android:layout_height="17dp"
                        android:layout_centerInParent="true"
                        android:src="@mipmap/icon_left" />
                </RelativeLayout>

                <TextView
                    android:id="@+id/tv_title"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_centerInParent="true"
                    android:text="Title"
                    android:textColor="#333333"
                    android:textSize="16sp" />

                <RelativeLayout
                    android:id="@+id/rl_right"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:layout_alignParentRight="true"
                    android:layout_marginRight="15dp"
                    android:visibility="gone">

                    <TextView
                        android:id="@+id/tv_right"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_centerInParent="true"
                        android:text="right"
                        android:textColor="#333333" />
                </RelativeLayout>

            </RelativeLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="50dp"
                android:orientation="horizontal"
                android:paddingLeft="15dp"
                android:paddingRight="15dp">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:text="规格名称"
                    android:textColor="#333333" />

                <EditText
                    android:id="@+id/et_name"
                    android:layout_width="match_parent"
                    android:layout_height="32dp"
                    android:layout_marginLeft="15dp"
                    android:layout_weight="1"
                    android:background="@drawable/shape_black_rect"

                    android:gravity="center_vertical"
                    android:imeOptions="actionDone"
                    android:inputType="text"
                    android:paddingLeft="5dp"
                    android:singleLine="true"
                    android:textSize="14sp" />

                <TextView
                    android:id="@+id/tv_add"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="15dp"
                    android:background="@drawable/shape_red_fill"
                    android:gravity="center"
                    android:paddingBottom="2dp"
                    android:paddingLeft="7dp"
                    android:paddingRight="7dp"
                    android:paddingTop="2dp"
                    android:text="添加"
                    android:textColor="#fff" />

            </LinearLayout>

            <View
                android:id="@+id/view01"
                android:layout_width="match_parent"
                android:layout_height="10dp"
                android:background="#e6e6e6"
                android:visibility="gone" />


            <android.support.v7.widget.RecyclerView
                android:id="@+id/rv_spec"
                android:layout_width="match_parent"
                android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>

            <View
                android:layout_width="match_parent"
                android:layout_height="10dp"
                android:background="#e6e6e6" />

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:paddingLeft="15dp"
                android:paddingRight="15dp">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="45dp"
                    android:gravity="center_vertical"
                    android:text="价格/库存"
                    android:textColor="#333333" />

                <View
                    android:layout_width="match_parent"
                    android:layout_height="1px"
                    android:background="#e6e6e6" />

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="您需要选择相应的销售属性,才能组合完整的规格信息"
                    android:textColor="#999" />

            </LinearLayout>

            <View
                android:layout_width="match_parent"
                android:layout_height="10dp"
                android:background="#e6e6e6" />

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent">


                <android.support.v7.widget.RecyclerView
                    android:id="@+id/rv_price"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"></android.support.v7.widget.RecyclerView>

            </RelativeLayout>
        </LinearLayout>
    </ScrollView>

</RelativeLayout>

后面重头戏来了,首先是上面的RecylerView的适配器

public class GoodsSpecTypeAdapter extends BaseAdapter<StoreManagerListEntity.GuigesEntity, GoodsSpecTypeAdapter.GoodsSpecTypeViewHolder> {

    private RecylerViewAddItemListener mAddItemListener;
    public GoodsSpecTypeInfoAdapter mInfoAdapter;

    public GoodsSpecTypeAdapter(Context context, List<StoreManagerListEntity.GuigesEntity> list) {
        super(context, list);
    }

    @Override
    public GoodsSpecTypeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new GoodsSpecTypeViewHolder(mInflater.inflate(R.layout.item_goods_spec_type, null));
    }

    @Override
    public void onBindViewHolder(final GoodsSpecTypeViewHolder holder, final int position) {
        final StoreManagerListEntity.GuigesEntity item = getItem(position);
        holder.mTv_type_name.setText(item.title);
        mInfoAdapter = new GoodsSpecTypeInfoAdapter(mContext, item.guigeArray, position);
        holder.mRv_spec_size.setAdapter(mInfoAdapter);

        mInfoAdapter.setOnItemDeleteListener(new ImageRecylerReduceItemListener() {
            @Override
            public void onReduceItemListener(int position) {
                List<String> list = bindAnotherRecyler1();
                mAddItemListener.onAddItemListener(list, position);
            }
        });

        holder.mEt_size.setOnEditorActionListener(new TextView.OnEditorActionListener() {
            @Override
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                if (actionId == EditorInfo.IME_ACTION_DONE) {
                    String size = holder.mEt_size.getText().toString().trim();
                    if (!TextUtils.isEmpty(size)) {
                        mInfoAdapter = new GoodsSpecTypeInfoAdapter(mContext, item.guigeArray /*mTypeList*/, position);
                        item.guigeArray.add(size);
                        List<String> list = bindAnotherRecyler1();
                        holder.mRv_spec_size.setAdapter(mInfoAdapter);
                        mAddItemListener.onAddItemListener(list, position);
                        holder.mEt_size.setText("");

                        mInfoAdapter.setOnItemDeleteListener(new ImageRecylerReduceItemListener() {
                            @Override
                            public void onReduceItemListener(int position) {

                                List<String> list = bindAnotherRecyler1();
                                mAddItemListener.onAddItemListener(list, position);
                            }
                        });
                    } else {
                        UIUtil.toastShort(mContext, "请输入规格参数");
                    }
                }
                return false;
            }
        });


    }

    private List<String> bindAnotherRecyler1() {
        int b = 0;
        if (mItems.size() > 0) {
            List<String> copylist = new ArrayList<>();
            for (int a = 0; a < mItems.size(); a++) {
                if (mItems.get(a).guigeArray.size() != 0) {
                    copylist.addAll(mItems.get(a).guigeArray);
                    b = a;
                    break;
                }
            }
            if (copylist.size() > 0) {
                List<String> L0 = new ArrayList<>();
                L0.addAll(copylist);
                for (int i = b + 1; i < mItems.size(); i++) {
                    List<String> L1 = mItems.get(i).guigeArray;

                    List<String> list = new ArrayList<>();
                    for (int j = 0; j < L0.size(); j++) {
                        for (int z = 0; z < L1.size(); z++) {
                            String s = L0.get(j) + ":" + L1.get(z);
                            list.add(s);
                        }
                    }
                    if (list.size() != 0) {
                        L0 = list;
                    }
                }
                return L0;
            }
        }
        return null;
    }

    class GoodsSpecTypeViewHolder extends RecyclerView.ViewHolder {

        private final RecyclerView mRv_spec_size;
        private final EditText mEt_size;
        private final TextView mTv_type_name;

        public GoodsSpecTypeViewHolder(View itemView) {
            super(itemView);
            mTv_type_name = itemView.findViewById(R.id.tv_type_name);
            mEt_size = itemView.findViewById(R.id.et_size);
            mRv_spec_size = itemView.findViewById(R.id.rv_spec_size);
            GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 3);
            gridLayoutManager.setOrientation(LinearLayout.VERTICAL);
            mRv_spec_size.setLayoutManager(gridLayoutManager);
            mRv_spec_size.setHasFixedSize(true);
        }
    }

    public void setAddItem(RecylerViewAddItemListener addItemListener) {
        mAddItemListener = addItemListener;
    }

重点就在于bindAnotherRecyler1()这个方法,在数据输入后,通过EditText的监听或者点击事件来组装数据,因为在这个适配器中,是数据的来源,所以在这里拿到数据并组装数据,再传到另一个适配器中可以直接显示,首先做一个判断增加程序的健壮性,第一次遍历中,新建一个copylist,遍历此适配器的规格数组,同事不影响适配器的数据展示;在用copylist的数据进行双重循环遍历组装数据,并做一些空数据处理,":"是为了后台存储数据做的规则。

   private List<String> bindAnotherRecyler1() {
        int b = 0;
        if (mItems.size() > 0) {
            List<String> copylist = new ArrayList<>();
            for (int a = 0; a < mItems.size(); a++) {
                if (mItems.get(a).guigeArray.size() != 0) {
                    copylist.addAll(mItems.get(a).guigeArray);
                    b = a;
                    break;
                }
            }
            if (copylist.size() > 0) {
                List<String> L0 = new ArrayList<>();
                L0.addAll(copylist);
                for (int i = b + 1; i < mItems.size(); i++) {
                    List<String> L1 = mItems.get(i).guigeArray;

                    List<String> list = new ArrayList<>();
                    for (int j = 0; j < L0.size(); j++) {
                        for (int z = 0; z < L1.size(); z++) {
                            String s = L0.get(j) + ":" + L1.get(z);
                            list.add(s);
                        }
                    }
                    if (list.size() != 0) {
                        L0 = list;
                    }
                }
                return L0;
            }
        }
        return null;
    }

在这个适配器里面嵌套了一个新的适配器,是便于规格删除操作和展示用的,以前遇到这种问题都是用这种方式来写~~~(>_<)~~~,如果众大佬有更好的方式,希望能帮我指出来去改正。

public class GoodsSpecTypeInfoAdapter extends RecyclerView.Adapter<GoodsSpecTypeInfoAdapter.GoodsSpecTypeViewHolder> {
    private final Context mContext;
    private final List<String> getItem;
    protected LayoutInflater mInflater;
    private int mPosition;
    private ImageRecylerReduceItemListener mItemDeleteListener;

    public GoodsSpecTypeInfoAdapter(Context context,List<String> list, int position) {
        mContext = context;
        getItem = list;
        mInflater = LayoutInflater.from(context);
        mPosition = position;
    }

    @Override
    public GoodsSpecTypeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new GoodsSpecTypeViewHolder(mInflater.inflate(R.layout.item_goods_spec_info, parent, false));
    }

    @Override
    public void onBindViewHolder(GoodsSpecTypeViewHolder holder, final int position) {
        holder.mRl_del.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                getItem.remove(position);
                notifyDataSetChanged();
                mItemDeleteListener.onReduceItemListener(position);
            }
        });
        String item = getItem.get(position);
        if (!TextUtils.isEmpty(item)) {
            holder.mTv_size.setVisibility(View.VISIBLE);
            holder.mTv_size.setText(item);
        } else {
            holder.mTv_size.setVisibility(View.GONE);
        }

    }

    @Override
    public int getItemCount() {
        try {
            if (getItem != null && getItem.size() > 0) {
                return getItem.size();
            } else {
                return 0;
            }
        } catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    class GoodsSpecTypeViewHolder extends RecyclerView.ViewHolder {

        private final TextView mTv_size;
        private final RelativeLayout mRl_del;
        private final ImageView mIv_del;

        public GoodsSpecTypeViewHolder(View itemView) {
            super(itemView);
            mTv_size = itemView.findViewById(R.id.tv_size);
            mRl_del = itemView.findViewById(R.id.rl_del);
            mIv_del = itemView.findViewById(R.id.iv_del);
        }
    }

    public void setOnItemDeleteListener(ImageRecylerReduceItemListener itemDeleteListener) {
        mItemDeleteListener = itemDeleteListener;
    }

}

然后就是主界面第二个RecylerView的适配器了,主要记录了输入的数据并保证数据可以正确的携带回去

public class GoodsSpecTypeNumberAdapter extends BaseAdapter<StoreManagerListEntity.SkuListEntity, GoodsSpecTypeNumberAdapter.GoodsSpecTypeViewHolder> {


    public GoodsSpecTypeNumberAdapter(Context context, List<StoreManagerListEntity.SkuListEntity> list) {
        super(context, list);
    }

    @Override
    public GoodsSpecTypeViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new GoodsSpecTypeViewHolder(mInflater.inflate(R.layout.item_goods_spec_number, parent, false));
    }

    @Override
    public void onBindViewHolder(GoodsSpecTypeViewHolder holder, int position) {
        StoreManagerListEntity.SkuListEntity item = getItem(position);


        holder.mEt_number_price.setTag(position * 100 + 1);
        holder.mEt_number_content.setTag(position * 100 + 2);

        holder.mTv_number_name.setText(item.spec);
        if (!TextUtils.isEmpty(item.stock)) {
            holder.mEt_number_content.setText(item.stock);
        }
        if (!TextUtils.isEmpty(item.price)) {
            holder.mEt_number_price.setText(item.price);
        }

        holder.mEt_number_price.addTextChangedListener(new TextSwitcher(holder, "1"));
        holder.mEt_number_content.addTextChangedListener(new TextSwitcher(holder, "2"));
    }

    class GoodsSpecTypeViewHolder extends RecyclerView.ViewHolder {


        private final TextView mTv_number_name;
        private final EditText mEt_number_price;
        private final EditText mEt_number_content;

        GoodsSpecTypeViewHolder(View itemView) {
            super(itemView);
            mTv_number_name = itemView.findViewById(R.id.tv_number_name);
            mEt_number_price = itemView.findViewById(R.id.et_number_price);
            mEt_number_content = itemView.findViewById(R.id.et_number_content);
        }
    }

    class TextSwitcher implements TextWatcher {
        private GoodsSpecTypeViewHolder mHolder;
        private String mType;

        TextSwitcher(GoodsSpecTypeViewHolder mHolder, String type) {
            this.mHolder = mHolder;
            mType = type;
        }

        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void afterTextChanged(Editable s) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {

            if ("1".equals(mType)) {
                int position = (Integer) mHolder.mEt_number_price.getTag();
                ((GoodsSpecActicity) mContext).saveEditData(position, mType, s.toString());
            } else if ("2".equals(mType)) {
                int position = (Integer) mHolder.mEt_number_content.getTag();
                ((GoodsSpecActicity) mContext).saveEditData(position, mType, s.toString());
            }
        }
    }
}

最后贴出来两个挂件,自定义两个接口,主要为了讲清楚思路和逻辑,工具类和基类就不贴在这里了,有兴趣的同学可以下载项目看下。

public interface ImageRecylerReduceItemListener {
    void onReduceItemListener(int position);
}

public interface RecylerViewAddItemListener {
    void onAddItemListener(List<String> entity, int position);
}

文章就到这里,欢迎指出错误或者修改优化意见。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 161,873评论 4 370
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 68,483评论 1 306
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 111,525评论 0 254
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,595评论 0 218
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 53,018评论 3 295
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,958评论 1 224
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 32,118评论 2 317
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,873评论 0 208
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,643评论 1 250
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,813评论 2 253
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,293评论 1 265
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,615评论 3 262
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,306评论 3 242
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,170评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,968评论 0 201
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 36,107评论 2 285
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,894评论 2 278