RecylerView(GridView布局)实现充值界面效果

648 阅读8分钟

RecylerView(GridView布局)实现充值界面效果

项目中有一个充值的效果如下:

效果图
之前为了赶项目进度,也没有多想,这不是很简单的么?5个TextView加1个EditText不就搞定了么? 的确这样做是可以实现的,而且也在规定时间内完成了项目。(但是存在局限性) 由于项目中多次的使用了RecycleView,然后发现这个用RecycleView实现效果会更好(布局更灵活,不限制个数),完成后的效果:
有角标
无角标

  • 1、数据传递效果的展示 首先分析下这个界面需要的数据,由于这个界面是后台通过两个字段判断实现的效果
   String data = "3,9,30,50,100";
   //isDiscount :1、有角标 2、无角标
	String isDiscount = "1";

我们首先要通过IsDiscount这个字段来判断是否显示带角标的控件,以及data字段来判断动态添加几个控件

  • 2、界面实现效果分析 1、组件选择 文章开始就说到了,我们选用的是RecycleView这个控件结合GridView布局实现效果 2、RecyeView Adapter布局分析 ①有角标TextView ②正常无角标TextView ③EditText输入框 布局如上三种,大家都知道RecycleView的强大,现在我们就利用它其中的ItemType这个功能,RecyleView很多复杂的界面都是通过ItemType这个属性来实现的。 3、具体代码的实现 ①ItemType种类的控制
 @Override
 public DemoAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
     switch (viewType) {
       case ItemModel.ONE:
                ///左上角三角标识布局;
                return new CornorViewHoler(LayoutInflater.from(parent.getContext()).inflate(R.layout.corner_one, parent, false));
     case ItemModel.TWO:
                return new OneViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.one, parent, false));
      case ItemModel.THREE:
                return new TWoViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.two, parent, false));
        }
        return null;
    }

在onCreateViewHolde这个方法中添加所需要的三种布局文件 ②Item数据封装 在这个Adapter中,由于我需要知道几个条件,第一个是当前选中的状态是否是免费的标志,第二个是当前选中的值,所以封装了一个ItemModel的类用于处理数据

public class ItemModel implements Serializable {
    //左上角三角图标
    public static final int ONE = 1001;
    //textview布局
    public static final int TWO = 1002;
    //edittext布局
    public static final int THREE = 1003;
    public int type;
    public Object data;
    //是否免费的标志
    public boolean isFree;
    public ItemModel(int type, Object data, boolean isFree) {
        this.type = type;
        this.data = data;
    }
}

好了前期的准备工作差不多了,现在我们就该对Adapter中的逻辑进行处理了。先上Adapter的完整代码

public class DemoAdapter extends RecyclerView.Adapter<DemoAdapter.BaseViewHolder> {
    private ArrayList<ItemModel> dataList = new ArrayList<>();
    private int lastPressIndex = -1;
    private Context mContext;

    public void replaceAll(ArrayList<ItemModel> list, Context context) {
        mContext = context;
        dataList.clear();
        if (list != null && list.size() > 0) {
            dataList.addAll(list);
        }
        notifyDataSetChanged();
    }

    @Override
    public DemoAdapter.BaseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        switch (viewType) {

            case ItemModel.ONE:
                ///左上角三角标识布局;
                return new CornorViewHoler(LayoutInflater.from(parent.getContext()).inflate(R.layout.corner_one, parent, false));
            case ItemModel.TWO:
                return new OneViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.one, parent, false));

            case ItemModel.THREE:
                return new TWoViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.two, parent, false));
        }
        return null;
    }

    @Override
    public void onBindViewHolder(DemoAdapter.BaseViewHolder holder, int position) {

        holder.setData(dataList.get(position).data);
    }

    @Override
    public int getItemViewType(int position) {
        return dataList.get(position).type;
    }

    @Override
    public int getItemCount() {
        return dataList != null ? dataList.size() : 0;
    }

    public class BaseViewHolder extends RecyclerView.ViewHolder {

        public BaseViewHolder(View itemView) {
            super(itemView);
        }

        void setData(Object data) {
        }
    }

    private class OneViewHolder extends BaseViewHolder {
        private TextView tv;

        public OneViewHolder(View view) {
            super(view);
            tv = (TextView) view.findViewById(R.id.tv);

            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e("TAG", "OneViewHolder: ");
                    notyfy = 0;
                    int position = getAdapterPosition();
                    ItemModel model = dataList.get(position);
                    Log.e("TAG", "OneViewHolder: " + model.toString());
                    EventBus.getDefault().post(model);
                    if (lastPressIndex == position) {
                        lastPressIndex = -1;
                    } else {
                        lastPressIndex = position;
                    }
                    notifyDataSetChanged();


                }

            });
        }

        @Override
        void setData(Object data) {
            if (data != null) {
                String text = (String) data;
                tv.setText(text);
                if (getAdapterPosition() == lastPressIndex) {
                    tv.setSelected(true);
                    tv.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.white));

                } else {
                    tv.setSelected(false);
                    tv.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.blue_500));
                }

            }


        }
    }

    int notyfy = 0;

    private class TWoViewHolder extends BaseViewHolder {
        private EditText et;
        private String chargeFunds;

        public TWoViewHolder(View view) {
            super(view);

            et = (EditText) view.findViewById(R.id.et);
            final int position = getAdapterPosition();
            //ItemModel model = dataList.get(position);
            //Log.e("TWoViewHolder", "TWoViewHolder: "+model.toString());
            Log.e("TWoViewHolder", "TWoViewHolder: ");
          et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {

                        if (lastPressIndex != position) {
                            notifyItemChanged(lastPressIndex);
                            lastPressIndex = position;
                        }
                    }
                }
            });
            et.addTextChangedListener(new TextWatcher() {


                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

                }

                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    if (charSequence != null || !charSequence.equals("")) {
                        try {
                            int str = Integer.parseInt(String.valueOf(charSequence));

                            if (str < 9) {

                                Toast.makeText(mContext, "输入的金额小于最小支付金额9元", Toast.LENGTH_SHORT).show();
                                et.setSelection(et.getText().length());
                            }
                            if (str > 2000) {
                                Toast.makeText(mContext, "输入的金额大于最大支付金额2000元", Toast.LENGTH_SHORT).show();
                                et.setText("2000");
                                et.setSelection(et.getText().length());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }

                @Override
                public void afterTextChanged(Editable editable) {


                    if (editable.length() > 0) {
                        String inputText = et.getText().toString().trim();
                        if (Double.parseDouble(inputText) < 9) {
                            chargeFunds = "9";
                        } else if (Double.parseDouble(inputText) > 2000) {
                            chargeFunds = "2000";
                        } else {
                            chargeFunds = inputText;
                        }
                    }

                    String funds = chargeFunds + "元";
                    ItemModel model = new ItemModel(ItemModel.THREE, funds, false);
                    EventBus.getDefault().post(model);
                }
            });


        }


        @Override
        void setData(Object data) {
            super.setData(data);
            final int position = getAdapterPosition();
            if (position == lastPressIndex)
                et.requestFocus();
            else
                et.clearFocus();
        }
    }

    private class CornorViewHoler extends BaseViewHolder {
        private TextView tv;

        public CornorViewHoler(View view) {
            super(view);
            tv = (TextView) view.findViewById(R.id.tv);
            //int position = getAdapterPosition();
            //ItemModel model = dataList.get(position);
            //Log.e("TAG", "OneViewHolder: "+model.toString());
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Log.e("TAG", "OneViewHolder: ");
                    notyfy = 0;
                    int position = getAdapterPosition();
                    ItemModel model = dataList.get(position);
                    EventBus.getDefault().post(model);
                    if (lastPressIndex == position) {
                        lastPressIndex = -1;
                    } else {
                        lastPressIndex = position;
                    }
                    notifyDataSetChanged();


                }

            });
        }

        @Override
        void setData(Object data) {
            if (data != null) {
                String text = (String) data;
                tv.setText(text);
                if (getAdapterPosition() == lastPressIndex) {
                    tv.setSelected(true);
                    tv.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.white));

                } else {
                    tv.setSelected(false);
                    tv.setTextColor(ContextCompat.getColor(itemView.getContext(), R.color.blue_500));
                }

            }
        }
    }
}

上述代码中数据传递使用的是EventBus3.0,所以需要在gradle文件添加如下引用:

compile 'org.greenrobot:eventbus:3.0.0'

现在开始对Adapter类进行分析,在Adapter类中我们创建了3个ViewHolder(CornorViewHoler、TWoViewHolder、OneViewHolder)在这三个ViewHolder中实现各自的逻辑,同时三个类中同时继承了void setData(Object data) 接口处理是否为选中状态、是否需要更改背景颜色以及状态 其他部分的代码都比较简单,不过在处理TWoViewHolder这个类的时候有点小麻烦(EditText),首先大家看到EditText有一个取值范围的(9~2000),这个通过addTextChangedListener监听来实现即可

    et.addTextChangedListener(new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                }
                @Override
                public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                    if (charSequence != null || !charSequence.equals("")) {
                        try {
                            int str = Integer.parseInt(String.valueOf(charSequence));
                            if (str < 9) {
                                Toast.makeText(mContext, "输入的金额小于最小支付金额9元", Toast.LENGTH_SHORT).show();
                                et.setSelection(et.getText().length());
                            }
                            if (str > 2000) {
                                Toast.makeText(mContext, "输入的金额大于最大支付金额2000元", Toast.LENGTH_SHORT).show();
                                et.setText("2000");
                                et.setSelection(et.getText().length());
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
                @Override
                public void afterTextChanged(Editable editable) {


                    if (editable.length() > 0) {
                        String inputText = et.getText().toString().trim();
                        if (Double.parseDouble(inputText) < 9) {
                            chargeFunds = "9";
                        } else if (Double.parseDouble(inputText) > 2000) {
                            chargeFunds = "2000";
                        } else {
                            chargeFunds = inputText;
                        }
                    }

                    String funds = chargeFunds + "元";
                    ItemModel model = new ItemModel(ItemModel.THREE, funds, false);
                    EventBus.getDefault().post(model);
                }
            });

到这里差不多写完了,是不是就大功告成了?别急,还有一个问题,点击EditText的时候,TextView的状态还没有消失呢,怎么办?

当页面刷新的时候 如果当前选中的是这个输入框就让它获取到并得到焦点,所以我们在TWoViewHolder类中的setData() 方法中让它获取焦点,将最后的位置传递给它

  @Override
        void setData(Object data) {
            super.setData(data);
            final int position = getAdapterPosition();
            if (position == lastPressIndex)
                et.requestFocus();
            else
                et.clearFocus();
        }

这样就差不多了,然后我们对EdiText的焦点进行监听(setOnFocusChangeListener),Notifycation布局文件即可

  et.setOnFocusChangeListener(new View.OnFocusChangeListener() {
                @Override
                public void onFocusChange(View v, boolean hasFocus) {
                    if (hasFocus) {

                        if (lastPressIndex != position) {
                            notifyItemChanged(lastPressIndex);
                            lastPressIndex = position;
                        }
                    } 
                }
            });

代码讲到这里就可以实现上面的效果了,下面将其他布局文件代码贴出来 MainActivity.class

public class MainActivity extends AppCompatActivity {

    private RecyclerView recyclerView;
    private DemoAdapter adapter;
    private TextView tvPay;
    private TextView tv_recharge_money;

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

        tv_recharge_money = (TextView) findViewById(R.id.tv_recharge_money);
        recyclerView = (RecyclerView) findViewById(R.id.recylerview);
        tvPay = (TextView) findViewById(R.id.tvPay);
        //setHasFixedSize 的作用就是确保尺寸是通过用户输入从而确保RecyclerView的尺寸是一个常数。
        // RecyclerView 的Item宽或者高不会变(提升性能)。
        recyclerView.setHasFixedSize(true);
        //recycleview设置布局方式,GridView (一行三列)
        recyclerView.setLayoutManager(new GridLayoutManager(this, 3));
        recyclerView.setAdapter(adapter = new DemoAdapter());
        adapter.replaceAll(getData(),this);
        EventBus.getDefault().register(this);

    }

    public ArrayList<ItemModel> getData() {
        String data = "3,9,30,50,100";
        // isDiscount :1、有角标 2、无角标
        String isDiscount = "2";
        String dataArr[] = data.split(",");
        ArrayList<ItemModel> list = new ArrayList<>();
        for (int i = 0; i < dataArr.length; i++) {
            String count = dataArr[i] + "元";
            if (isDiscount.equals("1") && i == 0) {
                list.add(new ItemModel(ItemModel.ONE, count, true));
            } else {
                list.add(new ItemModel(ItemModel.TWO, count, false));
            }
        }
        list.add(new ItemModel(ItemModel.THREE, null, false));

        return list;
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    public void getAdapterClickInfo(ItemModel model) {
        String money = model.data.toString().replace("元", "");
        tv_recharge_money.setText(money);
        if (model.isFree==true){
            Toast.makeText(this,"点击的是带免费标签的",Toast.LENGTH_SHORT).show();
        }else {
            Toast.makeText(this,"点击的是正常标签的",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(this);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.wangchang.testrecharge.MainActivity">

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

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_marginTop="12dp"
            android:background="@color/grey_300" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:padding="8dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="充值账号:"
                android:textColor="@color/black" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="15013678968"
                android:textColor="@color/yellow_900" />
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/grey_300" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="@color/white"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:padding="8dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="充值金额:"
                android:textColor="@color/black" />

            <TextView
                android:id="@+id/tv_recharge_money"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="100"
                android:textColor="@color/yellow_900" />
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/grey_300" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="8dp"
            android:text="选择充值金币:" />

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recylerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:padding="12dp" />

    </LinearLayout>

    <TextView
        android:id="@+id/tvPay"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_alignParentBottom="true"
        android:layout_margin="24dp"
        android:background="@drawable/tv_bg_pay"
        android:gravity="center"
        android:text="立即充值"
        android:textColor="@color/white" />
</RelativeLayout>

corner_one.xml

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="42dp"
        android:gravity="center"
        android:layout_margin="8dp"
        android:padding="12dp"
        android:background="@drawable/tv_bg"
        android:textColor="@color/blue_500" />

    <ImageView
        android:layout_margin="8dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:srcCompat="@drawable/free_click"
        android:id="@+id/imageView" />
</FrameLayout>

one.xml

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

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="42dp"
        android:gravity="center"
        android:layout_margin="8dp"
        android:padding="12dp"
        android:background="@drawable/tv_bg"
        android:textColor="@color/blue_500" />
</LinearLayout>

two.xml

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

    <EditText
        android:id="@+id/et"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="8dp"
        android:background="@drawable/bg_et"
        android:gravity="center"
        android:hint="9-2000元"
        android:inputType="number"
        android:padding="12dp"
        android:textSize="12sp" />
</LinearLayout>

好了,代码到此为止,效果也差不多了,有兴趣的朋友可以自行尝试下,欢迎大家一起交流,如有更好的建议或者意见可致电lcf_spark@163.com