高仿 微信、支付宝 选择银行卡效果(PopupWindow实现)

2019-01-14  本文已影响87人  吾乃韩小呆

尊敬的各位兄弟姐妹们,韩小呆同学终于逮到时间(忙里偷闲,花样嘬死更确切),为大家带来这个效果实现方式。额,日后我争取一周给大家带来一个好玩的效果,或者是实用的效果或者...总之是开发中实用的东西。

下面步入正题,我们先看一下支付宝和微信的效果吧:


微信效果 支付宝效果
韩小呆同学实现的效果

目测,没差多少,额,不要在意细节。韩小呆是程序员界的穷x。下面开始撸码:

1、搭建界面

<?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:id="@+id/rl_main"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   android:background="#005B9E"
   android:focusable="true"
   android:focusableInTouchMode="true"
   tools:context=".MainActivity">

   <TextView
       android:id="@+id/tv_name"
       android:layout_width="wrap_content"
       android:layout_height="50dp"
       android:layout_alignParentStart="true"
       android:layout_marginStart="20dp"
       android:layout_marginTop="20dp"
       android:gravity="center"
       android:text="用户名:"
       android:textColor="#ffffff"
       android:textSize="18sp" />

   <EditText
       android:id="@+id/et_name"
       android:layout_width="match_parent"
       android:layout_height="50dp"
       android:layout_marginTop="20dp"
       android:layout_marginEnd="10dp"
       android:layout_toEndOf="@+id/tv_name"
       android:paddingStart="10dp"
       android:paddingEnd="1dp"
       android:singleLine="true"
       android:textColor="#fff"
       android:textSize="14sp"
       tools:text="韩小呆" />

   <TextView
       android:id="@+id/tv_bank"
       android:layout_width="wrap_content"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_name"
       android:layout_alignParentStart="true"
       android:layout_marginStart="20dp"
       android:layout_marginTop="10dp"
       android:gravity="center"
       android:text="银行名:"
       android:textColor="#fff"
       android:textSize="18sp" />

   <EditText
       android:id="@+id/et_bank"
       android:layout_width="match_parent"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_name"
       android:layout_marginTop="10dp"
       android:layout_marginEnd="10dp"
       android:layout_toEndOf="@+id/tv_bank"
       android:paddingStart="10dp"
       android:paddingEnd="1dp"
       android:singleLine="true"
       android:textColor="#fff"
       android:textSize="14sp"
       tools:text="招商银行" />

   <TextView
       android:id="@+id/tv_bank_num"
       android:layout_width="wrap_content"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_bank"
       android:layout_alignParentStart="true"
       android:layout_marginStart="20dp"
       android:layout_marginTop="10dp"
       android:gravity="center"
       android:text="账户号:"
       android:textColor="#fff"
       android:textSize="18sp" />

   <EditText
       android:id="@+id/et_bank_num"
       android:layout_width="match_parent"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_bank"
       android:layout_marginTop="10dp"
       android:layout_marginEnd="10dp"
       android:layout_toEndOf="@+id/tv_bank_num"
       android:inputType="number"
       android:paddingStart="10dp"
       android:paddingEnd="1dp"
       android:singleLine="true"
       android:textColor="#fff"
       android:textSize="14sp"
       tools:text="6227000132080872008" />

   <TextView
       android:id="@+id/tv_phone"
       android:layout_width="wrap_content"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_bank_num"
       android:layout_alignParentStart="true"
       android:layout_marginStart="20dp"
       android:layout_marginTop="10dp"
       android:gravity="center"
       android:text="手机号:"
       android:textColor="#fff"
       android:textSize="18sp" />

   <EditText
       android:id="@+id/et_phone"
       android:layout_width="match_parent"
       android:layout_height="50dp"
       android:layout_below="@+id/tv_bank_num"
       android:layout_marginTop="10dp"
       android:layout_marginEnd="10dp"
       android:layout_toEndOf="@+id/tv_name"
       android:inputType="number"
       android:paddingStart="10dp"
       android:paddingEnd="1dp"
       android:singleLine="true"
       android:textColor="#fff"
       android:textSize="14sp"
       tools:text="15210990809" />

   <LinearLayout
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:layout_below="@+id/tv_phone"
       android:layout_marginTop="20dp"
       android:orientation="horizontal"
       android:padding="20dp">

       <Button
           android:id="@+id/btn_add"
           android:layout_width="0dp"
           android:layout_height="wrap_content"
           android:layout_marginEnd="10dp"
           android:layout_weight="1"
           android:background="#1EA362"
           android:text="add"
           android:textAllCaps="false"
           android:textColor="#ffffff"
           android:textSize="18sp" />

       <Button
           android:id="@+id/btn_show"
           android:layout_width="0dp"
           android:layout_height="wrap_content"
           android:layout_marginStart="10dp"
           android:layout_weight="1"
           android:background="#1EA362"
           android:text="show"
           android:textAllCaps="false"
           android:textColor="#ffffff"
           android:textSize="18sp" />
   </LinearLayout>

</RelativeLayout>

Activity 的界面搭建很简单,就是 一个添加银行卡的过程,和展示 popupWindow 的相关按钮;搭建完成是这个样子的:


Activity 界面

popupWindow 的界面更加简单一个 RecycleView 就行了,如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/fl_pop"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#50000000">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="300dp"
        android:background="#07182A"
        android:orientation="vertical">

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

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="10dp"
                android:text="选择到账银行卡"
                android:textColor="#00FFF6"
                android:textSize="16sp" />

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginStart="20dp"
                android:layout_marginTop="10dp"
                android:text="平台7个工作日内线下打款,请注意到账时间"
                android:textColor="#00CCFF"
                android:textSize="12sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="0.5dp"
                android:layout_alignParentBottom="true"
                android:layout_marginTop="10dp"
                android:background="#0C889B" />
        </LinearLayout>

        <android.support.v7.widget.RecyclerView
            android:id="@+id/rlv_pop"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#07182A" />

    </LinearLayout>
</FrameLayout>
弹出框效果

item 的效果就不放了,太简单了,浪费篇幅。

2、适配器逻辑

package com.hxd.bankcardpop;

import android.annotation.SuppressLint;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.RadioButton;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Content:
 * Actor:韩小呆 ヾ(✿゚▽゚)ノ
 * Time:  2019/01/05 22:09
 * Update:
 * Time:
 */
public class PopAdapter extends RecyclerView.Adapter<PopAdapter.MyViewHolder> {

    private Context mContext;
    private List<CardBean> cards;
    private OnItemClickListener mOnItemClickListener;

    private HashMap<Integer, Boolean> map;


    @SuppressLint("UseSparseArrays")
    PopAdapter(Context mContext) {
        this.mContext = mContext;
        map = new HashMap<>();
        cards = new ArrayList<>();
    }


    public void setData(List<CardBean> cardBeans) {
        this.cards.clear();
        this.cards.addAll(cardBeans);

        map.clear();
        for (int i = 0; i < this.cards.size(); i++) {
            map.put(i, false);
        }
    }


    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
        return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_pop, viewGroup, false));
    }

    @Override
    public void onBindViewHolder(@NonNull final MyViewHolder myViewHolder, final int i) {
        CardBean card = cards.get(i);

        myViewHolder.tvName.setText(card.getCard_bank());

        if (card.getId() == 0) {
            myViewHolder.rbSelect.setVisibility(View.INVISIBLE);
            myViewHolder.ibDel.setVisibility(View.INVISIBLE);
        } else {
            myViewHolder.rbSelect.setVisibility(View.VISIBLE);
            myViewHolder.ibDel.setVisibility(View.VISIBLE);
        }

        myViewHolder.rbSelect.setChecked(map.get(i));

        myViewHolder.ibDel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = myViewHolder.getLayoutPosition();
                mOnItemClickListener.onDelClick(myViewHolder.ibDel, pos);
            }
        });

        myViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int pos = myViewHolder.getLayoutPosition();
                mOnItemClickListener.onSelectClick(myViewHolder.itemView, pos);

                myViewHolder.rbSelect.setChecked(true);

                map.put(pos, map.get(pos));
                notifyDataSetChanged();
                singleSelect(pos);


            }
        });


    }


    //设置单选
    private void singleSelect(int pos) {
        Set<Map.Entry<Integer, Boolean>> entries = map.entrySet();
        for (Map.Entry<Integer, Boolean> entry : entries) {
            entry.setValue(false);
        }
        map.put(pos, true);
        notifyDataSetChanged();
    }


    @Override
    public int getItemCount() {
        return cards.size();
    }

    class MyViewHolder extends RecyclerView.ViewHolder {

        private TextView tvName;
        private ImageButton ibDel;
        private RadioButton rbSelect;

        MyViewHolder(@NonNull View itemView) {
            super(itemView);

            tvName = itemView.findViewById(R.id.tv_card_name);
            ibDel = itemView.findViewById(R.id.ib_del);
            rbSelect = itemView.findViewById(R.id.cb_card);

        }
    }

    public interface OnItemClickListener {
        void onDelClick(View view, int pos);

        void onSelectClick(View view, int pos);
    }

    void setOnItemClickListener(OnItemClickListener onItemClickListener) {
        mOnItemClickListener = onItemClickListener;
    }
}

这里面值得一说的是 RecycleView 的单选处理,对于高手 很简单,一个 map 解决了。但是对于像楼主这样的菜鸟就得反复琢磨了。

其实也很简单啦,在初始化Adapter 的时候,初始化一个map。当传入数据的时候,首先将 map内的数据清空,然后向内put进去,数据的位置和全部置位为false。 当选择某个item 的时候 将被选中的 item 的 RadioButton 变为已选,遍历map,将其余的item的选择状态均变为false。

如果看源码 ,请看上部分代码的 map 相关。

这里有一个细节需要注意一下,RecycleView 的item 内的 最好不要用 gone来隐藏看见,任意丢控件, 控件的隐藏和展示是成对出现的。

3、Activity 相关逻辑

package com.hxd.bankcardpop;

import android.annotation.SuppressLint;
import android.graphics.drawable.ColorDrawable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

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

public class MainActivity extends AppCompatActivity implements View.OnClickListener, PopAdapter.OnItemClickListener {


    private EditText etName;
    private EditText etBank;
    private EditText etBankNum;
    private EditText etPhone;
    private Button btnShow;
    private Button btnAdd;
    private RelativeLayout rlMain;

    private PopupWindow popCard;
    private PopAdapter adapter;
    private View view;
    private List<CardBean> cardBeans;
    private int tag = 5;

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

        rlMain = findViewById(R.id.rl_main);
        etName = findViewById(R.id.et_name);
        etBank = findViewById(R.id.et_bank);
        etBankNum = findViewById(R.id.et_bank_num);
        etPhone = findViewById(R.id.et_phone);
        btnShow = findViewById(R.id.btn_show);
        btnAdd = findViewById(R.id.btn_add);

        adapter = new PopAdapter(this);

        adapter.setOnItemClickListener(this);
        btnAdd.setOnClickListener(this);
        btnShow.setOnClickListener(this);

        cardBeans = new ArrayList<>();

        for (int i = 1; i < 5; i++) {
            cardBeans.add(new CardBean(i, "a" + i, "韩小呆" + i, "招商银行" + i, "622700013209087200" + i, "1383146022" + i));
        }
        cardBeans.add(new CardBean(0, "0", "0", "使用新卡提现", "0", "0"));

        initPopView();
    }

    @SuppressLint("InflateParams")
    private void initPopView() {
        view = getLayoutInflater().inflate(R.layout.pop_card, null, false);
        FrameLayout flPop = view.findViewById(R.id.fl_pop);
        RecyclerView rlvPop = view.findViewById(R.id.rlv_pop);

        rlvPop.setLayoutManager(new LinearLayoutManager(this));
        rlvPop.setAdapter(adapter);
        flPop.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {

        int id = v.getId();

        switch (id) {
            case R.id.btn_add:
                addData();
                break;
            case R.id.btn_show:
                showPop();
                break;
            case R.id.fl_pop:
                popCard.dismiss();
                break;
        }

    }

    private void addData() {
        tag++;
        String username = etName.getText().toString().trim();
        String bank = etBank.getText().toString().trim();
        String bankNum = etBankNum.getText().toString().trim();
        String phone = etPhone.getText().toString().trim();

        if (TextUtils.isEmpty(bank)) {
            Toast.makeText(this, "必须输入银行名称!", Toast.LENGTH_SHORT).show();
        } else {
            cardBeans.remove(cardBeans.size() - 1);
            cardBeans.add(new CardBean(tag, "" + tag, username, bank + tag, bankNum, phone));
            cardBeans.add(new CardBean(0, "0", "0", "使用新卡提现", "0", "0"));
            Toast.makeText(this, "添加成功!", Toast.LENGTH_LONG).show();

        }
    }


    private void showPop() {
        if (popCard == null) {
            popCard = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
        }
        popCard.setBackgroundDrawable(new ColorDrawable());
        popCard.showAtLocation(rlMain, Gravity.CENTER, 0, 0);
        adapter.setData(cardBeans);
        adapter.notifyDataSetChanged();

    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (popCard != null) {
            popCard.dismiss();
        }
    }


    @Override
    public void onDelClick(View view, int pos) {
        cardBeans.remove(pos);
        Toast.makeText(this, "删除第 " + (pos + 1) + " 条数据成功", Toast.LENGTH_LONG).show();
        popCard.dismiss();
    }

    @Override
    public void onSelectClick(View view, int pos) {
        Toast.makeText(this, "选择第 " + (pos + 1) + " 条数据成功", Toast.LENGTH_LONG).show();
//        popCard.dismiss();
    }
}

这里有几个细节需要注意一下:
1、PopupWindow内的view 最好只初始化一次,笔者看好多文章都是反复进行初始化,笔者不知道手机累不累性能咋样;
2、PopupWindow 也最好只初始化一次;
3、需要程序员自己整理服务器返还的数据,游戏时候服务器返回的json不是我们需要的哦。这是我们必备技能。

下面来运行一下,看看效果哦:


运行效果

最后献上demo 地址: BankCardPop

上一篇下一篇

猜你喜欢

热点阅读