popupWindow自定义(1)
popupWindow自定义(2)
首先看看效果图:
接着上篇文章的,上次讲述了自定义的密码框发现在时间使用过程中,当点击物理按键返回,密码框不消失,而是当前的Activity退出了,这次优化了这个bug一些默认的配置封装起来了,且在使用的时候更加方便。不多说,直接贴代码:
自定义密码框:
import android.content.Context;
import android.graphics.drawable.ColorDrawable;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import com.skypine.skypine.R;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
public class PasswordPopupWindow extends PopupWindow {
private Context mContext;
private View mMenuView;
private String mStringPassword; //输入的密码
private TextView[] mTextViewPsw; // 用数组保存6个TextView
private GridView mGridView; //支付键盘布局
private ArrayList<Map<String, String>> valueList;
private ImageView mImageViewCancel;
private TextView mTextViewForgetPsw;
private int currentIndex = -1;// 用于记录当前输入密码格位置
private TextView mTextViewTitle;
private TextView mTextViewDel;
private TextView cancelButton;
private TextView okButton;
private OnCancelListener cancelListener; //取消
public PasswordPopupWindow(Context context) {
super(context);
mContext = context;
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mMenuView = inflater.inflate(R.layout.password_dialog, null);
valueList = new ArrayList<>();
mTextViewPsw = new TextView[6];
mImageViewCancel = (ImageView) mMenuView.findViewById(R.id.iv_pay_back);
mTextViewPsw[0] = (TextView) mMenuView.findViewById(R.id.tv_pass1);
mTextViewPsw[1] = (TextView) mMenuView.findViewById(R.id.tv_pass2);
mTextViewPsw[2] = (TextView) mMenuView.findViewById(R.id.tv_pass3);
mTextViewPsw[3] = (TextView) mMenuView.findViewById(R.id.tv_pass4);
mTextViewPsw[4] = (TextView) mMenuView.findViewById(R.id.tv_pass5);
mTextViewPsw[5] = (TextView) mMenuView.findViewById(R.id.tv_pass6);
mGridView = (GridView) mMenuView.findViewById(R.id.gv_keybord);
mTextViewTitle = (TextView) mMenuView.findViewById(R.id.tv_pay_title);
mTextViewForgetPsw = (TextView) mMenuView.findViewById(R.id.tv_pay_forgetPwd);
/**/
cancelButton = (TextView) mMenuView.findViewById(R.id.cancelButton);
okButton = (TextView) mMenuView.findViewById(R.id.okButton);
setView();
//取消按钮
cancelButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
//取消
cancelListener.OnCancel();
//销毁弹出框
dismiss();
}
});
//设置SelectPicPopupWindow的View
this.setContentView(mMenuView);
//设置SelectPicPopupWindow弹出窗体的宽
this.setWidth(LayoutParams.FILL_PARENT);
//设置SelectPicPopupWindow弹出窗体的高
this.setHeight(LayoutParams.WRAP_CONTENT);
//设置SelectPicPopupWindow弹出窗体可点击
this.setFocusable(true);
//设置SelectPicPopupWindow弹出窗体动画效果
this.setAnimationStyle(R.style.mypopwindow_anim_style);
//实例化一个ColorDrawable颜色为半透明
ColorDrawable dw = new ColorDrawable(0xb0000000);
//设置SelectPicPopupWindow弹出窗体的背景
this.setBackgroundDrawable(dw);
//mMenuView添加OnTouchListener监听判断获取触屏位置如果在选择框外面则销毁弹出框
mMenuView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
int height = mMenuView.findViewById(R.id.pop_layout).getTop();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_UP) {
if (y < height) {
dismiss();
}
}
return true;
}
});
}
/*********************
* 取消
******************/
public interface OnCancelListener {
public void OnCancel();
}
public void setCancelListener(OnCancelListener cancelListener) {
this.cancelListener = cancelListener;
}
// 初始化按钮上应该显示的数字
private void setView() {
for (int i = 1; i < 13; i++) {
Map<String, String> map = new HashMap<>();
if (i < 10) {
map.put("name", String.valueOf(i));
} else if (i == 10) {//没有
map.put("name", "");
} else if (i == 11) {//
map.put("name", String.valueOf(0));
} else if (i == 12) {
map.put("name", "");
} else if (i == 13) {
map.put("name", " ");
} else if (i == 14) {
map.put("name", "");
}
valueList.add(map);
}
mGridView.setAdapter(adapter);
}
public interface OnPasswordInputFinish {
public void inputFinish();
}
/**
* 设置监听方法,在第6位输入完后触发
*/
public void setOnFinishInput(final OnPasswordInputFinish pass) {
mTextViewPsw[5].addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (s.toString().length() == 1) {
mStringPassword = ""; //每次触发都要将mStringPassword置空再重新获取,避免由于输入删除再输入造成混乱
for (int i = 0; i < 6; i++) {
mStringPassword += mTextViewPsw[i].getText().toString().trim();
}
pass.inputFinish();//接口中要实现的方法,完成密码输入完成后的响应逻辑
}
}
});
}
/**
* 清除所有密码
*/
public void clearAll() {
// currentIndex= -1;
// mTextViewPsw[0].setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[1].setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[2] .setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[3]. setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[4]. setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[5].setBackgroundResource(R.drawable.bg_circle_num_pwd);
// mTextViewPsw[0].setText("");
// mTextViewPsw[1].setText("");
// mTextViewPsw[2] .setText("");
// mTextViewPsw[3]. setText("");
// mTextViewPsw[4]. setText("");
// mTextViewPsw[5].setText("");
currentIndex = 5;
while (true)
if (currentIndex - 1 >= -1) { // 判断是否删除完毕
TextView temp = mTextViewPsw[currentIndex--];
temp.setText("");
temp.setBackgroundResource(R.drawable.bg_circle_num_pwd);
} else {
break;
}
}
/**
* 获取输入的密码
*/
public String getPassword() {
return mStringPassword;
}
/**
* 返回取消支付的ImageView
*/
public ImageView getCancel() {
return mImageViewCancel;
}
// /**
// * 返回取消
// */
// public TextView getmTextViewCancel() {
// return mTextViewCancel;
// }
/**
* 返回忘记密码的TextView
*/
public TextView getForgetPsw() {
return mTextViewForgetPsw;
}
/**
* 返回标题的TextView
*/
public TextView getTitle() {
return mTextViewTitle;
}
/**
* GridView的适配器
*/
BaseAdapter adapter = new BaseAdapter() {
@Override
public int getCount() {
return valueList.size();
}
@Override
public Object getItem(int position) {
return valueList.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 = View.inflate(mContext, R.layout.item_pay_gride, null);
holder = new ViewHolder();
holder.btnKey = (Button) convertView.findViewById(R.id.btn_keys);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.btnKey.setText(valueList.get(position).get("name"));
if (position == 12) {
holder.btnKey.setText("取消");
}
if (position == 14) {
mTextViewDel = holder.btnKey;
holder.btnKey.setText("删除");
}
if (position == 9 || position == 11 || position == 13) {
holder.btnKey.setBackground(null);
holder.btnKey.setText("");
}
okButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (currentIndex - 1 >= -1) { // 判断是否删除完毕
TextView temp = mTextViewPsw[currentIndex--];
temp.setText("");
temp.setBackgroundResource(R.drawable.bg_circle_num_pwd);
}
}
});
holder.btnKey.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (position < 11 && currentIndex != 9 && position != 9) { //点击0-9按钮
if (currentIndex >= -1 && currentIndex < 5) { //判断输入位置
TextView temp = mTextViewPsw[++currentIndex];
temp.setText(valueList.get(position).get("name"));
temp.setBackgroundResource(R.drawable.bg_circle_num_pwd_visiable);
}
} else {
if (position == 14) { //点击退格键
if (currentIndex - 1 >= -1) { // 判断是否删除完毕
TextView temp = mTextViewPsw[currentIndex--];
temp.setText("");
temp.setBackgroundResource(R.drawable.bg_circle_num_pwd);
}
}
if (position == 12) {
//退出
cancelListener.OnCancel();
}
}
}
});
return convertView;
}
};
static class ViewHolder {
public Button btnKey;
}
}
xml文件:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:orientation="vertical">
<LinearLayout
android:id="@+id/pop_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimary"
android:orientation="vertical">
<LinearLayout
android:id="@+id/ll_main_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="50dp">
<ImageView
android:id="@+id/iv_pay_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="10dp"/>
<TextView
android:id="@+id/tv_pay_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:text="@string/pin_id"
android:textColor="@color/white"
android:textSize="18dp"/>
</RelativeLayout>
<!-- 6位密码框布局,需要一个圆角边框的shape作为layout的背景 -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/dp_15"
android:gravity="center"
android:orientation="horizontal">
<!-- inputType设置隐藏密码明文
textSize设置大一点,否则“点”太小了,不美观 -->
<TextView
android:id="@+id/tv_pass1"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:paddingBottom="@dimen/dp_5"
android:textColor="@color/pwd_gray"
android:textSize="12sp"/>
<TextView
android:id="@+id/tv_pass2"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:textColor="@color/pwd_gray"
android:textSize="15sp"/>
<TextView
android:id="@+id/tv_pass3"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:textColor="@color/pwd_gray"
android:textSize="15sp"/>
<TextView
android:id="@+id/tv_pass4"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:textColor="@color/pwd_gray"
android:textSize="15sp"/>
<TextView
android:id="@+id/tv_pass5"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:textColor="@color/pwd_gray"
android:textSize="15sp"/>
<TextView
android:id="@+id/tv_pass6"
android:layout_width="@dimen/dp_15"
android:layout_height="@dimen/dp_15"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:background="@drawable/bg_circle_num_pwd"
android:gravity="center"
android:inputType="numberPassword"
android:textColor="@color/pwd_gray"
android:textSize="15sp"/>
</LinearLayout>
<TextView
android:id="@+id/tv_pay_forgetPwd"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
android:textColor="@color/white"
android:visibility="gone"/>
</LinearLayout>
<!-- 输入键盘 -->
<GridView
android:id="@+id/gv_keybord"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginTop="@dimen/dp_50"
android:horizontalSpacing="0.5dp"
android:numColumns="3"
android:textColor="@color/colorPrimary"
android:verticalSpacing="0.5dp"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
android:padding="@dimen/dp_10">
<TextView
android:id="@+id/cancelButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/dp_10"
android:text="@string/pay_cancle"
android:textColor="@color/white"
android:textSize="@dimen/sp_15"/>
<TextView
android:id="@+id/okButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_gravity="right"
android:padding="@dimen/dp_10"
android:text="@string/pay_delete"
android:textColor="@color/white"
android:textSize="@dimen/sp_15"/>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
</RelativeLayout>
style
<!-- 这个是popwindow -->
<style name="mypopwindow_anim_style">
<item name="android:windowEnterAnimation">@anim/popshow_anim</item>
<!-- 指定显示的动画xml -->
<item name="android:windowExitAnimation">@anim/pophidden_anim</item>
<!-- 指定消失的动画xml -->
</style>
popshow_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="100%p"
android:toYDelta="0" />
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0" />
</set>
pophidden_anim
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="0"
android:toYDelta="50%p" />
<alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.0" />
</set>
如果大家看懂了这个,再也不怕任何自定义的弹框,根据这个原理,可以封装任意的弹框
比如看看下面类似滴滴打车的搜索页面可以用PopWindow 实现,可以自己试试。
感谢批评与指导