Android知识笔记:Android 仿iOS 侧滑关闭Activity框架透底问题

文章讲述了在Android中改变Activity主题的正确方法,强调了不能在onCreate后直接更改主题,通常需使用setTheme()和recreate()。此外,还介绍了如何通过系统API修改Activity的windowIsTranslucent属性,以及反射调用convertToTranslucent和convertFromTranslucent方法实现透明度转换。
摘要由CSDN通过智能技术生成

public void changeTheme(int index) {

switch (index) {

case DEFAULT_THEME:

current_theme = R.style.DefaultTheme;

break;

case GREEN_THEME:

current_theme = R.style.GreenTheme;

break;

case ORANGE_THEME:

current_theme = R.style.OrangeTheme;

break;

default:

break;

}

}

protected void reload() {

Intent intent = getIntent();

overridePendingTransition(0, 0);

intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);

finish();

overridePendingTransition(0, 0);

startActivity(intent);

}

其实设置主题必须在任何view创建之前,所以我们不可能在activity的onCreate之后来更改主题,如果一定要做,就只能调用setTheme(),然后调用recreate(),重新创建一个activity,并且销毁上一个activity; 所以这个方案并不可行,整个界面必须销毁重建。 已知的Android theme修改方式

  • AndroidManifest 设置Activity Theme

  • 在Activity setContentView执行前 调用setTheme

可以通过其他方式修改Activity windowIsTranslucent 属性吗?

方案B+:反射动态设置Activity windowIsTranslucent

查阅Activity源码,看一下他是如何变成透明的

/**

  • Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} back from

  • opaque to translucent following a call to {@link #convertFromTranslucent()}.

  • Calling this allows the Activity behind this one to be seen again. Once all such Activities

  • have been redrawn {@link TranslucentConversionListener#onTranslucentConversionComplete} will

  • be called indicating that it is safe to make this activity translucent again. Until

  • {@link TranslucentConversionListener#onTranslucentConversionComplete} is called the image

  • behind the frontmost Activity will be indeterminate.

  • This call has no effect on non-translucent activities or on activities with the

  • {@link android.R.attr#windowIsFloating} attribute.

  • @param callback the method to call when all visible Activities behind this one have been

  • drawn and it is safe to make this Activity translucent again.

  • @param options activity options delivered to the activity below this one. The options

  • are retrieved using {@link #getActivityOptions}.

  • @return true if Window was opaque and will become translucent or

  • false if window was translucent and no change needed to be made.

  • @see #convertFromTranslucent()

  • @see TranslucentConversionListener

  • @hide

*/

@SystemApi

public boolean convertToTranslucent(TranslucentConversionListener callback,

ActivityOptions options) {

boolean drawComplete;

try {

mTranslucentCallback = callback;

mChangeCanvasToTranslucent = ActivityManager.getService().convertToTranslucent(

mToken, options == null ? null : options.toBundle());

WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, false);

drawComplete = true;

} catch (RemoteException e) {

// Make callback return as though it timed out.

mChangeCanvasToTranslucent = false;

drawComplete = false;

}

if (!mChangeCanvasToTranslucent && mTranslucentCallback != null) {

// Window is already translucent.

mTranslucentCallback.onTranslucentConversionComplete(drawComplete);

}

return mChangeCanvasToTranslucent;

}

/**

  • Convert a translucent themed Activity {@link android.R.attr#windowIsTranslucent} to a

  • fullscreen opaque Activity.

  • Call this whenever the background of a translucent Activity has changed to become opaque.

  • Doing so will allow the {@link android.view.Surface} of the Activity behind to be released.

  • This call has no effect on non-translucent activities or on activities with the

  • {@link android.R.attr#windowIsFloating} attribute.

  • @see #convertToTranslucent(android.app.Activity.TranslucentConversionListener,

  • ActivityOptions)

  • @see TranslucentConversionListener

  • @hide

*/

@SystemApi

public void convertFromTranslucent() {

try {

mTranslucentCallback = null;

if (ActivityManager.getService().convertFromTranslucent(mToken)) {

WindowManagerGlobal.getInstance().changeCanvasOpacity(mToken, true);

}

} catch (RemoteException e) {

// pass

}

}

可以看到这个两个Api就是将Activity转化为投透明和非透明通过 ActivityManager.getService() 和 WindowManagerGlobal.getInstance().changeCanvasOpacity()修改Window透明属性;

  • convertToTranslucent //将当前Activity Window 设置为透明

  • convertFromTranslucent //将当前 Activity Window 设置为非透明

由于是系统Api 并有 @hide 标注 正常是无法调用的,可以通过反射来调用; 反射调用如下:

/**

  • Convert a translucent themed Activity

  • 将Activity 改为透明

*/

public static void convertActivityToTranslucent(Activity activity) {

long timeMillis = SystemClock.currentThreadTimeMillis();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

convertActivityToTranslucentAfterL(activity);

} else {

convertActivityToTranslucentBeforeL(activity);

}

FxLog.d("convertActivity : convertActivityToTranslucent time = " + (SystemClock.currentThreadTimeMillis() - timeMillis));

}

/**

  • Calling the convertToTranslucent method on platforms before Android 5.0

*/

public static void convertActivityToTranslucentBeforeL(Activity activity) {

try {

Class<?>[] classes = Activity.class.getDeclaredClasses();

Class<?> translucentConversionListenerClazz = null;

for (Class clazz : classes) {

if (clazz.getSimpleName().contains(“TranslucentConversionListener”)) {

translucentConversionListenerClazz = clazz;

}

}

Method method = Activity.class.getDeclaredMethod(“convertToTranslucent”,

translucentConversionListenerClazz);

method.setAccessible(true);

method.invoke(activity, new Object[] {

null

});

} catch (Throwable t) {

}

}

/**

  • Calling the convertToTranslucent method on platforms after Android 5.0

*/

private static void convertActivityToTranslucentAfterL(Activity activity) {

try {

Method getActivityOptions = Activity.class.getDeclaredMethod(“getActivityOptions”);

getActivityOptions.setAccessible(true);

Object options = getActivityOptions.invoke(activity);

Class<?>[] classes = Activity.class.getDeclaredClasses();

Class<?> translucentConversionListenerClazz = null;

for (Class clazz : classes) {

if (clazz.getSimpleName().contains(“TranslucentConversionListener”)) {

translucentConversionListenerClazz = clazz;

}

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

百万年薪必刷面试题

最全Android进阶学习视频

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!

2024/03/13/H4lCoPEF.jpg" />

Android进阶资料

以下的资料是近年来,我和一些朋友面试收集整理了很多大厂的面试真题和资料,还有来自如阿里、小米、爱奇艺等一线大厂的大牛整理的架构进阶资料。希望可以帮助到大家。

Android进阶核心笔记

[外链图片转存中…(img-fVRTZz44-1711796398497)]

百万年薪必刷面试题

[外链图片转存中…(img-Yy8zXoTI-1711796398497)]

最全Android进阶学习视频

《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门即可获取!
  • 16
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值