需要的知识:RecyclerView的使用,本文章是用了一个RecyclerView来做PopWindow的内容部分
整体项目结构
需要的依赖
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha02'
全局获取上下文
public class BaseApplication extends Application {
private static Context sContext = null;
@Override
public void onCreate() {
super.onCreate();
sContext = getBaseContext();
}
public static Context getContext() {
return sContext;
}
}
在manifest的application中
android:name=".base.BaseApplication"
动画文件(设置popWindow弹出和消失的动画)
styles.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="pop_animation">
<item name="android:windowEnterAnimation">@anim/pop_in</item>
<item name="android:windowExitAnimation">@anim/pop_out</item>
</style>
</resources>
pop_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromYDelta="100%"
android:toYDelta="0"
android:duration="300"/>
<alpha
android:fromAlpha="0.8"
android:toAlpha="1.0"
android:duration="300"/>
</set>
pop_out.xml’
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%" />
<alpha
android:duration="300"
android:fromAlpha="1.0"
android:toAlpha="0.8" />
</set>
自定义的PopWindow
public class MyPopWindow extends PopupWindow {
private final View mPopView;
private TextView mClose_btn;
private RecyclerView mPlayListRv;
private PopListAdapter mPopListAdapter;
@SuppressLint("InflateParams")
public MyPopWindow() {
//调用父类构造函数,设置宽高
super(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//先要设置setBackgroundDrawable,然后setOutsideTouchable才有效果
setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
//点击外部可消失
setOutsideTouchable(true);
//不可点击背景之下的其他按钮
setFocusable(true);
mPopView = LayoutInflater.from(BaseApplication.getContext()).inflate(R.layout.popview_list, null);
setContentView(mPopView);
//设置动画效果
setAnimationStyle(R.style.pop_animation);
//初始化View
initView();
//初始化点击事件
initEvent();
}
private void initView() {
mClose_btn = mPopView.findViewById(R.id.play_list_close_btn);
mPlayListRv = mPopView.findViewById(R.id.play_list_rv);
//设置RecyclerView的显示为线性
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(BaseApplication.getContext());
mPlayListRv.setLayoutManager(linearLayoutManager);
//设置适配器
mPopListAdapter = new PopListAdapter();
mPlayListRv.setAdapter(mPopListAdapter);
}
private void initEvent() {
mClose_btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//点击消失
dismiss();
}
});
}
public void setListData(List<Music> list) {
if (mPopListAdapter != null) {
mPopListAdapter.setData(list);
}
}
public void setCurrentIndex(int index) {
if (mPopListAdapter != null) {
mPopListAdapter.setCurrentPosition(index);
mPlayListRv.scrollToPosition(index);
}
}
//点击的监听
public void setOnItemClickListener(onItemClickListener listener){
mPopListAdapter.setOnItemClickListener(listener);
}
//设置点击接口
public interface onItemClickListener{
void onItemClick(int pos);
}
}
布局代码
popview_list
<?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:background="#fff"
android:orientation="vertical">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/play_list_rv"
android:layout_width="match_parent"
android:layout_height="400dp"/>
<TextView
android:id="@+id/play_list_close_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:paddingTop="8dp"
android:paddingBottom="8dp"
android:textColor="#000"
android:text="关闭"
android:textSize="18sp" />
</LinearLayout>
popview_item
<?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"
android:paddingTop="10dp"
android:paddingBottom="6dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:id="@+id/title_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="20dp"
android:maxLines="1"
android:text="我是标题"
android:textSize="16sp" />
</LinearLayout>
<View
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginTop="10dp"
android:background="#000" />
</LinearLayout>
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
tools:context=".activity.MainActivity">
<Button
android:id="@+id/clickPop"
android:text="点击我弹出popWindow"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
bean类
public class Music {
String title;
public Music(String title){
this.title = title;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
适配器代码
public class PopListAdapter extends RecyclerView.Adapter<PopListAdapter.InnerViewHolder> {
List<Music> mData = new ArrayList<>();
private int mCurrentPosition;
private MyPopWindow.onItemClickListener mCurrentListener;
@NonNull
@Override
public InnerViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.popview_item, parent, false);
return new InnerViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull InnerViewHolder holder, final int position) {
Music music = mData.get(position);
holder.title.setText(music.getTitle());
//设置字体颜色
holder.title.setTextColor(BaseApplication.getContext().getResources().getColor(
mCurrentPosition == position ? R.color.colorAccent : R.color.colorPrimary));
//设置item本身的点击事件
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mCurrentListener.onItemClick(position);
Toast.makeText(BaseApplication.getContext(), "你点击了第"+(mCurrentPosition+1)+"条", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public int getItemCount() {
if (mData != null) {
return mData.size();
}
return 0;
}
public void setData(List<Music> list) {
mData.clear();
mData.addAll(list);
notifyDataSetChanged();
}
public void setCurrentPosition(int index) {
mCurrentPosition = index;
notifyDataSetChanged();
}
public void setOnItemClickListener(MyPopWindow.onItemClickListener listener) {
mCurrentListener = listener;
}
public class InnerViewHolder extends RecyclerView.ViewHolder {
TextView title;
public InnerViewHolder(@NonNull View itemView) {
super(itemView);
title = itemView.findViewById(R.id.title_tv);
}
}
}
控件背景颜色变化的一个工具类(使用时的activity中的背景改变)
public class PopWindowBgChange extends Activity {
public static ValueAnimator mEnterBgAnimator;
public static ValueAnimator mOutBgAnimator;
//背景的渐变动画
public static void initBgAnimation(final Window window) {
//进入
mEnterBgAnimator = ValueAnimator.ofFloat(1.0f,0.7f);
mEnterBgAnimator.setDuration(300);
mEnterBgAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
//LogUtil.e(TAG,"value -> " + animation.getAnimatedValue());
//背景透明度变化
upDateBgAlpha((Float) animation.getAnimatedValue(),window);
}
});
//退出
mOutBgAnimator = ValueAnimator.ofFloat(0.7f,1.0f);
mOutBgAnimator.setDuration(300);
mOutBgAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
upDateBgAlpha((Float) animation.getAnimatedValue(),window);
}
});
}
private static void upDateBgAlpha(float alpha,Window window) {
WindowManager.LayoutParams attributes = window.getAttributes();
attributes.alpha = alpha;
window.setAttributes(attributes);
}
}
MainActivity
public class MainActivity extends AppCompatActivity {
MyPopWindow myPopWindow;
private Button mClickPop;
private List<Music> mMusics = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
PopWindowBgChange.initBgAnimation(getWindow());
}
private void initData() {
//模拟数据
mMusics.add(new Music("1231231"));
mMusics.add(new Music("1231232"));
mMusics.add(new Music("1231233"));
mMusics.add(new Music("1231234"));
mMusics.add(new Music("1231235"));
myPopWindow.setListData(mMusics);
}
private void initView() {
mClickPop = findViewById(R.id.clickPop);
myPopWindow = new MyPopWindow();
mClickPop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//从下到上
myPopWindow.showAtLocation(v, Gravity.BOTTOM,0,0);
PopWindowBgChange.mEnterBgAnimator.start();
}
});
//item点击
myPopWindow.setOnItemClickListener(new MyPopWindow.onItemClickListener() {
@Override
public void onItemClick(int pos) {
myPopWindow.setCurrentIndex(pos);
}
});
//消失监听
myPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
@Override
public void onDismiss() {
PopWindowBgChange.mOutBgAnimator.start();
}
});
}
}