RecylerView(GridView布局)实现充值界面效果
来源:互联网 发布:主角可以优化功法的 编辑:程序博客网 时间:2024/05/22 06:33
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
- RecylerView(GridView布局)实现充值界面效果
- RecylerView实现多种复杂条目类型布局
- 用recylerView实现瀑布流的效果
- android学习——GridView实现主界面布局
- Android网格布局(GridView)---实现漂亮的多选效果
- Weex实现GridView的网格布局以及浮层效果
- Android学习之RecylerView完美实现瀑布流效果
- Android学习之RecylerView完美实现瀑布流效果
- Android自绘View界面布局实现文字水印效果
- ViewPager + GridView实现GridView分页首页导航栏布局分页效果
- GridView行高亮效果实现
- RecyclerView实现 gridview效果!
- Lsn5研究ListView源码来封装RecylerView实现添加无数个头布局和尾布局
- GridView + ViewFlipper布局界面,模仿“机锋市场”
- Android中RecyclerView布局代替GridView实现类似支付宝的界面
- Android之ViewPager+GridView实现仿美团首页导航栏布局分页效果
- 1.9 GridView: 将GridView中布局填充到界面中
- 利用GridView实现功能界面
- dubbo容器
- Android API统计
- 第一章 办公室沟通法则
- vue项目搭建
- 图的广度优先遍历
- RecylerView(GridView布局)实现充值界面效果
- 洛谷 P1255 数楼梯
- 多线程编程实例练习
- zoj2433
- J2EE设计模式
- dos命令使用
- 洛谷 P1092 虫食算
- fs.inotify.max_user_watches默认值太小,导致too many open files
- 寒假刷题——补模板——写新题