├── .github └── ISSUE_TEMPLATE │ └── bug_report.md ├── .gitignore ├── LICENSE ├── README-en.md ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro ├── src │ └── main │ │ ├── AndroidManifest.xml │ │ ├── java │ │ └── com │ │ │ └── lxj │ │ │ └── xpopupdemo │ │ │ ├── Constants.java │ │ │ ├── DemoActivity.java │ │ │ ├── MainActivity.java │ │ │ ├── PageInfo.java │ │ │ ├── XPopupApp.java │ │ │ ├── custom │ │ │ ├── CustomAttachPopup.java │ │ │ ├── CustomAttachPopup2.java │ │ │ ├── CustomBubbleAttachPopup.java │ │ │ ├── CustomCenter1.java │ │ │ ├── CustomCenterPopup.java │ │ │ ├── CustomDrawerPopupView.java │ │ │ ├── CustomEditTextBottomPopup.java │ │ │ ├── CustomFullScreenPopup.java │ │ │ ├── CustomHorizontalBubbleAttachPopup.java │ │ │ ├── CustomImageViewerPopup.java │ │ │ ├── CustomPartShadowPopupView.java │ │ │ ├── CustomPartShadowPopupView2.java │ │ │ ├── ListDrawerPopupView.java │ │ │ ├── LoginPopup.java │ │ │ ├── NotificationMsgPopup.java │ │ │ ├── PAdapter.java │ │ │ ├── PagerBottomPopup.java │ │ │ ├── PagerDrawerPopup.java │ │ │ ├── QQMsgPopup.java │ │ │ ├── TestFragment.java │ │ │ └── ZhihuCommentPopup.java │ │ │ ├── fragment │ │ │ ├── AllAnimatorDemo.java │ │ │ ├── BaseFragment.java │ │ │ ├── CustomAnimatorDemo.java │ │ │ ├── CustomPopupDemo.java │ │ │ ├── FragmentLifecycleDemo.java │ │ │ ├── ImageViewerDemo.java │ │ │ ├── PartShadowDemo.java │ │ │ └── QuickStartDemo.java │ │ │ └── vm │ │ │ └── DemoVM.java │ │ └── res │ │ ├── drawable │ │ ├── bg_circle.xml │ │ ├── bg_round.xml │ │ ├── bg_round2.xml │ │ ├── bg_toast.xml │ │ ├── ic_launcher_background.xml │ │ └── shadow_bg.9.png │ │ ├── layout │ │ ├── activity_demo.xml │ │ ├── activity_main.xml │ │ ├── adapter_custom_fullscreen_popup.xml │ │ ├── adapter_image.xml │ │ ├── adapter_image2.xml │ │ ├── adapter_text.xml │ │ ├── adapter_zhihu_comment.xml │ │ ├── custom_attach_popup.xml │ │ ├── custom_attach_popup2.xml │ │ ├── custom_base_popup_view.xml │ │ ├── custom_bottom_popup.xml │ │ ├── custom_bubble_attach_popup.xml │ │ ├── custom_drawer_popup.xml │ │ ├── custom_drawer_popup2.xml │ │ ├── custom_edittext_bottom_popup.xml │ │ ├── custom_fullscreen_popup.xml │ │ ├── custom_image_viewer_popup.xml │ │ ├── custom_list_drawer.xml │ │ ├── custom_loading_popup.xml │ │ ├── custom_pager_drawer.xml │ │ ├── custom_part_shadow_popup.xml │ │ ├── custom_part_shadow_popup2.xml │ │ ├── custom_popup.xml │ │ ├── custom_popup2.xml │ │ ├── custom_view_pager.xml │ │ ├── fragment_all_animator_demo.xml │ │ ├── fragment_custom_animator_demo.xml │ │ ├── fragment_image_preview.xml │ │ ├── fragment_lifecycle_demo.xml │ │ ├── fragment_part_shadow_demo.xml │ │ ├── fragment_quickstart.xml │ │ ├── fragment_test.xml │ │ ├── my_confim_popup.xml │ │ ├── my_custom_attach_popup.xml │ │ ├── my_list_popup.xml │ │ ├── my_list_popup_item.xml │ │ ├── my_loading_popup.xml │ │ ├── popup_custom_center.xml │ │ ├── popup_login.xml │ │ ├── popup_notification_msg.xml │ │ ├── popup_qq_msg.xml │ │ ├── temp.xml │ │ └── temp2.xml │ │ ├── mipmap-xxhdpi │ │ ├── arrow.png │ │ ├── dropdown.png │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ └── provider_paths.xml └── xpopup.keystore ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── lxj │ │ └── xpopup │ │ ├── XPopup.java │ │ ├── animator │ │ ├── BlurAnimator.java │ │ ├── EmptyAnimator.java │ │ ├── PopupAnimator.java │ │ ├── ScaleAlphaAnimator.java │ │ ├── ScrollScaleAnimator.java │ │ ├── ShadowBgAnimator.java │ │ ├── TranslateAlphaAnimator.java │ │ └── TranslateAnimator.java │ │ ├── core │ │ ├── AttachPopupView.java │ │ ├── BasePopupView.java │ │ ├── BottomPopupView.java │ │ ├── BubbleAttachPopupView.java │ │ ├── BubbleHorizontalAttachPopupView.java │ │ ├── CenterPopupView.java │ │ ├── DrawerPopupView.java │ │ ├── FullScreenDialog.java │ │ ├── HorizontalAttachPopupView.java │ │ ├── ImageViewerPopupView.java │ │ ├── PopupInfo.java │ │ └── PositionPopupView.java │ │ ├── enums │ │ ├── DragOrientation.java │ │ ├── LayoutStatus.java │ │ ├── PopupAnimation.java │ │ ├── PopupPosition.java │ │ └── PopupStatus.java │ │ ├── impl │ │ ├── AttachListPopupView.java │ │ ├── BottomListPopupView.java │ │ ├── CenterListPopupView.java │ │ ├── ConfirmPopupView.java │ │ ├── FullScreenPopupView.java │ │ ├── InputConfirmPopupView.java │ │ ├── LoadingPopupView.java │ │ └── PartShadowPopupView.java │ │ ├── interfaces │ │ ├── OnCancelListener.java │ │ ├── OnClickOutsideListener.java │ │ ├── OnConfirmListener.java │ │ ├── OnDragChangeListener.java │ │ ├── OnImageViewerLongPressListener.java │ │ ├── OnInputConfirmListener.java │ │ ├── OnSelectListener.java │ │ ├── OnSrcViewUpdateListener.java │ │ ├── SimpleCallback.java │ │ ├── XPopupCallback.java │ │ └── XPopupImageLoader.java │ │ ├── photoview │ │ ├── Compat.java │ │ ├── CustomGestureDetector.java │ │ ├── OnGestureListener.java │ │ ├── OnMatrixChangedListener.java │ │ ├── OnOutsidePhotoTapListener.java │ │ ├── OnPhotoTapListener.java │ │ ├── OnScaleChangedListener.java │ │ ├── OnSingleFlingListener.java │ │ ├── OnViewDragListener.java │ │ ├── OnViewTapListener.java │ │ ├── PhotoView.java │ │ ├── PhotoViewAttacher.java │ │ └── Util.java │ │ ├── util │ │ ├── FuckRomUtils.java │ │ ├── ImageDownloadTarget.java │ │ ├── KeyboardUtils.java │ │ ├── PermissionConstants.java │ │ ├── SSIVListener.java │ │ ├── SmartGlideImageLoader.java │ │ ├── XPermission.java │ │ └── XPopupUtils.java │ │ └── widget │ │ ├── BlankView.java │ │ ├── BubbleLayout.java │ │ ├── CheckView.java │ │ ├── HackyViewPager.java │ │ ├── LoadingView.java │ │ ├── PartShadowContainer.java │ │ ├── PhotoViewContainer.java │ │ ├── PopupDrawerLayout.java │ │ ├── PositionPopupContainer.java │ │ ├── SmartDivider.java │ │ ├── SmartDragLayout.java │ │ └── VerticalRecyclerView.java │ └── res │ ├── layout │ ├── _xpopup_adapter_text.xml │ ├── _xpopup_adapter_text_match.xml │ ├── _xpopup_attach_impl_list.xml │ ├── _xpopup_attach_popup_view.xml │ ├── _xpopup_bottom_impl_list.xml │ ├── _xpopup_bottom_popup_view.xml │ ├── _xpopup_bubble_attach_popup_view.xml │ ├── _xpopup_center_impl_confirm.xml │ ├── _xpopup_center_impl_list.xml │ ├── _xpopup_center_impl_loading.xml │ ├── _xpopup_center_popup_view.xml │ ├── _xpopup_divider.xml │ ├── _xpopup_drawer_popup_view.xml │ ├── _xpopup_fullscreen_popup_view.xml │ ├── _xpopup_image_viewer_popup_view.xml │ ├── _xpopup_partshadow_popup_view.xml │ └── _xpopup_position_popup_view.xml │ ├── values-zh │ └── strings.xml │ └── values │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── reward-list.md ├── screenshot ├── animators.gif ├── attach1.gif ├── attach2.gif ├── background.gif ├── bottom1.gif ├── bottom2.gif ├── bubble.gif ├── custom.gif ├── douyin.png ├── download.png ├── drawer.gif ├── full.gif ├── imageviewer1.gif ├── imageviewer2.gif ├── imageviewer3.gif ├── imageviewer4.gif ├── input.gif ├── inset1.gif ├── inset2.gif ├── logo.png ├── partshadow1.gif ├── partshadow2.gif ├── pay.png ├── position.gif └── search.gif └── settings.gradle /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 如何提Issue 3 | about: 科学的提Issue 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **XPopup版本** 11 | 如2.1.0 12 | 13 | **手机系统和型号** 14 | 华为Mate20 Android 10 15 | 16 | **描述你的问题** 17 | 最好能上代码截图和问题截图 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea 5 | .DS_Store 6 | /build 7 | /captures 8 | .externalNativeBuild 9 | bintray.sh 10 | bintray.bat -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 30 5 | defaultConfig { 6 | applicationId "com.lxj.xpopupdemo" 7 | minSdkVersion 19 8 | targetSdkVersion 30 9 | versionCode 6 10 | versionName xpopup_version 11 | // ndk { 12 | // // 设置支持的SO库架构 13 | // abiFilters 'armeabi-v7a' 14 | // //'x86', 'x86_64' , 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a' 15 | // } 16 | // dataBinding { 17 | // enabled = true 18 | // } 19 | } 20 | signingConfigs { 21 | release { 22 | storeFile file('xpopup.keystore') 23 | storePassword 'xpopup' 24 | keyAlias 'xpopup' 25 | keyPassword 'xpopup' 26 | v1SigningEnabled true 27 | v2SigningEnabled true 28 | } 29 | } 30 | buildTypes { 31 | debug { 32 | minifyEnabled false 33 | signingConfig signingConfigs.release 34 | } 35 | release { 36 | shrinkResources true 37 | minifyEnabled true 38 | signingConfig signingConfigs.release 39 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 40 | } 41 | } 42 | lintOptions { 43 | checkReleaseBuilds false 44 | abortOnError false 45 | } 46 | 47 | applicationVariants.all { variant -> 48 | variant.outputs.each { output -> 49 | output.outputFileName = "XPopup-" + xpopup_version +"-" + new Date().format('yyyyMMdd') + ".apk" 50 | // System.out.println(output) 输出属性 51 | } 52 | } 53 | } 54 | 55 | dependencies { 56 | implementation fileTree(include: ['*.jar'], dir: 'libs') 57 | implementation 'com.github.li-xiaojun:EasyAdapter:1.2.8' 58 | implementation 'com.github.li-xiaojun:StateLayout:1.3.4' 59 | implementation 'com.github.bumptech.glide:glide:4.12.0' 60 | implementation 'com.blankj:utilcodex:1.31.1' 61 | implementation "androidx.cardview:cardview:1.0.0" 62 | implementation "androidx.constraintlayout:constraintlayout:2.0.4" 63 | 64 | implementation 'androidx.appcompat:appcompat:1.3.1' 65 | implementation 'com.google.android.material:material:1.4.0' 66 | implementation 'androidx.recyclerview:recyclerview:1.2.1' 67 | // implementation "androidx.viewpager2:viewpager2:1.0.0" 68 | implementation "com.umeng.umsdk:common:9.4.4" 69 | implementation "com.umeng.umsdk:asms:1.4.1" // asms包依赖(必选) 70 | implementation "com.umeng.umsdk:apm:1.5.2" // U-APM产品包依赖(必选) 71 | 72 | implementation project(':library') 73 | // implementation 'com.github.li-xiaojun:XPopup:2.9.0' 74 | // implementation 'io.github.li-xiaojun:xpopup:2.9.4' 75 | 76 | } 77 | 78 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -dontwarn com.lxj.xpopup.widget.** 23 | -keep class com.lxj.xpopup.widget.**{*;} 24 | -dontwarn com.tencent.bugly.** 25 | -keep public class com.tencent.bugly.**{*;} 26 | -keep class android.support.**{*;} -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 20 | 21 | 22 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/Constants.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo; 2 | 3 | import java.util.ArrayList; 4 | 5 | public class Constants { 6 | 7 | public static ArrayList list = new ArrayList<>(); 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/PageInfo.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo; 2 | 3 | import com.lxj.xpopupdemo.fragment.BaseFragment; 4 | 5 | /** 6 | * Description: 7 | * Create by dance, at 2018/12/9 8 | */ 9 | public class PageInfo { 10 | public String title; 11 | public BaseFragment fragment; 12 | 13 | public PageInfo(String title, BaseFragment fragment) { 14 | this.title = title; 15 | this.fragment = fragment; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/XPopupApp.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo; 2 | 3 | import android.app.Application; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.view.Gravity; 7 | import com.blankj.utilcode.util.ToastUtils; 8 | import com.umeng.analytics.MobclickAgent; 9 | import com.umeng.commonsdk.UMConfigure; 10 | 11 | /** 12 | * Description: 13 | * Create by dance, at 2019/1/1 14 | */ 15 | public class XPopupApp extends Application { 16 | public static Context context; 17 | 18 | @Override 19 | public void onCreate() { 20 | super.onCreate(); 21 | context = this; 22 | UMConfigure.init(this, "60e2b78726a57f101846a2c2", "UMENG_CHANNEL", UMConfigure.DEVICE_TYPE_PHONE, ""); 23 | MobclickAgent.setPageCollectionMode(MobclickAgent.PageMode.AUTO); 24 | ToastUtils.getDefaultMaker().setGravity(Gravity.CENTER, 0 , 0); 25 | ToastUtils.getDefaultMaker().setBgResource(R.drawable.bg_toast); 26 | ToastUtils.getDefaultMaker().setTextColor(Color.WHITE); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomAttachPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | import com.lxj.xpopup.core.HorizontalAttachPopupView; 8 | import com.lxj.xpopupdemo.R; 9 | import com.lxj.xpopupdemo.XPopupApp; 10 | 11 | /** 12 | * Description: 自定义Attach弹窗,水平方向的 13 | * Create by lxj, at 2019/3/13 14 | */ 15 | public class CustomAttachPopup extends HorizontalAttachPopupView { 16 | public CustomAttachPopup(@NonNull Context context) { 17 | super(context); 18 | } 19 | 20 | @Override 21 | protected int getImplLayoutId() { 22 | return R.layout.custom_attach_popup; 23 | } 24 | 25 | @Override 26 | protected void onCreate() { 27 | super.onCreate(); 28 | findViewById(R.id.tv_zan).setOnClickListener(new OnClickListener() { 29 | @Override 30 | public void onClick(View v) { 31 | Toast.makeText(XPopupApp.context, "赞", Toast.LENGTH_LONG).show(); 32 | dismiss(); 33 | } 34 | }); 35 | findViewById(R.id.tv_comment).setOnClickListener(new OnClickListener() { 36 | @Override 37 | public void onClick(View v) { 38 | Toast.makeText(XPopupApp.context, "评论", Toast.LENGTH_LONG).show(); 39 | dismiss(); 40 | } 41 | }); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomAttachPopup2.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | import androidx.annotation.NonNull; 7 | import com.lxj.xpopup.core.AttachPopupView; 8 | import com.lxj.xpopupdemo.R; 9 | 10 | import java.util.Random; 11 | 12 | /** 13 | * Description: 自定义背景的Attach弹窗 14 | * Create by lxj, at 2019/3/13 15 | */ 16 | public class CustomAttachPopup2 extends AttachPopupView { 17 | public CustomAttachPopup2(@NonNull Context context) { 18 | super(context); 19 | } 20 | 21 | @Override 22 | protected int getImplLayoutId() { 23 | return R.layout.custom_attach_popup2; 24 | } 25 | 26 | @Override 27 | protected void onCreate() { 28 | super.onCreate(); 29 | final TextView tv = findViewById(R.id.tv); 30 | tv.setOnClickListener(new OnClickListener() { 31 | @Override 32 | public void onClick(View v) { 33 | // tv.setText(tv.getText() + "\n 啊哈哈哈啊哈"); 34 | // tv.setText("\n 啊哈哈哈啊哈"); 35 | } 36 | }); 37 | } 38 | 39 | // @Override 40 | // protected int getPopupWidth() { 41 | // return XPopupUtils.getAppWidth(getContext()); 42 | // } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomBubbleAttachPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import androidx.annotation.NonNull; 10 | 11 | import com.bumptech.glide.Glide; 12 | import com.lxj.xpopup.core.BubbleAttachPopupView; 13 | import com.lxj.xpopup.util.XPopupUtils; 14 | import com.lxj.xpopupdemo.R; 15 | 16 | /** 17 | * Description: 自定义气泡Attach弹窗 18 | * Create by lxj, at 2019/3/13 19 | */ 20 | public class CustomBubbleAttachPopup extends BubbleAttachPopupView { 21 | public CustomBubbleAttachPopup(@NonNull Context context) { 22 | super(context); 23 | } 24 | 25 | @Override 26 | protected int getImplLayoutId() { 27 | return R.layout.custom_bubble_attach_popup; 28 | } 29 | 30 | @Override 31 | protected void onCreate() { 32 | super.onCreate(); 33 | setBubbleBgColor(Color.BLUE); 34 | setBubbleShadowSize(XPopupUtils.dp2px(getContext(), 6)); 35 | setBubbleShadowColor(Color.RED); 36 | setArrowWidth(XPopupUtils.dp2px(getContext(), 8)); 37 | setArrowHeight(XPopupUtils.dp2px(getContext(), 9)); 38 | // .setBubbleRadius(100) 39 | setArrowRadius(XPopupUtils.dp2px(getContext(), 2)); 40 | final TextView tv = findViewById(R.id.tv); 41 | Glide.with(getContext()).load("https://t7.baidu.com/it/u=963301259,1982396977&fm=193&f=GIF").into((ImageView) findViewById(R.id.image)); 42 | tv.setOnClickListener(new OnClickListener() { 43 | @Override 44 | public void onClick(View v) { 45 | // tv.setText(tv.getText() + "\n 啊哈哈哈啊哈"); 46 | // tv.setText("\n 啊哈哈哈啊哈"); 47 | dismiss(); 48 | } 49 | }); 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomCenter1.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.lxj.xpopup.core.CenterPopupView; 8 | import com.lxj.xpopupdemo.R; 9 | 10 | public class CustomCenter1 extends CenterPopupView { 11 | public CustomCenter1(@NonNull Context context) { 12 | super(context); 13 | } 14 | 15 | @Override 16 | protected int getImplLayoutId() { 17 | return R.layout.temp2; 18 | } 19 | 20 | @Override 21 | protected int getMaxWidth() { 22 | return 0; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomCenterPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | import com.lxj.xpopup.core.CenterPopupView; 6 | import com.lxj.xpopupdemo.R; 7 | 8 | public class CustomCenterPopup extends CenterPopupView { 9 | public CustomCenterPopup(@NonNull Context context) { 10 | super(context); 11 | } 12 | 13 | @Override 14 | protected int getImplLayoutId() { 15 | return R.layout.popup_custom_center; 16 | } 17 | 18 | 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomDrawerPopupView.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.app.Activity; 4 | import android.content.Context; 5 | import android.graphics.Color; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.lifecycle.LifecycleObserver; 13 | 14 | import com.lxj.easyadapter.EasyAdapter; 15 | import com.lxj.easyadapter.ViewHolder; 16 | import com.lxj.xpopup.XPopup; 17 | import com.lxj.xpopup.core.DrawerPopupView; 18 | import com.lxj.xpopup.interfaces.OnConfirmListener; 19 | import com.lxj.xpopup.widget.VerticalRecyclerView; 20 | import com.lxj.xpopupdemo.R; 21 | 22 | import java.util.ArrayList; 23 | 24 | /** 25 | * Description: 自定义抽屉弹窗 26 | * Create by dance, at 2018/12/20 27 | */ 28 | public class CustomDrawerPopupView extends DrawerPopupView { 29 | TextView text; 30 | 31 | public CustomDrawerPopupView(@NonNull Context context) { 32 | super(context); 33 | } 34 | 35 | @Override 36 | protected int getImplLayoutId() { 37 | return R.layout.custom_drawer_popup2; 38 | } 39 | 40 | @Override 41 | protected void onCreate() { 42 | super.onCreate(); 43 | // CustomDrawerPopup2Binding.bind(getPopupImplView()); 44 | Log.e("tag", "CustomDrawerPopupView onCreate"); 45 | // text = findViewById(R.id.text); 46 | // findViewById(R.id.btn).setOnClickListener(new OnClickListener() { 47 | // @Override 48 | // public void onClick(View v) { 49 | // dismiss(); 50 | // } 51 | // }); 52 | 53 | //通过设置topMargin,可以让Drawer弹窗进行局部阴影展示 54 | // setPadding(0, 400, 0, 0); 55 | 56 | VerticalRecyclerView rv = findViewById(R.id.rv); 57 | ArrayList list = new ArrayList(); 58 | for (int i = 0; i < 200; i++) { 59 | list.add(i + ""); 60 | } 61 | rv.setAdapter(new EasyAdapter(list, R.layout.temp) { 62 | @Override 63 | protected void bind(ViewHolder viewHolder, Object o, int i) { 64 | if (i % 2 == 0) { 65 | viewHolder.getView(R.id.text).setText("aa - " + i); 66 | viewHolder.getView(R.id.text).setBackgroundColor(Color.WHITE); 67 | } else { 68 | viewHolder.getView(R.id.text).setText("aa - " + i + "大萨达所撒多" + 69 | "\n大萨达所撒多大萨达所撒多"); 70 | viewHolder.getView(R.id.text).setBackgroundColor(Color.RED); 71 | 72 | } 73 | } 74 | }); 75 | findViewById(R.id.btnMe).setOnClickListener(new OnClickListener() { 76 | @Override 77 | public void onClick(View v) { 78 | new XPopup.Builder(getContext()).isDestroyOnDismiss(true) 79 | .asConfirm("提示", "确定要退出吗?", new OnConfirmListener() { 80 | @Override 81 | public void onConfirm() { 82 | ((Activity)getContext()).finish(); 83 | dismiss(); 84 | } 85 | }).show(); 86 | } 87 | }); 88 | } 89 | 90 | @Override 91 | protected void onShow() { 92 | super.onShow(); 93 | // text.setText(new Random().nextInt()+""); 94 | Log.e("tag", "CustomDrawerPopupView onShow"); 95 | } 96 | 97 | @Override 98 | protected void onDismiss() { 99 | super.onDismiss(); 100 | Log.e("tag", "CustomDrawerPopupView onDismiss"); 101 | } 102 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomEditTextBottomPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | 6 | import android.view.KeyEvent; 7 | import android.view.View; 8 | import android.widget.EditText; 9 | 10 | import com.blankj.utilcode.util.ToastUtils; 11 | import com.lxj.xpopup.XPopup; 12 | import com.lxj.xpopup.core.BottomPopupView; 13 | import com.lxj.xpopup.interfaces.OnInputConfirmListener; 14 | import com.lxj.xpopupdemo.R; 15 | import com.lxj.xpopupdemo.fragment.QuickStartDemo; 16 | 17 | /** 18 | * Description: 自定义带有输入框的Bottom弹窗 19 | * Create by dance, at 2019/2/27 20 | */ 21 | public class CustomEditTextBottomPopup extends BottomPopupView { 22 | public CustomEditTextBottomPopup(@NonNull Context context) { 23 | super(context); 24 | } 25 | 26 | @Override 27 | protected int getImplLayoutId() { 28 | return R.layout.custom_edittext_bottom_popup; 29 | } 30 | 31 | @Override 32 | protected void onCreate() { 33 | super.onCreate(); 34 | findViewById(R.id.btn_finish).setOnClickListener(new OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | dismiss(); 38 | } 39 | }); 40 | // 41 | // setOnKeyListener(new OnKeyListener() { 42 | // @Override 43 | // public boolean onKey(View v, int keyCode, KeyEvent event) { 44 | // if(keyCode==KeyEvent.KEYCODE_BACK){ 45 | // ToastUtils.showShort("自定义弹窗设置了KeyListener"); 46 | // return true; 47 | // } 48 | // return true; 49 | // } 50 | // }); 51 | } 52 | 53 | @Override 54 | protected void onShow() { 55 | super.onShow(); 56 | } 57 | 58 | @Override 59 | protected void onDismiss() { 60 | super.onDismiss(); 61 | // Log.e("tag", "CustomEditTextBottomPopup onDismiss"); 62 | } 63 | 64 | public String getComment(){ 65 | EditText et = findViewById(R.id.et_comment); 66 | return et.getText().toString(); 67 | } 68 | 69 | // @Override 70 | // protected int getMaxHeight() { 71 | // return (int) (XPopupUtils.getWindowHeight(getContext())*0.75); 72 | // } 73 | } 74 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomFullScreenPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import androidx.annotation.NonNull; 7 | import com.lxj.xpopup.impl.FullScreenPopupView; 8 | import com.lxj.xpopupdemo.R; 9 | 10 | /** 11 | * Description: 自定义全屏弹窗 12 | * Create by lxj, at 2019/3/12 13 | */ 14 | public class CustomFullScreenPopup extends FullScreenPopupView { 15 | public CustomFullScreenPopup(@NonNull Context context) { 16 | super(context); 17 | } 18 | 19 | @Override 20 | protected int getImplLayoutId() { 21 | return R.layout.custom_fullscreen_popup; 22 | } 23 | 24 | @Override 25 | protected void onShow() { 26 | super.onShow(); 27 | Log.e("tag", "CustomFullScreenPopup onShow"); 28 | } 29 | @Override 30 | protected void onDismiss() { 31 | super.onDismiss(); 32 | Log.e("tag", "CustomFullScreenPopup onDismiss"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomHorizontalBubbleAttachPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | import androidx.annotation.NonNull; 8 | import com.lxj.xpopup.core.BubbleHorizontalAttachPopupView; 9 | import com.lxj.xpopup.util.XPopupUtils; 10 | import com.lxj.xpopupdemo.R; 11 | import com.lxj.xpopupdemo.XPopupApp; 12 | 13 | /** 14 | * Description: 自定义Attach弹窗,水平方向的带气泡的弹窗 15 | * Create by lxj, at 2019/3/13 16 | */ 17 | public class CustomHorizontalBubbleAttachPopup extends BubbleHorizontalAttachPopupView { 18 | public CustomHorizontalBubbleAttachPopup(@NonNull Context context) { 19 | super(context); 20 | } 21 | 22 | @Override 23 | protected int getImplLayoutId() { 24 | return R.layout.custom_attach_popup; 25 | } 26 | 27 | @Override 28 | protected void onCreate() { 29 | super.onCreate(); 30 | setBubbleBgColor(Color.parseColor("#4D5063")); 31 | setBubbleShadowSize(XPopupUtils.dp2px(getContext(), 3)); 32 | setBubbleShadowColor(Color.BLACK); 33 | getPopupImplView().setBackgroundResource(0); 34 | findViewById(R.id.tv_zan).setOnClickListener(new OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | Toast.makeText(XPopupApp.context, "赞", Toast.LENGTH_LONG).show(); 38 | dismiss(); 39 | } 40 | }); 41 | findViewById(R.id.tv_comment).setOnClickListener(new OnClickListener() { 42 | @Override 43 | public void onClick(View v) { 44 | Toast.makeText(XPopupApp.context, "评论", Toast.LENGTH_LONG).show(); 45 | dismiss(); 46 | } 47 | }); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomImageViewerPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | import androidx.annotation.NonNull; 9 | 10 | import com.blankj.utilcode.util.ToastUtils; 11 | import com.lxj.xpopup.XPopup; 12 | import com.lxj.xpopup.core.ImageViewerPopupView; 13 | import com.lxj.xpopup.interfaces.OnSelectListener; 14 | import com.lxj.xpopupdemo.R; 15 | 16 | /** 17 | * Description: 自定义大图浏览弹窗 18 | * Create by dance, at 2019/5/8 19 | */ 20 | public class CustomImageViewerPopup extends ImageViewerPopupView { 21 | public CustomImageViewerPopup(@NonNull Context context) { 22 | super(context); 23 | } 24 | 25 | @Override 26 | protected int getImplLayoutId() { 27 | return R.layout.custom_image_viewer_popup; 28 | } 29 | 30 | @Override 31 | protected void onCreate() { 32 | super.onCreate(); 33 | // tv_pager_indicator.setVisibility(GONE); 34 | findViewById(R.id.tvClickMe).setOnClickListener(new OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | new XPopup.Builder(getContext()).asBottomList("提示", new String[]{"保存照片"}, new OnSelectListener() { 38 | @Override 39 | public void onSelect(int position, String text) { 40 | ToastUtils.showLong("你自己实现保存照片"); 41 | } 42 | }).show(); 43 | } 44 | }); 45 | } 46 | 47 | @Override 48 | protected void onShow() { 49 | super.onShow(); 50 | Log.e("tag","CustomImageViewerPopup onShow"); 51 | } 52 | 53 | @Override 54 | protected void onDismiss() { 55 | super.onDismiss(); 56 | Log.e("tag","CustomImageViewerPopup onDismiss"); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomPartShadowPopupView.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.TextView; 7 | import androidx.annotation.NonNull; 8 | import com.lxj.xpopup.impl.PartShadowPopupView; 9 | import com.lxj.xpopupdemo.R; 10 | 11 | /** 12 | * Description: 自定义局部阴影弹窗 13 | * Create by dance, at 2018/12/21 14 | */ 15 | public class CustomPartShadowPopupView extends PartShadowPopupView { 16 | public CustomPartShadowPopupView(@NonNull Context context) { 17 | super(context); 18 | } 19 | @Override 20 | protected int getImplLayoutId() { 21 | return R.layout.custom_part_shadow_popup; 22 | } 23 | 24 | TextView text; 25 | @Override 26 | protected void onCreate() { 27 | super.onCreate(); 28 | text = findViewById(R.id.text); 29 | Log.e("tag","CustomPartShadowPopupView onCreate"); 30 | findViewById(R.id.btnClose).setOnClickListener(new OnClickListener() { 31 | @Override 32 | public void onClick(View v) { 33 | dismiss(); 34 | } 35 | }); 36 | findViewById(R.id.ch).setOnClickListener(new OnClickListener() { 37 | @Override 38 | public void onClick(View v) { 39 | text.setText(text.getText()+"\n 啦啦啦啦啦啦"); 40 | 41 | } 42 | }); 43 | } 44 | 45 | @Override 46 | protected void onShow() { 47 | super.onShow(); 48 | Log.e("tag","CustomPartShadowPopupView onShow"); 49 | } 50 | 51 | @Override 52 | protected void onDismiss() { 53 | super.onDismiss(); 54 | Log.e("tag","CustomPartShadowPopupView onDismiss"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/CustomPartShadowPopupView2.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.view.ViewGroup; 5 | import android.widget.FrameLayout; 6 | 7 | import androidx.annotation.NonNull; 8 | 9 | import com.lxj.xpopup.impl.PartShadowPopupView; 10 | import com.lxj.xpopupdemo.R; 11 | 12 | /** 13 | * Description: 自定义局部阴影弹窗 14 | * Create by dance, at 2018/12/21 15 | */ 16 | public class CustomPartShadowPopupView2 extends PartShadowPopupView { 17 | int gravity; 18 | public CustomPartShadowPopupView2(@NonNull Context context, int gravity) { 19 | super(context); 20 | this.gravity = gravity; 21 | } 22 | @Override 23 | protected int getImplLayoutId() { 24 | return R.layout.custom_part_shadow_popup2; 25 | } 26 | 27 | @Override 28 | protected void onCreate() { 29 | super.onCreate(); 30 | FrameLayout.LayoutParams params = (LayoutParams) findViewById(R.id.ll).getLayoutParams(); 31 | params.gravity = gravity; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/ListDrawerPopupView.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import androidx.annotation.NonNull; 5 | import androidx.fragment.app.FragmentActivity; 6 | import androidx.lifecycle.MutableLiveData; 7 | import androidx.lifecycle.Observer; 8 | import androidx.lifecycle.ViewModel; 9 | import androidx.lifecycle.ViewModelProvider; 10 | import androidx.recyclerview.widget.LinearLayoutManager; 11 | import androidx.recyclerview.widget.RecyclerView; 12 | 13 | import android.os.Handler; 14 | import android.util.Log; 15 | import android.view.View; 16 | import android.widget.Button; 17 | import android.widget.Toast; 18 | 19 | import com.lxj.easyadapter.EasyAdapter; 20 | import com.lxj.easyadapter.ViewHolder; 21 | import com.lxj.xpopup.core.DrawerPopupView; 22 | import com.lxj.xpopup.util.XPopupUtils; 23 | import com.lxj.xpopupdemo.R; 24 | import com.lxj.xpopupdemo.vm.DemoVM; 25 | 26 | import java.util.ArrayList; 27 | import java.util.Random; 28 | 29 | /** 30 | * Description: 自定义带列表的Drawer弹窗 31 | * Create by dance, at 2019/1/9 32 | */ 33 | public class ListDrawerPopupView extends DrawerPopupView { 34 | RecyclerView recyclerView; 35 | public ListDrawerPopupView(@NonNull Context context) { 36 | super(context); 37 | } 38 | 39 | @Override 40 | protected int getImplLayoutId() { 41 | return R.layout.custom_list_drawer; 42 | } 43 | final ArrayList data = new ArrayList<>(); 44 | 45 | DemoVM demoVM; 46 | @Override 47 | protected void onCreate() { 48 | demoVM = new ViewModelProvider(((FragmentActivity)getContext())).get(DemoVM.class); 49 | recyclerView = findViewById(R.id.recyclerView); 50 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 51 | 52 | for (int i = 0; i < 50; i++) { 53 | data.add(""+i); 54 | } 55 | 56 | final Button button = findViewById(R.id.btn); 57 | final EasyAdapter commonAdapter = new EasyAdapter(data, android.R.layout.simple_list_item_1) { 58 | @Override 59 | protected void bind(@NonNull ViewHolder holder, @NonNull String s, int position) { 60 | holder.setText(android.R.id.text1, s); 61 | } 62 | }; 63 | demoVM.liveData.observe(this, new Observer() { 64 | @Override 65 | public void onChanged(String s) { 66 | button.setText(s); 67 | Toast.makeText(getContext(), "弹窗onResume时才收到数据更新", Toast.LENGTH_SHORT).show(); 68 | Log.e("tag", "liveData onChange: "+ s); 69 | } 70 | }); 71 | recyclerView.setAdapter(commonAdapter); 72 | button.setOnClickListener(new OnClickListener() { 73 | @Override 74 | public void onClick(View v) { 75 | // if(data.size()==0)return; 76 | // data.remove(0); 77 | // commonAdapter.notifyDataSetChanged(); 78 | dismiss(); 79 | new Handler().postDelayed(new Runnable() { 80 | @Override 81 | public void run() { 82 | demoVM.liveData.postValue(new Random().nextInt(10000)+""); 83 | } 84 | },1000); 85 | 86 | } 87 | }); 88 | 89 | } 90 | 91 | @Override 92 | protected int getMaxWidth() { 93 | return XPopupUtils.getScreenWidth(getContext()) - 100; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/LoginPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.view.KeyEvent; 5 | import android.view.View; 6 | import android.widget.Button; 7 | import android.widget.EditText; 8 | import android.widget.Toast; 9 | import androidx.annotation.NonNull; 10 | import com.lxj.xpopup.XPopup; 11 | import com.lxj.xpopup.core.CenterPopupView; 12 | import com.lxj.xpopup.interfaces.OnSelectListener; 13 | import com.lxj.xpopupdemo.R; 14 | 15 | public class LoginPopup extends CenterPopupView { 16 | public LoginPopup(@NonNull Context context) { 17 | super(context); 18 | } 19 | 20 | @Override 21 | protected int getImplLayoutId() { 22 | return R.layout.popup_login; 23 | } 24 | 25 | @Override 26 | protected void onCreate() { 27 | super.onCreate(); 28 | Button button = findViewById(R.id.btnSelect); 29 | button.setOnClickListener(new OnClickListener() { 30 | @Override 31 | public void onClick(View v) { 32 | new XPopup.Builder(getContext()) 33 | .hasShadowBg(false) 34 | .isRequestFocus(false) 35 | .atView(v) 36 | .asAttachList(new String[]{"1", "2", "3", "4"}, null, new OnSelectListener() { 37 | @Override 38 | public void onSelect(int position, String text) { 39 | 40 | } 41 | }).show(); 42 | } 43 | }); 44 | EditText etName = findViewById(R.id.etName); 45 | etName.setOnKeyListener(new OnKeyListener() { 46 | @Override 47 | public boolean onKey(View v, int keyCode, KeyEvent event) { 48 | if (keyCode==KeyEvent.KEYCODE_DEL){ 49 | Toast.makeText(getContext(), "按了删除键", Toast.LENGTH_SHORT).show(); 50 | return true; 51 | } 52 | return false; 53 | } 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/NotificationMsgPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.view.View; 5 | 6 | import androidx.annotation.NonNull; 7 | import com.blankj.utilcode.util.ScreenUtils; 8 | import com.lxj.xpopup.core.PositionPopupView; 9 | import com.lxj.xpopupdemo.R; 10 | 11 | /** 12 | * Description: 自定义自由定位Position弹窗 13 | * Create by dance, at 2019/6/14 14 | */ 15 | public class NotificationMsgPopup extends PositionPopupView { 16 | public NotificationMsgPopup(@NonNull Context context) { 17 | super(context); 18 | } 19 | 20 | @Override 21 | protected int getImplLayoutId() { 22 | return R.layout.popup_notification_msg; 23 | } 24 | 25 | @Override 26 | protected void onCreate() { 27 | super.onCreate(); 28 | findViewById(R.id.tvClose).setOnClickListener(new OnClickListener() { 29 | @Override 30 | public void onClick(View v) { 31 | dismiss(); 32 | } 33 | }); 34 | } 35 | 36 | @Override 37 | protected int getPopupWidth() { 38 | return ScreenUtils.getScreenWidth(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/PAdapter.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import androidx.annotation.NonNull; 4 | import androidx.fragment.app.Fragment; 5 | import androidx.fragment.app.FragmentManager; 6 | import androidx.fragment.app.FragmentPagerAdapter; 7 | 8 | public class PAdapter extends FragmentPagerAdapter { 9 | String[] titles; 10 | public PAdapter(@NonNull FragmentManager fm) { 11 | super(fm); 12 | } 13 | 14 | public PAdapter(@NonNull FragmentManager fm, String[] titles) { 15 | super(fm); 16 | this.titles = titles; 17 | } 18 | 19 | 20 | @Override 21 | public int getCount() { 22 | return 6; 23 | } 24 | 25 | @Override 26 | public Fragment getItem(int position) { 27 | return TestFragment.create("XPopup默认是Dialog实现,由于Android的限制,Dialog中默认无法使用Fragment。\n\n所以要想在弹窗中使用Fragment,要设置isViewMode(true)."); 28 | } 29 | 30 | @Override 31 | public CharSequence getPageTitle(int position) { 32 | return titles!=null ? titles[position] : "xpopup"; 33 | } 34 | } -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/PagerBottomPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context;; 4 | import android.util.Log; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.ImageView; 9 | import android.widget.LinearLayout; 10 | import android.widget.TextView; 11 | 12 | import androidx.annotation.NonNull; 13 | import androidx.annotation.Nullable; 14 | import androidx.core.widget.NestedScrollView; 15 | import androidx.fragment.app.Fragment; 16 | import androidx.fragment.app.FragmentActivity; 17 | import androidx.fragment.app.FragmentManager; 18 | import androidx.fragment.app.FragmentPagerAdapter; 19 | import androidx.viewpager.widget.PagerAdapter; 20 | import androidx.viewpager.widget.ViewPager; 21 | 22 | import com.lxj.xpopup.core.BottomPopupView; 23 | import com.lxj.xpopup.util.XPopupUtils; 24 | import com.lxj.xpopupdemo.R; 25 | 26 | import java.util.ArrayList; 27 | import java.util.List; 28 | 29 | 30 | /** 31 | * Description: 自定义带有ViewPager的Bottom弹窗 32 | * Create by dance, at 2019/5/5 33 | */ 34 | public class PagerBottomPopup extends BottomPopupView { 35 | public PagerBottomPopup(@NonNull Context context) { 36 | super(context); 37 | } 38 | 39 | @Override 40 | protected int getImplLayoutId() { 41 | return R.layout.custom_view_pager; 42 | } 43 | 44 | ViewPager pager; 45 | 46 | @Override 47 | protected void onCreate() { 48 | super.onCreate(); 49 | pager = findViewById(R.id.pager); 50 | FragmentActivity activity = (FragmentActivity) getContext(); 51 | pager.setAdapter(new PAdapter(activity.getSupportFragmentManager())); 52 | 53 | // ViewGroup.MarginLayoutParams params = (MarginLayoutParams) getPopupContentView().getLayoutParams(); 54 | // params.bottomMargin = 200; 55 | // getPopupContentView().setLayoutParams(params); 56 | } 57 | 58 | @Override 59 | protected List getInternalFragmentNames() { 60 | ArrayList list = new ArrayList<>(); 61 | list.add(TestFragment.class.getSimpleName()); 62 | return list; 63 | } 64 | 65 | @Override 66 | protected void onShow() { 67 | super.onShow(); 68 | } 69 | 70 | @Override 71 | protected void onDismiss() { 72 | super.onDismiss(); 73 | } 74 | 75 | @Override 76 | protected int getMaxHeight() { 77 | return (int) (XPopupUtils.getScreenHeight(getContext())*.85f); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/PagerDrawerPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | 6 | import androidx.annotation.NonNull; 7 | import androidx.fragment.app.FragmentActivity; 8 | import androidx.viewpager.widget.ViewPager; 9 | 10 | import com.google.android.material.tabs.TabLayout; 11 | import com.lxj.xpopup.core.DrawerPopupView; 12 | import com.lxj.xpopupdemo.R; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | 17 | 18 | /** 19 | * Description: 自定义带有ViewPager的Drawer弹窗 20 | * Create by dance, at 2019/5/5 21 | */ 22 | public class PagerDrawerPopup extends DrawerPopupView { 23 | public PagerDrawerPopup(@NonNull Context context) { 24 | super(context); 25 | } 26 | 27 | @Override 28 | protected int getImplLayoutId() { 29 | return R.layout.custom_pager_drawer; 30 | } 31 | 32 | TabLayout tabLayout; 33 | ViewPager pager; 34 | String[] titles = new String[]{"首页", "娱乐", "汽车", "八卦", "搞笑", "互联网"}; 35 | @Override 36 | protected void onCreate() { 37 | super.onCreate(); 38 | tabLayout = findViewById(R.id.tabLayout); 39 | pager = findViewById(R.id.pager); 40 | pager.setOffscreenPageLimit(titles.length); 41 | FragmentActivity activity = (FragmentActivity) getContext(); 42 | pager.setAdapter(new PAdapter(activity.getSupportFragmentManager(), titles)); 43 | tabLayout.setupWithViewPager(pager); 44 | } 45 | 46 | @Override 47 | protected List getInternalFragmentNames() { 48 | ArrayList list = new ArrayList<>(); 49 | list.add(TestFragment.class.getSimpleName()); 50 | return list; 51 | } 52 | 53 | @Override 54 | protected void onShow() { 55 | super.onShow(); 56 | Log.e("tag", "PagerDrawerPopup onShow"); 57 | } 58 | 59 | @Override 60 | protected void onDismiss() { 61 | super.onDismiss(); 62 | Log.e("tag", "PagerDrawerPopup onDismiss"); 63 | } 64 | 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/QQMsgPopup.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.content.Context; 4 | 5 | import androidx.annotation.NonNull; 6 | 7 | import com.lxj.xpopup.core.PositionPopupView; 8 | import com.lxj.xpopup.enums.DragOrientation; 9 | import com.lxj.xpopupdemo.R; 10 | 11 | /** 12 | * Description: 自定义自由定位Position弹窗 13 | * Create by dance, at 2019/6/14 14 | */ 15 | public class QQMsgPopup extends PositionPopupView { 16 | public QQMsgPopup(@NonNull Context context) { 17 | super(context); 18 | } 19 | 20 | @Override 21 | protected int getImplLayoutId() { 22 | return R.layout.popup_qq_msg; 23 | } 24 | 25 | @Override 26 | protected DragOrientation getDragOrientation() { 27 | return DragOrientation.DragToLeft; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/custom/TestFragment.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.custom; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.TextView; 6 | import com.lxj.xpopupdemo.R; 7 | import com.lxj.xpopupdemo.fragment.BaseFragment; 8 | 9 | 10 | public class TestFragment extends BaseFragment { 11 | 12 | public static TestFragment create(String text){ 13 | TestFragment testFragment = new TestFragment(); 14 | Bundle bundle = new Bundle(); 15 | bundle.putString("text", text); 16 | testFragment.setArguments(bundle); 17 | return testFragment; 18 | } 19 | 20 | @Override 21 | protected int getLayoutId() { 22 | return R.layout.fragment_test; 23 | } 24 | 25 | @Override 26 | public void init(View view) { 27 | String text = getArguments().getString("text", "XPopup"); 28 | view.findViewById(R.id.tv).setText(text); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/fragment/AllAnimatorDemo.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.fragment; 2 | 3 | import android.view.View; 4 | import android.widget.AdapterView; 5 | import android.widget.ArrayAdapter; 6 | import android.widget.Spinner; 7 | 8 | import com.lxj.xpopup.XPopup; 9 | import com.lxj.xpopup.enums.PopupAnimation; 10 | import com.lxj.xpopupdemo.R; 11 | 12 | /** 13 | * Description: 14 | * Create by dance, at 2018/12/9 15 | */ 16 | public class AllAnimatorDemo extends BaseFragment { 17 | Spinner spinner; 18 | @Override 19 | protected int getLayoutId() { 20 | return R.layout.fragment_all_animator_demo; 21 | } 22 | PopupAnimation[] data; 23 | @Override 24 | public void init(View view) { 25 | spinner = view.findViewById(R.id.spinner); 26 | 27 | data = PopupAnimation.values(); 28 | spinner.setAdapter(new ArrayAdapter(getContext(), android.R.layout.simple_list_item_1, data)); 29 | spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { 30 | @Override 31 | public void onItemSelected(AdapterView parent, View view, final int position, long id) { 32 | spinner.postDelayed(new Runnable() { 33 | @Override 34 | public void run() { 35 | new XPopup.Builder(getContext()) 36 | .popupAnimation(data[position]) 37 | .asConfirm("演示应用不同的动画", "你可以为弹窗选择任意一种动画,但这并不必要,因为我已经默认给每种弹窗设定了最佳动画!对于你自定义的弹窗,可以随心选择心仪的动画方案。", null) 38 | .show(); 39 | } 40 | },200); //确保spinner的消失动画不影响XPopup动画,可以看得更清晰 41 | } 42 | @Override 43 | public void onNothingSelected(AdapterView parent) { 44 | } 45 | }); 46 | 47 | } 48 | 49 | 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/fragment/BaseFragment.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.fragment; 2 | 3 | import android.os.Bundle; 4 | import androidx.annotation.NonNull; 5 | import androidx.annotation.Nullable; 6 | import androidx.fragment.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.Toast; 11 | 12 | import com.lxj.statelayout.StateLayout; 13 | import com.lxj.xpopupdemo.XPopupApp; 14 | 15 | /** 16 | * Description: 17 | * Create by dance, at 2018/12/9 18 | */ 19 | public abstract class BaseFragment extends Fragment { 20 | View view; 21 | boolean isInit = false; 22 | StateLayout stateLayout; 23 | @Nullable 24 | @Override 25 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 | if (view == null) { 27 | view = inflater.inflate(getLayoutId(), container, false); 28 | stateLayout = new StateLayout(getContext()).wrap(view).showLoading(); 29 | } 30 | return stateLayout; 31 | } 32 | 33 | @Override 34 | public void onResume() { 35 | super.onResume(); 36 | safeInit(); 37 | } 38 | 39 | private void safeInit() { 40 | if (getUserVisibleHint() && view!=null) { 41 | if (!isInit) { 42 | isInit = true; 43 | init(view); 44 | stateLayout.postDelayed(new Runnable() { 45 | @Override 46 | public void run() { 47 | stateLayout.showContent(); 48 | } 49 | },300); 50 | } 51 | } 52 | } 53 | 54 | @Override 55 | public void setUserVisibleHint(boolean isVisibleToUser) { 56 | super.setUserVisibleHint(isVisibleToUser); 57 | safeInit(); 58 | } 59 | 60 | protected abstract int getLayoutId(); 61 | public abstract void init(View view); 62 | 63 | public void toast(String msg) { 64 | Toast.makeText(XPopupApp.context, msg, Toast.LENGTH_SHORT).show(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/fragment/CustomAnimatorDemo.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.fragment; 2 | 3 | import androidx.interpolator.view.animation.FastOutSlowInInterpolator; 4 | import android.view.View; 5 | 6 | import com.lxj.xpopup.XPopup; 7 | import com.lxj.xpopup.animator.PopupAnimator; 8 | import com.lxj.xpopupdemo.R; 9 | 10 | /** 11 | * Description: 12 | * Create by dance, at 2018/12/9 13 | */ 14 | public class CustomAnimatorDemo extends BaseFragment { 15 | 16 | @Override 17 | protected int getLayoutId() { 18 | return R.layout.fragment_custom_animator_demo; 19 | } 20 | 21 | public void init(View view) { 22 | view.findViewById(R.id.btn_show).setOnClickListener(listener); 23 | } 24 | 25 | View.OnClickListener listener = new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | new XPopup.Builder(getContext()) 29 | .isDestroyOnDismiss(true) //对于只使用一次的弹窗,推荐设置这个 30 | .customAnimator(new RotateAnimator()) 31 | .asConfirm("演示自定义动画", "当前的动画是一个自定义的旋转动画,无论是自定义弹窗还是自定义动画,已经被设计得非常简单;这个动画代码只有6行即可完成!", null) 32 | .show(); 33 | } 34 | }; 35 | 36 | 37 | static class RotateAnimator extends PopupAnimator{ 38 | @Override 39 | public void initAnimator() { 40 | targetView.setScaleX(0); 41 | targetView.setScaleY(0); 42 | targetView.setAlpha(0); 43 | targetView.setRotation(360); 44 | } 45 | @Override 46 | public void animateShow() { 47 | targetView.animate().rotation(0) 48 | .scaleX(1).scaleY(1).alpha(1).setInterpolator(new FastOutSlowInInterpolator()).setDuration(340) 49 | .start(); 50 | } 51 | @Override 52 | public void animateDismiss() { 53 | targetView.animate().rotation(720).scaleX(0).scaleY(0).alpha(0).setInterpolator(new FastOutSlowInInterpolator()).setDuration(340) 54 | .start(); 55 | } 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/fragment/FragmentLifecycleDemo.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.fragment; 2 | 3 | import android.view.View; 4 | 5 | import com.lxj.xpopup.XPopup; 6 | import com.lxj.xpopup.core.BasePopupView; 7 | import com.lxj.xpopup.interfaces.SimpleCallback; 8 | import com.lxj.xpopupdemo.DemoActivity; 9 | import com.lxj.xpopupdemo.R; 10 | 11 | /** 12 | * 演示传入Fragment的Lifecycle,当Fragment销毁时,弹窗自动销毁,无内存泄漏 13 | */ 14 | public class FragmentLifecycleDemo extends BaseFragment{ 15 | @Override 16 | protected int getLayoutId() { 17 | return R.layout.fragment_lifecycle_demo; 18 | } 19 | 20 | @Override 21 | public void init(View view) { 22 | view.findViewById(R.id.btnShow).setOnClickListener(new View.OnClickListener() { 23 | @Override 24 | public void onClick(View v) { 25 | new XPopup.Builder(getContext()) 26 | .customHostLifecycle(getLifecycle()) 27 | .setPopupCallback(new SimpleCallback(){ 28 | @Override 29 | public void onDismiss(BasePopupView popupView) { 30 | 31 | } 32 | }) 33 | .asConfirm("演示自定义UI生命周期", "3秒后当前Fragment会被销毁,弹窗也自动销毁,避免内存泄漏", () -> { 34 | 35 | }).show(); 36 | ((DemoActivity)getActivity()).delayDestroy(); 37 | } 38 | }); 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/lxj/xpopupdemo/vm/DemoVM.java: -------------------------------------------------------------------------------- 1 | package com.lxj.xpopupdemo.vm; 2 | 3 | import androidx.lifecycle.MutableLiveData; 4 | import androidx.lifecycle.ViewModel; 5 | 6 | public class DemoVM extends ViewModel { 7 | public MutableLiveData liveData = new MutableLiveData<>(); 8 | 9 | @Override 10 | protected void onCleared() { 11 | super.onCleared(); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_circle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_round2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/bg_toast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/shadow_bg.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/junixapp/XPopup/fd1b8b7739596680a90e56efaa01ed524d4d95a1/app/src/main/res/drawable/shadow_bg.9.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_demo.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 18 | 19 |