Commit f8b1d573 authored by Amit Kumar's avatar Amit Kumar 💻
Browse files

Add blur view in BlissLauncher v2

parent 4987554a
Pipeline #149432 passed with stage
in 8 minutes and 43 seconds
......@@ -27,6 +27,7 @@ class ShaderBlurDrawable internal constructor(private val blurWallpaperProvider:
}
private val blurBounds = RectF()
var canvasOffset: Float = 0f
private val blurPath = Path()
private var blurPathValid = false
set(value) {
......@@ -44,6 +45,7 @@ class ShaderBlurDrawable internal constructor(private val blurWallpaperProvider:
fun draw(canvas: Canvas, noRadius: Boolean = false) {
if (blurAlpha == 0) return
if (blurBounds.right.toInt() - blurBounds.left.toInt() == 0) return
blurBitmap = blurWallpaperProvider.wallpaper
if (blurBitmap == null) {
......@@ -65,7 +67,11 @@ class ShaderBlurDrawable internal constructor(private val blurWallpaperProvider:
// setupBlurPath()
// canvas.translate(0f, -1500f)
// We check the offset just to make sure we don't translate it incorrectly
// when moving back to home screen from widget page.
if (canvasOffset > 0) {
canvas.translate(canvasOffset, 0f)
}
if (noRadius) {
canvas.drawRect(
0f, 0f,
......@@ -75,7 +81,9 @@ class ShaderBlurDrawable internal constructor(private val blurWallpaperProvider:
} else {
canvas.drawPath(DeviceProfile.path, blurPaint)
}
// canvas.translate(0f, 1500f)
if (canvasOffset > 0)
canvas.translate(-canvasOffset, 0f)
}
override fun setAlpha(alpha: Int) {
......
......@@ -17,7 +17,9 @@
package foundation.e.blisslauncher.features.launcher;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
......@@ -27,14 +29,22 @@ import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.logging.Handler;
import foundation.e.blisslauncher.R;
import foundation.e.blisslauncher.core.blur.BlurWallpaperProvider;
import foundation.e.blisslauncher.core.blur.ShaderBlurDrawable;
import foundation.e.blisslauncher.core.customviews.Insettable;
import foundation.e.blisslauncher.core.customviews.InsettableFrameLayout;
import foundation.e.blisslauncher.core.executors.MainThreadExecutor;
import foundation.e.blisslauncher.features.test.CellLayout;
import foundation.e.blisslauncher.features.test.TestActivity;
import foundation.e.blisslauncher.features.test.VariantDeviceProfile;
public class Hotseat extends CellLayout implements Insettable {
public class Hotseat extends CellLayout implements Insettable, BlurWallpaperProvider.Listener {
private final TestActivity mLauncher;
private CellLayout mContent;
......@@ -44,6 +54,30 @@ public class Hotseat extends CellLayout implements Insettable {
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mHasVerticalHotseat;
private final BlurWallpaperProvider blurWallpaperProvider;
private ShaderBlurDrawable fullBlurDrawable = null;
private int blurAlpha = 255;
private final Drawable.Callback blurDrawableCallback = new Drawable.Callback() {
@Override
public void invalidateDrawable(@NonNull Drawable who) {
new MainThreadExecutor().execute(() -> invalidate());
}
@Override
public void scheduleDrawable(
@NonNull Drawable who, @NonNull Runnable what, long when
) {
}
@Override
public void unscheduleDrawable(
@NonNull Drawable who, @NonNull Runnable what
) {
}
};
public Hotseat(Context context) {
this(context, null);
}
......@@ -55,7 +89,19 @@ public class Hotseat extends CellLayout implements Insettable {
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mLauncher = TestActivity.Companion.getLauncher(context);
setBackgroundColor(0x33000000);
setWillNotDraw(false);
blurWallpaperProvider = BlurWallpaperProvider.Companion.getInstance(getContext());
createBlurDrawable();
}
private void createBlurDrawable() {
if (isAttachedToWindow() && fullBlurDrawable != null) {
fullBlurDrawable.stopListening();
}
fullBlurDrawable = blurWallpaperProvider.createDrawable();
fullBlurDrawable.setCallback(blurDrawableCallback);
fullBlurDrawable.setBounds(getLeft(), getTop(), getRight(), getBottom());
if (isAttachedToWindow()) fullBlurDrawable.startListening();
}
// TODO: Remove this later.
......@@ -70,6 +116,41 @@ public class Hotseat extends CellLayout implements Insettable {
setGridSize(idp.getInv().getNumHotseatIcons(), 1);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
BlurWallpaperProvider.Companion.getInstance(getContext()).addListener(this);
if (fullBlurDrawable != null) {
fullBlurDrawable.startListening();
}
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
BlurWallpaperProvider.Companion.getInstance(getContext()).removeListener(this);
if (fullBlurDrawable != null) {
fullBlurDrawable.stopListening();
}
}
@Override
protected void onDraw(@Nullable Canvas canvas) {
if (fullBlurDrawable != null) {
fullBlurDrawable.setAlpha(blurAlpha);
fullBlurDrawable.draw(canvas);
}
super.onDraw(canvas);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
if (changed && fullBlurDrawable != null) {
fullBlurDrawable.setBounds(left, top, right, bottom);
}
super.onLayout(changed, left, top, right, bottom);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
// We don't want any clicks to go through to the hotseat unless the workspace is in
......@@ -96,4 +177,14 @@ public class Hotseat extends CellLayout implements Insettable {
// Don't let if follow through to workspace
return true;
}
@Override
public void onWallpaperChanged() {
}
@Override
public void onEnabledChanged() {
createBlurDrawable();
}
}
......@@ -8,6 +8,7 @@ import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.app.ActivityOptions
import android.app.AlertDialog
import android.app.WallpaperManager
import android.app.usage.UsageStats
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProviderInfo
......@@ -21,6 +22,7 @@ import android.content.pm.ActivityInfo
import android.content.pm.ApplicationInfo
import android.content.pm.LauncherActivityInfo
import android.content.pm.LauncherApps
import android.content.pm.PackageManager
import android.content.res.Configuration
import android.graphics.Point
import android.graphics.Rect
......@@ -43,6 +45,7 @@ import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.View
import android.view.View.OnAttachStateChangeListener
import android.view.View.OnFocusChangeListener
import android.view.ViewGroup
import android.view.animation.AccelerateDecelerateInterpolator
......@@ -57,6 +60,7 @@ import android.widget.SeekBar
import android.widget.TextView
import android.widget.TextView.OnEditorActionListener
import android.widget.Toast
import androidx.core.app.ActivityCompat
import androidx.core.view.isVisible
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import androidx.recyclerview.widget.DividerItemDecoration
......@@ -68,11 +72,12 @@ import foundation.e.blisslauncher.BlissLauncher
import foundation.e.blisslauncher.R
import foundation.e.blisslauncher.core.Preferences
import foundation.e.blisslauncher.core.Utilities
import foundation.e.blisslauncher.core.blur.BlurWallpaperProvider
import foundation.e.blisslauncher.core.broadcast.WallpaperChangeReceiver
import foundation.e.blisslauncher.core.customviews.AbstractFloatingView
import foundation.e.blisslauncher.core.customviews.BlissFrameLayout
import foundation.e.blisslauncher.core.customviews.BlissInput
import foundation.e.blisslauncher.core.customviews.FolderTitleInput
import foundation.e.blisslauncher.core.customviews.InsettableFrameLayout
import foundation.e.blisslauncher.core.customviews.LauncherPagedView
import foundation.e.blisslauncher.core.customviews.RoundedWidgetView
import foundation.e.blisslauncher.core.customviews.SquareFrameLayout
......@@ -113,6 +118,7 @@ import foundation.e.blisslauncher.features.weather.WeatherPreferences
import foundation.e.blisslauncher.features.weather.WeatherSourceListenerService
import foundation.e.blisslauncher.features.weather.WeatherUpdateService
import foundation.e.blisslauncher.features.widgets.WidgetManager
import foundation.e.blisslauncher.features.widgets.WidgetPageLayer
import foundation.e.blisslauncher.features.widgets.WidgetViewBuilder
import foundation.e.blisslauncher.features.widgets.WidgetsActivity
import foundation.e.blisslauncher.features.widgets.WidgetsRootView
......@@ -170,7 +176,7 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
private lateinit var dragLayer: DragLayer
private lateinit var workspace: LauncherPagedView
private lateinit var hotseat: Hotseat
private lateinit var widgetPage: InsettableFrameLayout
private lateinit var widgetPage: WidgetPageLayer
private lateinit var mSearchInput: BlissInput
......@@ -227,6 +233,8 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
private val TAG = "TestActivity"
private var wallpaperChangeReceiver: WallpaperChangeReceiver? = null
override fun onCreate(savedInstanceState: Bundle?) {
if (DEBUG_STRICT_MODE) {
StrictMode.setThreadPolicy(
......@@ -259,6 +267,8 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
mAppWidgetHost = BlissLauncher.getApplication(this).appWidgetHost
initDeviceProfile(BlissLauncher.getApplication(this).invariantDeviceProfile)
val wm = getSystemService(WALLPAPER_SERVICE) as WallpaperManager
wm.suggestDesiredDimensions(mDeviceProfile.widthPx, mDeviceProfile.heightPx)
dragController = DragController(this)
rotationHelper = RotationHelper(this)
mStateManager = LauncherStateManager(this)
......@@ -299,6 +309,17 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
}
}
})
if (ActivityCompat.checkSelfPermission(
this,
Manifest.permission.READ_EXTERNAL_STORAGE
) != PackageManager.PERMISSION_GRANTED
) {
requestPermissions(
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
STORAGE_PERMISSION_REQUEST_CODE
)
}
createOrUpdateIconGrid()
overlayCallbackImpl = OverlayCallbackImpl(this)
setLauncherOverlay(overlayCallbackImpl)
......@@ -448,11 +469,53 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
// Setup the drag controller (drop targets have to be added in reverse order in priority)
dragController.setMoveTarget(workspace)
wallpaperChangeReceiver = WallpaperChangeReceiver(workspace)
workspace.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
wallpaperChangeReceiver?.setWindowToken(v.windowToken)
}
override fun onViewDetachedFromWindow(v: View) {
wallpaperChangeReceiver?.setWindowToken(null)
}
})
}
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
if (requestCode == WeatherPreferences.LOCATION_PERMISSION_REQUEST_CODE) {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
// We only get here if user tried to enable the preference,
// hence safe to turn it on after permission is granted
val lm = getSystemService(LOCATION_SERVICE) as LocationManager
if (!lm.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
showLocationEnableDialog()
Preferences.setEnableLocation(this)
} else {
startService(
Intent(this, WeatherUpdateService::class.java)
.setAction(WeatherUpdateService.ACTION_FORCE_UPDATE)
)
}
}
} else if (requestCode == STORAGE_PERMISSION_REQUEST_CODE) {
if (grantResults.isNotEmpty() &&
grantResults[0] == PackageManager.PERMISSION_GRANTED
) {
BlurWallpaperProvider.getInstance(applicationContext).updateAsync()
}
} else super.onRequestPermissionsResult(requestCode, permissions, grantResults)
}
private fun setupWidgetPage() {
widgetPage =
layoutInflater.inflate(R.layout.widgets_page, rootView, false) as InsettableFrameLayout
layoutInflater.inflate(R.layout.widgets_page, rootView, false) as WidgetPageLayer
rootView.addView(widgetPage)
widgetContainer = widgetPage.findViewById(R.id.widget_container)
......@@ -1337,6 +1400,8 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
const val DEBUG_STRICT_MODE = false
private val STORAGE_PERMISSION_REQUEST_CODE: Int = 586
// TODO: Remove after test is finished
fun getLauncher(context: Context): TestActivity {
return if (context is TestActivity) {
......@@ -1396,8 +1461,11 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
if (scrollFromWorkspace) {
workspace.onOverlayScrollChanged(progress)
widgetPage.translationX = widgetPage.measuredWidth * (progress - 1)
widgetPage.changeBlurBounds(progress, true)
} else {
workspace.onOverlayScrollChanged(progress)
Log.i(TAG, "onScrollChanged: $progress")
widgetPage.changeBlurBounds(progress, false)
}
}
}
......@@ -1414,6 +1482,7 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
workspace.onOverlayScrollChanged(it.animatedValue as Float)
widgetPage.translationX =
widgetPage.measuredWidth * (it.animatedValue as Float - 1)
widgetPage.changeBlurBounds(it.animatedValue as Float, true)
}
workspaceAnim.duration = 300
workspaceAnim.interpolator = AccelerateDecelerateInterpolator()
......@@ -1425,6 +1494,7 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
override fun onAnimationCancel(animation: Animator) {
workspace.onOverlayScrollChanged(0f)
widgetPage.translationX = (-widgetPage.measuredWidth).toFloat()
widgetPage.changeBlurBounds(0f, true)
animator = null
}
})
......@@ -1435,6 +1505,7 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
workspace.onOverlayScrollChanged(it.animatedValue as Float)
widgetPage.translationX =
widgetPage.measuredWidth * (it.animatedValue as Float - 1)
widgetPage.changeBlurBounds(it.animatedValue as Float, false)
}
workspaceAnim.duration = 300
workspaceAnim.interpolator = AccelerateDecelerateInterpolator()
......@@ -1446,6 +1517,7 @@ class TestActivity : BaseDraggingActivity(), AutoCompleteAdapter.OnSuggestionCli
override fun onAnimationCancel(animation: Animator) {
workspace.onOverlayScrollChanged(1f)
widgetPage.translationX = 0f
widgetPage.changeBlurBounds(1f, false)
animator = null
}
})
......
package foundation.e.blisslauncher.features.widgets
import android.content.Context
import android.graphics.Canvas
import android.graphics.drawable.Drawable
import android.util.AttributeSet
import foundation.e.blisslauncher.core.blur.BlurWallpaperProvider
import foundation.e.blisslauncher.core.blur.ShaderBlurDrawable
import foundation.e.blisslauncher.core.customviews.Insettable
import foundation.e.blisslauncher.core.customviews.InsettableFrameLayout
import foundation.e.blisslauncher.core.runOnMainThread
class WidgetPageLayer @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : InsettableFrameLayout(context, attrs), Insettable,
BlurWallpaperProvider.Listener {
private val blurWallpaperProvider: BlurWallpaperProvider
private var fullBlurDrawable: ShaderBlurDrawable? = null
private val blurAlpha = 255
private val blurDrawableCallback: Drawable.Callback = object : Drawable.Callback {
override fun invalidateDrawable(who: Drawable) {
runOnMainThread {
invalidate()
}
}
override fun scheduleDrawable(
who: Drawable,
what: Runnable,
`when`: Long
) {
}
override fun unscheduleDrawable(
who: Drawable,
what: Runnable
) {
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
BlurWallpaperProvider.getInstance(context).addListener(this)
fullBlurDrawable?.startListening()
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
BlurWallpaperProvider.getInstance(context).removeListener(this)
fullBlurDrawable?.stopListening()
}
override fun onDraw(canvas: Canvas) {
fullBlurDrawable?.alpha = blurAlpha
fullBlurDrawable?.draw(canvas)
super.onDraw(canvas)
}
override fun onLayout(
changed: Boolean,
left: Int,
top: Int,
right: Int,
bottom: Int
) {
super.onLayout(changed, left, top, right, bottom)
if (changed) {
fullBlurDrawable?.setBounds(left, top, right, bottom)
}
}
/**
* We only need to change right bound for widget page blur layer.
*/
fun changeBlurBounds(factor: Float, isLeftToRight: Boolean) {
fullBlurDrawable?.setBounds(left, top, (right * factor).toInt(), bottom)
if (isLeftToRight) {
fullBlurDrawable?.canvasOffset =
(right - left) * (1 - factor)
}
fullBlurDrawable?.invalidateSelf()
}
private fun createBlurDrawable() {
if (isAttachedToWindow) {
fullBlurDrawable?.stopListening()
}
fullBlurDrawable = blurWallpaperProvider.createDrawable().apply {
callback = blurDrawableCallback
setBounds(left, top, right, bottom)
}
if (isAttachedToWindow) fullBlurDrawable?.startListening()
}
override fun onEnabledChanged() {
createBlurDrawable()
}
override fun onWallpaperChanged() {}
init {
setWillNotDraw(false)
blurWallpaperProvider = BlurWallpaperProvider.getInstance(context)
createBlurDrawable()
}
}
......@@ -15,6 +15,11 @@
android:clipToPadding="false"
android:importantForAccessibility="no">
<!--<foundation.e.blisslauncher.core.customviews.BlurBackgroundView
android:id="@+id/blur_layer"
android:layout_width="match_parent"
android:layout_height="match_parent" />-->
<foundation.e.blisslauncher.core.customviews.LauncherPagedView
android:id="@+id/workspace"
android:layout_width="match_parent"
......
<?xml version="1.0" encoding="utf-8"?>
<foundation.e.blisslauncher.core.customviews.InsettableFrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
<foundation.e.blisslauncher.features.widgets.WidgetPageLayer xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
......@@ -95,4 +95,4 @@
android:text="Max"
android:textColor="@color/white" />
</RelativeLayout>
</foundation.e.blisslauncher.core.customviews.InsettableFrameLayout>
\ No newline at end of file
</foundation.e.blisslauncher.features.widgets.WidgetPageLayer>
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment