侧滑效果[第七篇]:侧滑框架SmartSwipe之侧滑透明效果
SmartSwipe的侧滑透明效果主要体现在以下两种特效:
283.gif 284.gifSmartSwipe中TranslucentSlidingConsumer
可以实现以上效果。
代码如下:
TranslucentSlidingConsumer.java
/**
* Sliding with no drawer view, the view below will gradually show up as the contentView moves
* <pre>
* Note:
* {@link TranslucentSlidingConsumer} works similar to {@link SpaceConsumer}, differences are:
* 1. {@link SpaceConsumer} is simple, just make contentView movable
* 2. {@link TranslucentSlidingConsumer} can do something like {@link SlidingConsumer}, such as:
* 2.1 show shadow while swiping;
* 2.2 delete from data list with ListView/RecyclerView... on fully swiped
* 3. {@link TranslucentSlidingConsumer} is the base class of {@link ActivitySlidingBackConsumer}
* </pre>
* @author billy.qi
*/
public class TranslucentSlidingConsumer extends SlidingConsumer {
public TranslucentSlidingConsumer() {
//set drawer view not required
setDrawerViewRequired(false);
}
@Override
protected void initChildrenFormXml() {
//do nothing
}
@Override
public View getDrawerView(int direction) {
//no drawer view
return null;
}
@Override
protected void layoutDrawerView() {
//no drawer to layout
}
@Override
public TranslucentSlidingConsumer setDrawerView(int direction, View drawerView) {
// add no drawer view
return this;
}
@Override
protected void changeDrawerViewVisibility(int visibility) {
// no drawer view to show
}
@Override
public SwipeConsumer setOverSwipeFactor(float overSwipeFactor) {
// no over scale
return this;
}
}
TranslucentSlidingConsumer
是SlidingConsumer
的子类,所以它具备滑动特性。
【RecyclerView中Item删除效果实现】
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(mContext).inflate(R.layout.recycleview_item, parent, false);
TranslucentSlidingConsumer translucentSlidingConsumer = SmartSwipe.wrap(itemView)
.addConsumer(new TranslucentSlidingConsumer())
.enableHorizontal()
.as(TranslucentSlidingConsumer.class);
SmartSwipeWrapper wrapper = translucentSlidingConsumer.getWrapper();
ViewHolder holder = new ViewHolder(wrapper, translucentSlidingConsumer);
return holder;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tvName;
private ImageView ivAvatar;
public ViewHolder(SmartSwipeWrapper wrapper, TranslucentSlidingConsumer translucentSlidingConsumer) {
super(wrapper);
translucentSlidingConsumer.addListener(new SimpleSwipeListener(){
@Override
public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
int position = getAdapterPosition();
if (position >= 0 && position < mData.size()) {
mData.remove(position);
notifyItemRemoved(position);
}
}
});
tvName = itemView.findViewById(R.id.text);
ivAvatar = itemView.findViewById(R.id.iv_avatar);
((View)ivAvatar.getParent()).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(mContext, ImageViewerActivity.class);
intent.putExtra(ImageViewerActivity.IMAGE_EXTRA, R.mipmap.avatar_1);
mContext.startActivity(intent);
}
});
}
}
侧滑删除效果的本质其实就是SlidingConsumer
,SlidingConsumer
依赖一个抽屉布局,滑动的时候会慢慢的将抽屉布局给显示出来,然而TranslucentSlidingConsumer
去除了抽屉布局,仅仅保留SlidingConsumer
的侧滑效果。
【下滑关闭Activity效果】
就拿现在比较流行的即时通讯软件微信
为例,打开一张图片,下滑图片时会有透明缩放的效果,如上图。
那么,我们开始使用TranslucentSlidingConsumer
达到上图效果。
【第一步】
直接使用TranslucentSlidingConsumer
public class ImageViewerActivity extends AppCompatActivity {
public static String IMAGE_EXTRA = "image";
private View activityContentView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ImageView imageView = new ImageView(this);
imageView.setImageResource(getIntent().getIntExtra(IMAGE_EXTRA, 0));
setContentView(imageView);
activityContentView = findViewById(android.R.id.content);
activityContentView.setBackgroundColor(0xFF000000);
SmartSwipe.wrap(imageView)
.addConsumer(new TranslucentSlidingConsumer())
.enableTop();
}
}
新建一个ImageViewerActivity
,点击某按钮跳转到这个Activity,这个Activity的主要作用是展示图片,现在,将侧滑效果添加到图片上,效果如下:
【第二步】
让Activity中布局的背景逐渐透明
SmartSwipe.wrap(imageView)
.addConsumer(new TranslucentSlidingConsumer())
.enableTop()
.addListener(new SimpleSwipeListener(){
@Override
public void onSwipeStart(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
}
@Override
public void onSwipeProcess(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction, boolean settling, float progress) {
activityContentView.setAlpha(1 - progress);
}
@Override
public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
//关闭当前界面
ImageViewerActivity.this.finish();
}
});
添加一个SimpleSwipeListener
监听,重写三个方法,分别是onSwipeStart
、onSwipeProcess
、onSwipeOpened
,onSwipeStart
代码滑动的开始,onSwipeProcess
代表正在滑动并返回滑动的进度,onSwipeOpened
表示滑动结束。
当滑动结束的时候,我们销毁当前Activity,在正在滑动时,根据onSwipeProcess
的进度值实现Activity逐渐透明效果。
效果如下:
286.gif【第三步】
缩放图片
SmartSwipe.wrap(imageView)
.addConsumer(new TranslucentSlidingConsumer())
.enableTop()
.addListener(new SimpleSwipeListener(){
@Override
public void onSwipeStart(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
//ActivityTranslucentUtil.convertActivityToTranslucent(ImageViewerActivity.this, null);
}
@Override
public void onSwipeProcess(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction, boolean settling, float progress) {
View contentView = wrapper.getContentView();
activityContentView.setAlpha(1 - progress);
contentView.setScaleX(1 - progress);
contentView.setScaleY(1 - progress);
}
@Override
public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
//关闭当前界面
ImageViewerActivity.this.finish();
}
});
直接在onSwipeProcess
方法中设置缩放变化,代码如上。
效果如下:
287.gif【第四步】
界面透明效果的渐变
这里需要使用ActivityTranslucentUtil
辅助类,这个类的作用是将Window和Activity设置为透明。
/**
* @author billy.qi
*/
@SuppressLint("PrivateApi")
public class ActivityTranslucentUtil {
private static Class mTranslucentConversionListenerClass;
private static Method mMethodConvertFromTranslucent;
private static Method mMethodConvertToTranslucent;
private static Method mMethodGetActivityOptions;
private static boolean mInitialedConvertToTranslucent;
private static boolean mInitialedConvertFromTranslucent;
private Activity mActivity;
private boolean mIsTranslucent;
public ActivityTranslucentUtil(Activity activity) {
this.mActivity = activity;
}
public static void convertWindowToTranslucent(Activity activity) {
if (activity != null) {
View contentView = activity.findViewById(android.R.id.content);
Drawable background = contentView.getBackground();
if (background == null) {
TypedArray a = activity.getTheme().obtainStyledAttributes(new int[]{android.R.attr.windowBackground});
int windowBg = a.getResourceId(0, 0);
a.recycle();
if (windowBg != 0) {
contentView.setBackgroundResource(windowBg);
}
}
Window window = activity.getWindow();
window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
window.getDecorView().setBackgroundDrawable(null);
SmartSwipeWrapper wrapper = SmartSwipe.peekWrapperFor(activity);
if (wrapper != null) {
wrapper.setBackgroundColor(Color.TRANSPARENT);
}
}
}
private MessageQueue.IdleHandler convertActivityToTranslucentIdleHandler = new MessageQueue.IdleHandler() {
@Override
public boolean queueIdle() {
convertActivityToTranslucent();
return false;
}
};
private long convertTranslucentTimeStamp;
public void convertActivityToTranslucent() {
convertActivityToTranslucent(true);
}
public void convertActivityToTranslucent(final boolean retry) {
if (mIsTranslucent || mActivity == null) {
return;
}
if (convertingActivity != null) {
Looper.myQueue().addIdleHandler(convertActivityToTranslucentIdleHandler);
return;
}
convertTranslucentTimeStamp = SystemClock.elapsedRealtime();
final long callbackTimeStamp = convertTranslucentTimeStamp;
convertActivityToTranslucent(mActivity, new ActivityTranslucentUtil.TranslucentCallback() {
@Override
public void onTranslucentCallback(boolean translucent) {
if (callbackTimeStamp == convertTranslucentTimeStamp) {
if (retry && !translucent) {
convertActivityToTranslucent(false);
} else {
setTranslucent(translucent);
}
}
}
});
}
public void convertActivityFromTranslucent() {
convertTranslucentTimeStamp = SystemClock.elapsedRealtime();
convertActivityFromTranslucent(mActivity);
setTranslucent(false);
}
private void setTranslucent(boolean translucent) {
this.mIsTranslucent = translucent;
}
public boolean isTranslucent() {
return mIsTranslucent;
}
/** record the converting activity, resolve more than 1 xxUIs add onto the same activity */
private static WeakReference<Activity> convertingActivity;
/**
* Reflect call Activity.convertToTranslucent(...)
* @param activity activity
* @param callback callback
*/
public static void convertActivityToTranslucent(Activity activity, final TranslucentCallback callback) {
convertingActivity = new WeakReference<>(activity);
Object mTranslucentConversionListener = null;
try {
if (mTranslucentConversionListenerClass == null) {
Class[] clazzArray = Activity.class.getDeclaredClasses();
for (Class clazz : clazzArray) {
if (clazz.getSimpleName().contains("TranslucentConversionListener")) {
mTranslucentConversionListenerClass = clazz;
}
}
}
//resolve black flash at the beginning:
// Activity.convertToTranslucent(...) will takes tens of milliseconds
//thanks: https://github.com/Simon-Leeeeeeeee/SLWidget/blob/master/swipeback/src/main/java/cn/simonlee/widget/swipeback/SwipeBackHelper.java
if (mTranslucentConversionListenerClass != null) {
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
boolean translucent = false;
if (args != null && args.length == 1) {
translucent = (Boolean) args[0];
}
convertCallback(callback, translucent);
return null;
}
};
mTranslucentConversionListener = Proxy.newProxyInstance(mTranslucentConversionListenerClass.getClassLoader(), new Class[]{mTranslucentConversionListenerClass}, invocationHandler);
}
if (mMethodConvertToTranslucent == null && mInitialedConvertToTranslucent) {
convertCallback(callback, false);
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (mMethodConvertToTranslucent == null) {
mInitialedConvertToTranslucent = true;
Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions");
getActivityOptions.setAccessible(true);
mMethodGetActivityOptions = getActivityOptions;
Method method = Activity.class.getDeclaredMethod("convertToTranslucent", mTranslucentConversionListenerClass, ActivityOptions.class);
method.setAccessible(true);
mMethodConvertToTranslucent = method;
}
Object options = mMethodGetActivityOptions.invoke(activity);
mMethodConvertToTranslucent.invoke(activity, mTranslucentConversionListener, options);
} else {
if (mMethodConvertToTranslucent == null) {
mInitialedConvertToTranslucent = true;
Method method = Activity.class.getDeclaredMethod("convertToTranslucent", mTranslucentConversionListenerClass);
method.setAccessible(true);
mMethodConvertToTranslucent = method;
}
mMethodConvertToTranslucent.invoke(activity, mTranslucentConversionListener);
}
if (mTranslucentConversionListener == null) {
convertCallback(callback, false);
}
} catch (Throwable ignored) {
convertCallback(callback, false);
}
}
private static void convertCallback(TranslucentCallback callback, boolean translucent) {
if (callback != null) {
callback.onTranslucentCallback(translucent);
}
convertingActivity = null;
}
public static void convertActivityFromTranslucent(Activity activity) {
if (activity == null) {
return;
}
if (convertingActivity != null && convertingActivity.get() == activity) {
convertingActivity = null;
}
try {
if (mMethodConvertFromTranslucent == null) {
if (mInitialedConvertFromTranslucent) {
return;
}
mInitialedConvertFromTranslucent = true;
Method method = Activity.class.getDeclaredMethod("convertFromTranslucent");
method.setAccessible(true);
mMethodConvertFromTranslucent = method;
}
mMethodConvertFromTranslucent.invoke(activity);
} catch (Throwable ignored) {
}
}
public interface TranslucentCallback {
void onTranslucentCallback(boolean translucent);
}
}
使用以上辅助类,将Window和Activity设置成透明,代码如下:
activityContentView = findViewById(android.R.id.content);
activityContentView.setBackgroundColor(0xFF000000);
ActivityTranslucentUtil.convertWindowToTranslucent(this);
SmartSwipe.wrap(imageView)
.addConsumer(new TranslucentSlidingConsumer())
.enableTop()
.addListener(new SimpleSwipeListener(){
@Override
public void onSwipeStart(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
ActivityTranslucentUtil.convertActivityToTranslucent(ImageViewerActivity.this, null);
}
@Override
public void onSwipeProcess(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction, boolean settling, float progress) {
View contentView = wrapper.getContentView();
activityContentView.setAlpha(1 - progress);
contentView.setScaleX(1 - progress);
contentView.setScaleY(1 - progress);
}
@Override
public void onSwipeOpened(SmartSwipeWrapper wrapper, SwipeConsumer consumer, int direction) {
//关闭当前界面
ImageViewerActivity.this.finish();
}
});
[本章完...]