关注finddreams博客,一起分享,一起进步:http://blog.csdn.net/finddreams/article/details/44678171
做为我们日常使用最多的APP,手机QQ的每一次UI界面与操作习惯的改变都牵动着我们每一个用户的心。当然手Q的开发团队也认识到这个问题,所以在每次升级时都会做到整体风格的一致性,并和IOS版本保持一致的风格体验。
记得之前有一次微信版本更新,Android版本与IOS版本的界面和操作习惯出现了非常大的不一致,引起了很多微信用户的不满,于是下个Android版本又和IOS版本长一样了,网友戏称这是被骂回去的。
手机QQ和微信都是超级APP,用户体验自然是做的极好的了,也是众多开发者模仿的对象,今天给大家模仿一下手机QQ聊天列表滑动菜单删除和分析一下腾讯系很多APP,比如QQ邮箱,QQ空间等中滑动返回功能的实现。
1.手Q聊天列表的滑动菜单删除,是个非常方便的功能,非常的有创意。要实现这个功能我们可以使用到GitHub上一个开源的项目,SwipeMenuListView
使用这个开源项目也非常的简单,下载下来,看看demo实例代码也就会用了。
首先,把SwipeMenuListView加入到你要使用的布局文件layout中
<com.baoyz.swipemenulistview.SwipeMenuListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
然后再Activity中调用,并添加上滑动时显示要显示的两个菜单条目,一个推到顶部(暂时没有实现),一个为删除当前条目;具体代码:
/** * 初始化滑动菜单 */
private void initSwipeMenu() {
mListView = (SwipeMenuListView) findViewById(R.id.listView);
adapter = new NewsAdapter(this, chats, listView);
mListView.setAdapter(adapter);
// step 1. create a MenuCreator
SwipeMenuCreator creator = new SwipeMenuCreator() {
@Override
public void create(SwipeMenu menu) {
// create "up" item
SwipeMenuItem upItem = new SwipeMenuItem(
getApplicationContext());
// set item background
upItem.setBackground(new ColorDrawable(Color.rgb(0xE5, 0xE8,
0xE9)));
// set item width
upItem.setWidth(dp2px(90));
upItem.setIcon(R.drawable.up);
menu.addMenuItem(upItem);
// create "delete" item
SwipeMenuItem deleteItem = new SwipeMenuItem(
getApplicationContext());
// set item background
deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,
0x3F, 0x25)));
// set item width
deleteItem.setWidth(dp2px(90));
// set a icon
deleteItem.setIcon(R.drawable.ic_delete);
// add to menu
menu.addMenuItem(deleteItem);
}
};
// set creator
mListView.setMenuCreator(creator);
// step 2. listener item click event
mListView.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(int position, SwipeMenu menu,
int index) {
switch (index) {
case 0:
break;
case 1:
chats.remove(position);
adapter.notifyDataSetChanged();
break;
}
return false;
}
});
这样就可以实现手机QQ聊天列表滑动菜单删除功能了。
1.手势滑动返回的好处?
随着手机屏幕的尺寸越来越大,虽然直观上可视范围更大了,但给我们的操作习惯带来了很多不便。单手在大屏的Android手机上进行操作,发现手指短的话很难点击到返回按钮,返回就变得很难。单手快速往右水平滑动的功能,实现了界面的返回,给我们带来了很大的便利,交互体验好多了。
2.手势滑动返回的实现方式一:使用SwipeBackLayout
原理:这种实现的重点在于将Activity 的属性设置为透明的,然后上方的Activity就可以在跟随手指移动时候放一个半透明的层表示那种渐变的阴影效果,全部滑动完成后再把上方Activity销毁掉。
向右滑动销毁(finish)Activity, 随着手势的滑动而滑动的效果;
步骤:具体源码可以参考[SwipeBack]这个开源项目(https://github.com/liuguangqiang/SwipeBack)
这种方式实现有一个很关键的小细节,就是别忘了要把这个Activity的窗体背景变成透明的,否则会出现黑屏的现象;
<style name="Theme.Swipe.Back" parent="AppTheme">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowBackground">@android:color/transparent</item>
</style>
3.手势滑动返回的实现方式二:使用GestureDetector手势识别的类
这种方式应该是手机QQ,以及QQ邮箱正在使用的方式。第一种方式不怎么常见,而且因为窗体背景变成透明的了,所以在滑动的时候,感觉像一张薄纸,像蒙在脸上的一层薄纱。所以还是推荐这一种方式。
/** * @Description:手势滑动的Activity,只需要继承就可实现手势滑动 * @author http://blog.csdn.net/finddreams */
public class GestureBackActivity extends Activity {
private GestureDetector myDectector;
private static final String TAG = "GestureBackActivity";
boolean flingFinishEnabled = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
initGestureDetector();
AppManager.getAppManager().addActivity(this);
}
private void initGestureDetector() {
if (myDectector == null) {
myDectector = new GestureDetector(this, new MyGestureListener());
}
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (flingFinishEnabled) {
return myDectector.onTouchEvent(ev) || super.dispatchTouchEvent(ev);
}
return super.dispatchTouchEvent(ev);
}
/** * 手势监听器 * */
public class MyGestureListener implements OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
// Toast.makeText(getApplicationContext(),"down",Toast.LENGTH_SHORT).show();
return true;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// Toast.makeText(getApplicationContext(),"onSingleTapUp",Toast.LENGTH_SHORT).show();
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2,
float distanceX, float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
if (e1.getX() - e2.getX() > 100 && Math.abs(velocityX) > 0) {
Log.d(TAG, "向左滑动");
} else if (e2.getX() - e1.getX() > 100 && Math.abs(velocityX) > 0) {
Log.d(TAG, "向右滑动");
AppManager.getAppManager().finishActivity();
}
return false;
}
}
}
代码中有个AppManager类,这是一个管理Activity的类,可以对项目中Activity的生命周期进行管理,以达到安全退出的目的;
/** * @Description:是一个管理Activity的类,可以对项目中Activity的生命周期进行管理, 达到安全退出的目的; * @author http://blog.csdn.net/finddreams */
public class AppManager {
private static Stack<Activity> activityStack;
private static AppManager instance;
private AppManager() {
}
/** * 单一实例 */
public static AppManager getAppManager() {
if (instance == null) {
instance = new AppManager();
}
return instance;
}
/** * 添加Activity到堆栈中 */
public void addActivity(Activity activity) {
if (activityStack == null) {
activityStack = new Stack<Activity>();
}
activityStack.add(activity);
}
/** * 获取当前Activity(堆栈中最后压入的) */
public Activity currentActivity() {
Activity activity = activityStack.lastElement();
return activity;
}
/** * 结束当前Activity(堆栈中最后压入的) */
public void finishActivity() {
Activity activity = activityStack.lastElement();
finishActivity(activity);
}
/** * 结束指定的Activity */
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity.overridePendingTransition(R.anim.in_from_right,
R.anim.out_to_right);
activity = null;
}
}
/** * 结束指定类名的Activity */
public void finishActivity(Class<?> cls) {
for (Activity activity : activityStack) {
if (activity.getClass().equals(cls)) {
finishActivity(activity);
}
}
}
/** * 结束所有Activity */
public void finishAllActivity() {
for (int i = 0, size = activityStack.size(); i < size; i++) {
if (null != activityStack.get(i)) {
activityStack.get(i).finish();
}
}
activityStack.clear();
}
/** * 彻底退出应用程序,安全退出 */
public void AppExit(Context context) {
try {
finishAllActivity();
ActivityManager activityMgr = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
activityMgr.restartPackage(context.getPackageName());
System.exit(0);
android.os.Process.killProcess(android.os.Process.myPid());
} catch (Exception e) {
}
}
}
要实现打开一个Activity是从左往右滑动进入的效果,我们必须使用到动画,具体代码:
protected void startActivity(Class<?> cls) {
Intent intent = new Intent();
intent.setClass(this, cls);
startActivity(intent);
overridePendingTransition(R.anim.in_from_left, R.anim.out_to_left);
}
同时为了实现滑动退出的时候,是从左到右的动画退出效果,我们也必须使用到动画:
/** * 结束指定的Activity */
public void finishActivity(Activity activity) {
if (activity != null) {
activityStack.remove(activity);
activity.finish();
activity.overridePendingTransition(R.anim.in_from_right,
R.anim.out_to_right);
activity = null;
}
}
一个Activity想要实现滑动返回的效果,就只需要继承这个类即可,使用起来也是非常的方便。
源码见:https://github.com/finddreams/SlidingBack 欢迎star!