diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml index b268ef3..08c51b4 100644 --- a/.idea/deploymentTargetSelector.xml +++ b/.idea/deploymentTargetSelector.xml @@ -4,6 +4,14 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index 0ad17cb..f351441 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -7,4 +7,11 @@ + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 6f45e8f..30a4019 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,11 +1,9 @@ - - + xmlns:tools="http://schemas.android.com/tools"> + - + android:usesCleartextTraffic="true" + tools:targetApi="31"> + + + + android:exported="true" + android:theme="@style/MainActivity"> diff --git a/app/src/main/java/com/example/androiddemo/Function.java b/app/src/main/java/com/example/androiddemo/Function.java index c4e1d81..46d07c0 100644 --- a/app/src/main/java/com/example/androiddemo/Function.java +++ b/app/src/main/java/com/example/androiddemo/Function.java @@ -1,6 +1,8 @@ package com.example.androiddemo; -import com.example.androiddemo.activity.Toast; +import com.example.androiddemo.activity.DefPopup; +import com.example.androiddemo.activity.Dialog; +import com.example.androiddemo.activity.DefToast; import java.util.ArrayList; import java.util.List; @@ -20,7 +22,9 @@ public class Function { } public static void init() { - list.add(new Function("多样化提示", Toast.class)); + list.add(new Function("多样化提示", DefToast.class)); + list.add(new Function("毛玻璃弹窗", Dialog.class)); + list.add(new Function("自定义Popup", DefPopup.class)); } diff --git a/app/src/main/java/com/example/androiddemo/activity/DefPopup.java b/app/src/main/java/com/example/androiddemo/activity/DefPopup.java new file mode 100644 index 0000000..2577477 --- /dev/null +++ b/app/src/main/java/com/example/androiddemo/activity/DefPopup.java @@ -0,0 +1,49 @@ +package com.example.androiddemo.activity; + +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; +import android.app.Activity; +import android.os.Bundle; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.PopupWindow; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.PopupMenu; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.example.androiddemo.R; + +public class DefPopup extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_def_popup); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + findViewById(R.id.btn_custom).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + PopupMenu popupMenu = new PopupMenu(DefPopup.this, v); + popupMenu.getMenuInflater().inflate(R.menu.popup_menu, popupMenu.getMenu()); + popupMenu.setOnMenuItemClickListener(item -> { + Toast.makeText(DefPopup.this, item.getTitle(), Toast.LENGTH_SHORT).show(); + return true; + }); + popupMenu.show(); + } + }); + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/androiddemo/activity/Toast.java b/app/src/main/java/com/example/androiddemo/activity/DefToast.java similarity index 78% rename from app/src/main/java/com/example/androiddemo/activity/Toast.java rename to app/src/main/java/com/example/androiddemo/activity/DefToast.java index d25e8d7..28dd3d7 100644 --- a/app/src/main/java/com/example/androiddemo/activity/Toast.java +++ b/app/src/main/java/com/example/androiddemo/activity/DefToast.java @@ -3,19 +3,11 @@ package com.example.androiddemo.activity; import android.animation.Animator; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; -import android.app.Dialog; -import android.graphics.Bitmap; import android.os.Bundle; import android.os.Handler; -import android.renderscript.Allocation; -import android.renderscript.Element; -import android.renderscript.RenderScript; -import android.renderscript.ScriptIntrinsicBlur; import android.util.DisplayMetrics; import android.view.Gravity; import android.view.View; -import android.view.ViewGroup; -import android.widget.ImageView; import android.widget.LinearLayout; import androidx.activity.EdgeToEdge; @@ -25,7 +17,6 @@ import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; -import com.bumptech.glide.Glide; import com.example.androiddemo.R; import com.example.androiddemo.databinding.ViewToastBinding; import com.google.android.material.card.MaterialCardView; @@ -33,7 +24,7 @@ import com.google.android.material.card.MaterialCardView; /** * 多样化提示界面 */ -public class Toast extends AppCompatActivity { +public class DefToast extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { @@ -45,7 +36,6 @@ public class Toast extends AppCompatActivity { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); - View viewById = findViewById(R.id.TopToast); LinearLayout linearLayout = findViewById(R.id.line1); // 屏幕的宽度/2 @@ -57,11 +47,18 @@ public class Toast extends AppCompatActivity { layoutParams.setMargins(0, 20, 0, 0); layoutParams.gravity = Gravity.CENTER_HORIZONTAL; - viewById.setOnClickListener(v -> linearLayout.addView(NewToast("测试"), 0, layoutParams)); + findViewById(R.id.TopToast).setOnClickListener(v -> { + linearLayout.setGravity(Gravity.CENTER_HORIZONTAL); + linearLayout.addView(NewToast("测试"), 0, layoutParams); + }); + findViewById(R.id.CenterToast).setOnClickListener(v -> { + linearLayout.setGravity(Gravity.CENTER); + linearLayout.addView(NewToast("测试"), 0, layoutParams); + }); - Glide.with(this).load("https://pic2.zhimg.com/v2-febc9228d18886a29c68a66536279dfb_r.jpg?source=1940ef5c") - .into((ImageView) findViewById(R.id.imageView)); +// Glide.with(this).load("https://pic2.zhimg.com/v2-febc9228d18886a29c68a66536279dfb_r.jpg?source=1940ef5c") +// .into((ImageView) findViewById(R.id.imageView)); } @@ -75,16 +72,14 @@ public class Toast extends AppCompatActivity { MaterialCardView materialCardView = binding.getRoot(); - ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(materialCardView, "scaleY", 0.8f, 1f); - scaleYAnimator.setDuration(300); // 动画持续时间1秒 - - // 创建透明度渐变动画 - ObjectAnimator fadeInAnimator = ObjectAnimator.ofFloat(materialCardView, "alpha", 0f, 1f); - fadeInAnimator.setDuration(300); // 动画持续时间1秒 - + //创建移动动画 + ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(materialCardView, "scaleY", 0.5f, 1f); + ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(materialCardView, "scaleX", 0.5f, 1f); + scaleXAnimator.setDuration(100); + scaleYAnimator.setDuration(100); // 动画持续时间1秒 // 同时播放两个动画 AnimatorSet set = new AnimatorSet(); - set.playTogether(scaleYAnimator, fadeInAnimator); + set.playTogether(scaleYAnimator,scaleXAnimator); set.start(); // 设置动画结束后的回调 diff --git a/app/src/main/java/com/example/androiddemo/activity/Dialog.java b/app/src/main/java/com/example/androiddemo/activity/Dialog.java new file mode 100644 index 0000000..f0cc76e --- /dev/null +++ b/app/src/main/java/com/example/androiddemo/activity/Dialog.java @@ -0,0 +1,208 @@ +package com.example.androiddemo.activity; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Bundle; +import android.view.MenuInflater; +import android.view.View; +import android.view.Window; +import android.view.WindowManager; +import android.widget.Toast; + +import androidx.activity.EdgeToEdge; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.graphics.Insets; +import androidx.core.view.ViewCompat; +import androidx.core.view.WindowInsetsCompat; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.target.Target; +import com.example.androiddemo.R; +import com.google.android.material.dialog.MaterialAlertDialogBuilder; +import com.google.android.material.dialog.MaterialDialogs; + +import java.util.function.Consumer; + +public class Dialog extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + EdgeToEdge.enable(this); + setContentView(R.layout.activity_dialog); + ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> { + Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars()); + v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); + return insets; + }); + //SDK 小于31 的关闭界面 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + android.widget.Toast.makeText(this, "只支持Android 12以上的设备", Toast.LENGTH_SHORT).show(); + finish(); + } + findViewById(R.id.btn_dialog).setOnClickListener(v -> { + //仅模糊背景 + BlurDialog dialog = new BlurDialog(v.getContext(), BlurDialog.BLUR_TYPE_BLUR_BACKGROUND); + dialog.show(); + }); + findViewById(R.id.btn_dialog2).setOnClickListener(v -> { + //仅模糊后方屏幕 + BlurDialog dialog = new BlurDialog(this, BlurDialog.BLUR_TYPE_BLUR_BEHIND); + dialog.show(); + }); + findViewById(R.id.btn_dialog3).setOnClickListener(v -> { + //模糊背景和后方屏幕 + BlurDialog dialog = new BlurDialog(this, BlurDialog.BLUR_TYPE_BLUR_BACKGROUND_AND_BEHIND); + dialog.show(); + }); + + Glide.with(this).asDrawable(). + load("https://pic2.zhimg.com/v2-febc9228d18886a29c68a66536279dfb_r.jpg?source=1940ef5c") + .addListener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, @Nullable Object model, @NonNull Target target, boolean isFirstResource) { + return false; + } + + @Override + public boolean onResourceReady(@NonNull Drawable resource, @NonNull Object model, Target target, @NonNull DataSource dataSource, boolean isFirstResource) { + findViewById(R.id.main).setBackground(resource); + return false; + } + }).submit(); + + } + /** + * 对话框背景毛玻璃化 + */ + private void blurdialog() { + BlurDialog dialog = new BlurDialog(this, BlurDialog.BLUR_TYPE_BLUR_BACKGROUND); + dialog.show(); + } + /** @noinspection FieldCanBeLocal*/ + public class BlurDialog extends AlertDialog { + + private Window mWindow; + + //窗口背景高斯模糊程度,数值越高越模糊且越消耗性能 + private final int mBackgroundBlurRadius = 90; + //窗口周边背景高斯模糊程度 + private final int mBlurBehindRadius = 20; + + //根据窗口高斯模糊功能是否开启来设置窗口周边暗色的程度 + private final float mDimAmountWithBlur = 0f; + private final float mDimAmountNoBlur = 0.4f; + + // 根据窗口高斯模糊功能是否开启来为窗口设置不同的不透明度 + private final int mWindowBackgroundAlphaWithBlur = 170; + private final int mWindowBackgroundAlphaNoBlur = 255; + + //使用一个矩形drawable文件作为窗口背景,这个矩形的轮廓和圆角确定了窗口高斯模糊的区域 + private Drawable mWindowBackgroundDrawable; + + /** + * 高斯模糊的类型 + * 0代表只模糊背景 + * 1代表之模糊后方屏幕 + * 2代表同时模糊背景和后方屏幕 + */ + private int mBlurType = 0; + public static final int BLUR_TYPE_BLUR_BACKGROUND = 0; + public static final int BLUR_TYPE_BLUR_BEHIND = 1; + public static final int BLUR_TYPE_BLUR_BACKGROUND_AND_BEHIND = 2; + + public BlurDialog(@NonNull Context context, int blurType) { + super(context, R.style.BlurDialogTheme); + mBlurType = blurType; + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.dialog_blur); + initBlur(); + } + + private void initBlur() { + mWindow = getWindow(); + //替换window默认的背景 + mWindowBackgroundDrawable = getContext().getDrawable(R.drawable.window_background); + getWindow().setBackgroundDrawable(mWindowBackgroundDrawable); + + //注册一个监听者去监听窗口UI视图是否可见以便调整窗口高斯模糊功能是否开启 + setupWindowBlurListener(); + + //允许背景模糊,也可以通过样式属性R.attr#windowBlurBehindEnabled来实现 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); + + // 允许背景变暗,也可以通过样式属性R.attr#backgroundDimEnabled来实现 + getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND); + } + + /** + * 设置一个窗口视图状态监听者,监听窗口视图是否可见以便是否更新窗口模糊的状态 + */ + private void setupWindowBlurListener() { + Consumer windowBlurEnabledListener = this::updateWindowForBlurs; + getWindow().getDecorView().addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() { + @Override + public void onViewAttachedToWindow(@NonNull View v) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + mWindow.getWindowManager().addCrossWindowBlurEnabledListener(windowBlurEnabledListener); + } + } + + @Override + public void onViewDetachedFromWindow(@NonNull View v) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + mWindow.getWindowManager().removeCrossWindowBlurEnabledListener(windowBlurEnabledListener); + } + } + }); + } + + /** + * 更新窗口的高斯模糊效果 + * + * @param blursEnabled + */ + private void updateWindowForBlurs(boolean blursEnabled) { + if (mBlurType == BLUR_TYPE_BLUR_BACKGROUND) { + //仅模糊背景 + mWindowBackgroundDrawable.setAlpha(blursEnabled ? mWindowBackgroundAlphaWithBlur : mWindowBackgroundAlphaNoBlur);//调整背景的透明度 + getWindow().setDimAmount(blursEnabled ? mDimAmountWithBlur : mDimAmountNoBlur);//调整背景周边昏暗的程度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + getWindow().setBackgroundBlurRadius(mBackgroundBlurRadius);//设置背景模糊程度 + } + return; + } + if (mBlurType == BLUR_TYPE_BLUR_BEHIND) { + //仅模糊后方屏幕 + getWindow().setDimAmount(blursEnabled ? mDimAmountWithBlur : mDimAmountNoBlur);//调整背景周边昏暗的程度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + getWindow().getAttributes().setBlurBehindRadius(mBlurBehindRadius);//设置背景周边模糊程度 + } + getWindow().setAttributes(getWindow().getAttributes());//让上面的高斯模糊效果生效 + return; + } + //同时模糊背景和后方屏幕 + mWindowBackgroundDrawable.setAlpha(blursEnabled ? mWindowBackgroundAlphaWithBlur : mWindowBackgroundAlphaNoBlur);//调整背景的透明度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + getWindow().setBackgroundBlurRadius(mBackgroundBlurRadius);//设置背景模糊程度 + } + getWindow().setDimAmount(blursEnabled ? mDimAmountWithBlur : mDimAmountNoBlur);//调整背景周边昏暗的程度 + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + getWindow().getAttributes().setBlurBehindRadius(mBlurBehindRadius);//设置背景周边模糊程度 + } + getWindow().setAttributes(getWindow().getAttributes());//让上面的高斯模糊效果生效 + } + } + +} \ No newline at end of file diff --git a/app/src/main/res/animator/popup_enter.xml b/app/src/main/res/animator/popup_enter.xml new file mode 100644 index 0000000..6bbc258 --- /dev/null +++ b/app/src/main/res/animator/popup_enter.xml @@ -0,0 +1,7 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/window_background.xml b/app/src/main/res/drawable/window_background.xml new file mode 100644 index 0000000..7eca51c --- /dev/null +++ b/app/src/main/res/drawable/window_background.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/layout/activity_def_popup.xml b/app/src/main/res/layout/activity_def_popup.xml new file mode 100644 index 0000000..3e025d6 --- /dev/null +++ b/app/src/main/res/layout/activity_def_popup.xml @@ -0,0 +1,17 @@ + + + +