自定义PopupWindow
上下左右弹出来的PopupWindow
界面:
PopList的界面就是一个LinearLayout包着一个ListView
ListView的item的界面就是一个LinearLayout包着一个TextView
字体变色:
当ListView的item在android:state_selected=true
的情况下,想改变字体颜色的话
可以在res文件夹下新建一个Android Resource Directory,并且在Resource type的位置选择color。
在color这个文件夹下创建Color Resource File,然后在TextView设置android:textColor="@color/selector_font_color"。
如果想在字体变色的基础上加上走马灯,那就再加上android:ellipsize=“marquee” android:singleLine=“true” android:marqueeRepeatLimit=“marquee_forever”。不过要注意的是,如果文本内容的所占的长度并没有超过TextView可以显示的长度的话,走马灯是不会有效果的,而且走马灯也只有在获得焦点的时候才会起作用。如果在没有焦点的时候也想让走马灯有效果的话,可以自定义TextView一直得到焦点。
selector_font_color.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="#009cff" android:state_selected="true" />
<item android:color="#8e8e8e" />
</selector>
加动画:
跟上面创建color
文件夹基本上是同样的方法,只是在Resource type里面选的不是color而是anim
而已。
然后就可以创建自定义动画的xml了:R.anim.anim_pop_from_top, R.anim.anim_pop_from_bottom, R.anim.anim_pop_from_left, R.anim.anim_pop_from_right。
影响宽高的方法: setBackgroundDrawable(), setHeight(), setWidth()。
一定要调用这三个方法,少了哪一个都有可能让PopupWindow的宽高设置无效。
setBackgroundDrawable()
可以设置一张透明的,但是一定要设置。
setWidth()
和setHeight()
如果没有明确的大小的话,可以用ViewGroup.LayoutParams.MATCH_PARENT
或者ViewGroup.LayoutParams.WRAP_CONTENT
。
调整宽高的方法: setHeight(), setWidth(), update()。
用了setHeight()
、setWidth()
之后务必要调用update()
,否则设置完了也看不到效果、
不要轻易使用getLayoutParams()
,因为很有可能会报空。
避免窗体泄露的方法: dismiss()。
在调用PopList的Activity的onDestroy()
里面,必须判断PopList
有没有dismiss
,如果不判断而PopList又没有dismiss()
的话就会造成窗体泄露。
监听PopList的点击:
在PopList和Adapter里面分别定义两个回调接口OnPopItemClickListener, OnClickItemListener,在Activity里面监听PopList的回调就可以了。
PopList.java
class PopList extends PopupWindow {
private static final String TAG = "PopList";
static final int FROM_TOP = 0;
static final int FROM_BOTTOM = 1;
static final int FROM_LEFT = 2;
static final int FROM_RIGHT = 3;
private LinearLayout popLayout;
private ListView layoutList;
private Context mContext;
private PopAdapter mAdapter = null;
private Animation mAnimaton = null;
PopList(Context context) {
super(context);
mContext = context;
setFocusable(true);
setTouchable(true);
setOutsideTouchable(true);
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
setWidth(mContext.getResources().getDimensionPixelOffset(R.dimen.dp_390));
View view = LayoutInflater.from(context).inflate(R.layout.layout_pop_list, null);
setContentView(view);
init(view);
}
private void init(View view) {
popLayout = view.findViewById(R.id.pop_layout);
layoutList = view.findViewById(R.id.layout_list);
mAdapter = new PopAdapter();
mAdapter.setOnItemClickListener(new PopAdapter.OnItemClickListener() {
@Override
public void onItemClick(int position, String title) {
if (onPopItemClickListener != null) {
onPopItemClickListener.onPopItemClick(position, title);
}
}
});
}
void setData(List<String> list, int select) {
if (list == null || list.isEmpty()) return;
mAdapter.setData(list, select);
layoutList.setAdapter(mAdapter);
}
void show(int direction, View anchor, int itemCount) {
adjustHeight(direction, itemCount);
update(); // 调整完宽高之后一定要update()
showAtLocation(anchor, findGravity(direction), 0, 0);
appendAnimation(direction);
}
private void adjustHeight(int direction, int itemCount) {
if (direction == FROM_TOP || direction == FROM_BOTTOM) {
if (itemCount > 6) {
setHeight(mContext.getResources().getDimensionPixelOffset(R.dimen.dp_480));
} else {
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
}
} else {
if (itemCount > 10) {
setHeight(mContext.getResources().getDimensionPixelOffset(R.dimen.dp_800));
} else {
setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
}
}
}
private int findGravity(int direction) {
switch (direction) {
case FROM_TOP:
return Gravity.TOP | Gravity.CENTER_HORIZONTAL;
case FROM_BOTTOM:
return Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
case FROM_LEFT:
return Gravity.LEFT | Gravity.CENTER_VERTICAL;
case FROM_RIGHT:
return Gravity.RIGHT | Gravity.CENTER_VERTICAL;
default:
return Gravity.CENTER;
}
}
private void appendAnimation(int direction) {
if (mAnimaton != null && !mAnimaton.hasEnded()) mAnimaton.cancel();
mAnimaton = null;
switch (direction) {
case FROM_TOP:
mAnimaton = AnimationUtils.loadAnimation(mContext, R.anim.anim_pop_from_top);
break;
case FROM_BOTTOM:
mAnimaton = AnimationUtils.loadAnimation(mContext, R.anim.anim_pop_from_bottom);
break;
case FROM_LEFT:
mAnimaton = AnimationUtils.loadAnimation(mContext, R.anim.anim_pop_from_left);
break;
case FROM_RIGHT:
mAnimaton = AnimationUtils.loadAnimation(mContext, R.anim.anim_pop_from_right);
break;
}
if (mAnimaton != null) {
mAnimaton.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
layoutList.smoothScrollToPosition(mAdapter.getLastSelect());
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
popLayout.setAnimation(mAnimaton);
mAnimaton.start();
}
}
private OnPopItemClickListener onPopItemClickListener;
public interface OnPopItemClickListener {
void onPopItemClick(int position, String title);
}
void setOnPopItemClickListener(OnPopItemClickListener onPopItemClickListener) {
this.onPopItemClickListener = onPopItemClickListener;
}
public static class PopAdapter extends BaseAdapter {
private List<String> mListItems;
private int mLastSelect = 0;
PopAdapter() {
mListItems = new ArrayList<>();
}
void setData(List<String> list, int select) {
if (list == null) return;
if (mListItems == null) mListItems = new ArrayList<>();
else if (!mListItems.isEmpty()) mListItems.clear();
mListItems.addAll(list);
mLastSelect = select;
notifyDataSetChanged();
}
int getLastSelect() {
return mLastSelect;
}
@Override
public int getCount() {
return mListItems.size();
}
@Override
public Object getItem(int position) {
return mListItems.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item_pop_list, parent, false);
holder = new ViewHolder();
holder.itemLayout = convertView.findViewById(R.id.item_layout);
holder.itemText = convertView.findViewById(R.id.item_text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.itemText.setSelected(mLastSelect == position);
holder.itemText.setText(mListItems.get(position));
holder.itemLayout.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mLastSelect == position) return;
mLastSelect = position;
if (onItemClickListener != null) {
onItemClickListener.onItemClick(position, mListItems.get(position));
}
// 如果没有这句 那么不会执行holder.itemText.setSelected()
notifyDataSetChanged();
}
});
return convertView;
}
static class ViewHolder {
LinearLayout itemLayout;
TextView itemText;
}
private OnItemClickListener onItemClickListener;
public interface OnItemClickListener {
void onItemClick(int position, String title);
}
void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
}
}