Android仿钉钉物品采购输入保存JSON串

图片.png

公司要求做这么一个列表展示可以输入的EditText一个listView的列表,有点像钉钉的物品采购模块,并且价格需要自动计算,数量乘以单价,上图所示的类似效果图,点击添加按钮可以新增一组条目用于填写,删除按钮可以删除一组条目。下面直接展示主要逻辑部分代码。时间部分在demo里面忽略掉了。可以用自己喜欢的时间框架.

首先是Activity的布局文件:mListView 是一项目中常用的和ScroolView嵌套的ListView布局,也可以用 RecylerView 代替

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:background="@color/white">

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

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@drawable/icon_left_back"/>
        </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"
            >

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


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

        <com.lzy.demoedittextinput.mListView
            android:id="@+id/lv_goods_purchase"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/white"
            android:divider="@null"
            android:scrollbars="none"/>

    </ScrollView>

    <TextView
        android:id="@+id/tv_commit"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:background="@color/white"
        android:gravity="center"
        android:text="+ 新增物品"
        android:textColor="#000"
        android:textSize="16sp"/>

</LinearLayout>

下面是Activity代码,记得在清单文件注册。

import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.List;

public class GoodsPurchaseParticularsActivity extends AppCompatActivity implements View.OnClickListener {

    private List<GoodsPurchaseEntity> mList = new ArrayList<>();
    private CreateGoodsPurChaseAdapter mAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_goods_purchase_particulars);
        String article_purchase = getIntent().getStringExtra("article_purchase");
        if (article_purchase != null) {
            mList = JSON.parseArray(article_purchase, GoodsPurchaseEntity.class);
        } else {

            mList.add(new GoodsPurchaseEntity());
        }

        mAdapter = new CreateGoodsPurChaseAdapter(this, mList);

        RelativeLayout rl_back = (RelativeLayout) findViewById(R.id.rl_back);
        TextView tv_title = (TextView) findViewById(R.id.tv_title);
        ListView lv_goods_purchase = (ListView) findViewById(R.id.lv_goods_purchase);
        TextView tv_commit = (TextView) findViewById(R.id.tv_commit);
        RelativeLayout rl_right = (RelativeLayout) findViewById(R.id.rl_right);
        TextView tv_right = (TextView) findViewById(R.id.tv_right);

        tv_title.setText("明细");
        tv_right.setText("确定");
        mList.add(new GoodsPurchaseEntity());

        rl_back.setOnClickListener(this);
        tv_commit.setOnClickListener(this);
        rl_right.setOnClickListener(this);
        lv_goods_purchase.setAdapter(mAdapter);

        mAdapter.setOnDeleteItemListener(new CreateGoodsPurChaseAdapter.onDeleteItemListener() {
            @Override
            public void deleteItemListener(int position) {
                mList.remove(position);
                mAdapter.notifyDataSetChanged();
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.rl_back:
                finish();
                break;

            case R.id.tv_commit:
                mList.add(new GoodsPurchaseEntity());
                mAdapter.notifyDataSetChanged();
                break;

            case R.id.rl_right:
                submit();
                break;
        }
    }

    private void submit() {
        for (int i = 0; i < mList.size(); i++) {
            String norms = mList.get(i).getNorms();
            String name = mList.get(i).getName();
            String num = mList.get(i).getNum();
            String units = mList.get(i).getUnits();
            String type = mList.get(i).getType();
            String unit_price = mList.get(i).getUnit_price();
            String all_price = mList.get(i).getAll_price();

            if (TextUtils.isEmpty(norms) || TextUtils.isEmpty(name) || TextUtils.isEmpty(num)
                    || TextUtils.isEmpty(units) || TextUtils.isEmpty(type)
                    || TextUtils.isEmpty(unit_price) || TextUtils.isEmpty(all_price)) {
                Toast.makeText(this, "明细填写不全", Toast.LENGTH_SHORT).show();
                return;
            }
        }

        Double all_price = 0.00;
        String goods = JSON.toJSONString(mList);
        for (int i = 0; i < mList.size(); i++) {
            Double all_prices = Double.parseDouble(mList.get(i).getAll_price());
            all_price = all_price + all_prices;
        }

        Intent intent = new Intent();
        intent.putExtra("all_price", all_price + "");
        intent.putExtra("article_purchase", goods);
        intent.putExtra("num", mList.size() + "");
        setResult(RESULT_OK, intent);
        finish();
    }

    public void saveEditData(int position, String type, String str) {
        //数字用于区分EditText
        try {
            if ("1".equals(type)) {
                mList.get((position - 1) / 100).setType(str);
            } else if ("2".equals(type)) {
                mList.get((position - 2) / 100).setName(str);
            } else if ("3".equals(type)) {
                mList.get((position - 3) / 100).setNorms(str);
            } else if ("4".equals(type)) {
                mList.get((position - 4) / 100).setNum(str);
            } else if ("5".equals(type)) {
                mList.get((position - 5) / 100).setUnits(str);
            } else if ("6".equals(type)) {
                mList.get((position - 6) / 100).setUnit_price(str);
            } else if ("7".equals(type)) {
                mList.get((position - 7) / 100).setAll_price(str);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

下面是适配器代码,布局文件在后面。因为listView 先绘制的特性,所以思路是将EditText 的输入的值以监听的方式存入到实体中。

import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.TextView;

import java.text.DecimalFormat;
import java.util.List;


public class CreateGoodsPurChaseAdapter extends BaseAdapter {

    private Context mContext;
    private List<GoodsPurchaseEntity> mList;
    private onDeleteItemListener mOnDeleteItemListener;
    private final DecimalFormat mFormat;

    public CreateGoodsPurChaseAdapter(Context context, List<GoodsPurchaseEntity> list) {
        mContext = context;
        mList = list;
        mFormat = new DecimalFormat("##.##");
    }

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

    @Override
    public Object getItem(int position) {
        return mList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        ViewHolder holder;
        if (convertView == null) {
            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_goods_purchase, null);

            holder = new ViewHolder(convertView, position);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }
        if (position == 0) {
            holder.tv_delete.setVisibility(View.GONE);
            // holder.tv_num.setText("采购明细");
        } else {
            holder.tv_delete.setVisibility(View.VISIBLE);
        }
        int i = position + 1;
        holder.tv_num.setText("采购明细(" + i + ")");

        holder.rl_delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mOnDeleteItemListener.deleteItemListener(position);
            }
        });
        holder.et_type.setTag(position * 100 + 1);
        holder.et_name.setTag(position * 100 + 2);
        holder.et_norms.setTag(position * 100 + 3);
        holder.et_num.setTag(position * 100 + 4);
        holder.et_units.setTag(position * 100 + 5);
        holder.et_unit_price.setTag(position * 100 + 6);
        holder.tv_all_price.setTag(position * 100 + 7);

        GoodsPurchaseEntity bean = mList.get(position);
        holder.et_type.setText(bean.getType());
        holder.et_name.setText(bean.getName());
        holder.et_norms.setText(bean.getNorms());
        holder.et_num.setText(bean.getNum());
        holder.et_units.setText(bean.getUnits());
        holder.et_unit_price.setText(bean.getUnit_price());
        holder.tv_all_price.setText(bean.getAll_price());


        return convertView;
    }

    class ViewHolder {
        private TextView tv_delete;
        private RelativeLayout rl_delete;
        private EditText et_type;
        private EditText et_name;
        private EditText et_norms;
        private EditText et_num;
        private EditText et_units;
        private EditText et_unit_price;
        private TextView tv_all_price;
        private TextView tv_num;

        public ViewHolder(View convertView, int position) {
            tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
            tv_num = (TextView) convertView.findViewById(R.id.tv_num);
            tv_all_price = (TextView) convertView.findViewById(R.id.tv_all_price);
            rl_delete = (RelativeLayout) convertView.findViewById(R.id.rl_delete);
            et_type = (EditText) convertView.findViewById(R.id.et_type);
            et_name = (EditText) convertView.findViewById(R.id.et_name);
            et_norms = (EditText) convertView.findViewById(R.id.et_norms);
            et_num = (EditText) convertView.findViewById(R.id.et_num);
            et_units = (EditText) convertView.findViewById(R.id.et_units);
            et_unit_price = (EditText) convertView.findViewById(R.id.et_unit_price);


            et_type.addTextChangedListener(new TextSwitcher(this, "1"));
            et_name.addTextChangedListener(new TextSwitcher(this, "2"));
            et_norms.addTextChangedListener(new TextSwitcher(this, "3"));
            et_num.addTextChangedListener(new TextSwitcher(this, "4"));
            et_units.addTextChangedListener(new TextSwitcher(this, "5"));
            et_unit_price.addTextChangedListener(new TextSwitcher(this, "6"));
            tv_all_price.addTextChangedListener(new TextSwitcher(this, "7"));
        }
    }

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

        public TextSwitcher(ViewHolder 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.et_type.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("2".equals(mType)) {
                int position = (Integer) mHolder.et_name.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("3".equals(mType)) {
                int position = (Integer) mHolder.et_norms.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
            } else if ("4".equals(mType)) {
                int position = (Integer) mHolder.et_num.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());

                String et_num = mHolder.et_num.getText().toString();
                String units_price = mHolder.et_unit_price.getText().toString();
                if (TextUtils.isEmpty(et_num) || TextUtils.isEmpty(units_price)) {
                    mHolder.tv_all_price.setText("0");
                } else {
                    double all_price = Double.parseDouble(et_num) * Double.parseDouble(units_price);
                    String formatted = mFormat.format(all_price);
                    mHolder.tv_all_price.setText(formatted + "");
                }

            } else if ("5".equals(mType)) {
                int position = (Integer) mHolder.et_units.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());

            } else if ("6".equals(mType)) {
                int position = (Integer) mHolder.et_unit_price.getTag();
                ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
                String et_num = mHolder.et_num.getText().toString();
                String units_price = mHolder.et_unit_price.getText().toString();
                if (TextUtils.isEmpty(et_num) || TextUtils.isEmpty(units_price)) {
                    mHolder.tv_all_price.setText("0");
                } else {
                    double all_price = Double.parseDouble(et_num) * Double.parseDouble(units_price);
                    String formatted = mFormat.format(all_price);
                    mHolder.tv_all_price.setText(formatted + "");
                }
            } else if ("7".equals(mType)) {
                if (mHolder.tv_all_price.getTag() != null) {
                    int position = (Integer) mHolder.tv_all_price.getTag();

                    ((GoodsPurchaseParticularsActivity) mContext).saveEditData(position, mType, s.toString());
                }
            }
        }
    }

    public interface onDeleteItemListener {
        void deleteItemListener(int position);
    }

    public void setOnDeleteItemListener(onDeleteItemListener onDeleteItemListener) {
        mOnDeleteItemListener = onDeleteItemListener;
    }
}

下面是适配器Item布局,为了节省代码,封装了style

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <RelativeLayout
        android:id="@+id/rl_delete"
        android:layout_width="match_parent"
        android:layout_height="30dp"
        >

        <TextView
            android:id="@+id/tv_num"
            android:layout_width="wrap_content"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:text="报销明细"
            android:textSize="12sp"
            android:textColor="#999999"
            android:layout_height="match_parent"/>

        <TextView
            android:id="@+id/tv_delete"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:gravity="center_vertical"
            android:paddingLeft="15dp"
            android:paddingRight="15dp"
            android:text="删除"
            android:textColor="#32a8fc"
            android:textSize="12sp"/>
    </RelativeLayout>


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:orientation="horizontal">

        <TextView
            android:text="采购类型"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_type"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="45dp">

        <TextView
            android:text="物品名称"
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_name"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="45dp">

        <TextView
            android:text="规格        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_norms"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="数量        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_num"
            android:hint="请输入"
            android:inputType="number"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="单位        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_units"
            android:hint="请输入"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="单价        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <EditText
            android:id="@+id/et_unit_price"
            android:hint="请输入"
            android:inputType="numberDecimal"
            style="@style/common_45dp_edittext"/>

    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:background="#e5e5e5"
        android:layout_height="0.5dp"/>

    <LinearLayout
        style="@style/common_45dp_linearLayout">

        <TextView
            android:text="总价        "
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:gravity="center"
            android:textColor="#666666"/>

        <TextView
            android:id="@+id/tv_all_price"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginLeft="15dp"
            android:layout_marginRight="15dp"
            android:layout_weight="1"
            android:background="@null"
            android:gravity="center_vertical"
            android:hint="0"
            android:textColor="#333333"
            android:textColorHint="#999999"
            />

    </LinearLayout>

</LinearLayout>

style 如下

  <!-- 通用45dp #111 文字,提示文字#999 主要用于文字填写-->
    <style name="common_45dp_edittext">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">match_parent</item>
        <item name="android:layout_marginLeft">10dp</item>
        <item name="android:background">@null</item>
        <item name="android:singleLine">true</item>
        <item name="android:textColor">#333333</item>
        <item name="android:textColorHint">#999999</item>
        <item name="android:textSize">14sp</item>
    </style>


    <!-- 通用45dp 白底 条目线性布局 主要用于条目选择-->
    <style name="common_45dp_linearLayout">
        <item name="android:layout_width">match_parent</item>
        <item name="android:layout_height">45dp</item>

        <item name="android:gravity">center_vertical</item>
        <item name="android:orientation">horizontal</item>
    </style>

以上就是这个需求的主题逻辑和思路,如果有问题希望大家指正,也希望和有其他思路的大神交流学习。↖(▔.▔)↗

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 前言 其实以前写过这么一片类似的文章链接,利用字符串+runtime能做到命名域级别的解耦,其实这种做法很极端,编...
    Link913阅读 934评论 2 2
  • 朋友问题:“源头是什么?是树状吗?是吸收養分嗎? 答:不是。 心脏,扑通扑通地跳动,产生了不少血液,流向了全身,不...
    古茜妲樹二阅读 646评论 0 3
  • 探索 ConcurrentHashMap 高并发性的实现机制
    Tony_HQ阅读 240评论 0 0