这其实很简单就可以实现,只需要自定义一个View继承自HorizontalScrollView

1,新建一个项目,再新建一个MySlideMenu继承HorizontalScrollView

public class MySlideMenu extends HorizontalScrollView {  //继承自横向可滚动ScrollView
    private int mScreenWidth;  //屏幕宽度
    private int mMenuRightPadding;  //菜单栏的右边距 
    
    //菜单栏的宽度
    private int mMenuWidth;
    private int mMenuHalfWidth;  //菜单栏的半边宽度
    
    private boolean isOpen;  //标志当前菜单栏是否打开
    
    private boolean isOnce;  //是否第一次打开
    
    private ViewGroup mContent;  //内容页面
    private ViewGroup mMenu;   //菜单页面
    
    
    
    public MySlideMenu(Context context, AttributeSet attrs){
        this(context, attrs, 0);
    }
    
    public MySlideMenu(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mScreenWidth=ScreenUtils.getScreenWidth(context);
        
        TypedArray a=context.getTheme().obtainStyledAttributes(attrs,
                R.styleable.SlidingMenu, defStyle, 0);
        
        int n = a.getIndexCount();
        for (int i = 0; i < n; i++) {
            int attr=a.getIndex(i);
            if(attr==R.styleable.SlidingMenu_rightPadding){
                mMenuRightPadding = a.getDimensionPixelSize(attr,
                        (int) TypedValue.applyDimension(
                                TypedValue.COMPLEX_UNIT_DIP, 50f,
                                getResources().getDisplayMetrics()));// 默认为10DP
            }
        }
        a.recycle();
    }
    
    
    @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if(!isOnce){  //只允许获得第一次的  测量结果
                LinearLayout ll=(LinearLayout) getChildAt(0);
                mMenu=(ViewGroup) ll.getChildAt(0);  //从线性布局中获得 Menu布局
                mContent=(ViewGroup) ll.getChildAt(1);
                
                mMenuWidth=mScreenWidth-mMenuRightPadding;
                mMenuHalfWidth=mMenuWidth/2;
                mMenu.getLayoutParams().width=mMenuWidth;
                mContent.getLayoutParams().width=mScreenWidth;
                
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if(changed){
            this.scrollTo(mMenuWidth, 0);    //将菜单隐藏
            isOnce=true;
        }
    }
    
    //打开菜单
    public void openMenu(){
        if(isOpen){
            return;
        }
        this.scrollTo(0, 0);
        isOpen=true;
    }
    //关闭菜单
    public void closeMenu(){
        if(!isOpen){
            return;
        }
        this.scrollTo(mMenuWidth,0);
        isOpen=false;
    }
    //切换菜单开关状态
    public void toggle(){
        if(isOpen){
            closeMenu();
        }
        else{
            openMenu();
        }
    }
    
    //监听手势滑动  
    @Override
        public boolean onTouchEvent(MotionEvent ev) {
            
            switch (ev.getAction()) {
                case MotionEvent.ACTION_UP:
                    int scrollX=getScrollX(); //获取滑动的横坐标
                    if(scrollX>mMenuHalfWidth){   //判断 有没有滑倒一半的距离
                        this.smoothScrollTo(mMenuWidth, 0);  //隐藏
                        isOpen=false;
                    }
                    else{
                        this.smoothScrollTo(0, 0);//展开
                        isOpen=true;
                    }
                    return true;
            }
            return super.onTouchEvent(ev);
        }
    
    //监听滑动时   菜单视图 和 滑动视图出现相应的放大缩小的特效
    @Override
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            float scale = l * 1.0f / mMenuWidth;
            float leftScale = 1 - 0.3f * scale;
            float rightScale = 0.8f + scale * 0.2f;
            
            ViewHelper.setScaleX(mMenu, leftScale);
            ViewHelper.setScaleY(mMenu, leftScale);
            ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale));
            ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.7f);
            ViewHelper.setPivotX(mContent, 0);
            ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
            ViewHelper.setScaleX(mContent, rightScale);
            ViewHelper.setScaleY(mContent, rightScale);
        }    
}
这里面其实就是用到了一个横向的ScrollView,并且在滑动时加入了一些动画效果而已,但ViewHelper并不是andorid API提供的,而是需要下载nineoldandroids-2.4.0.jar包.

2,新建一个屏幕辅助类
/**
 * 获得屏幕相关的辅助类
 * 
 * @author zhy
 * 
 */
public class ScreenUtils
{
    private ScreenUtils()
    {
        /* cannot be instantiated */
        throw new UnsupportedOperationException("cannot be instantiated");
    }
    /**
     * 获得屏幕高度
     * 
     * @param context
     * @return
     */
    public static int getScreenWidth(Context context)
    {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.widthPixels;
    }
    /**
     * 获得屏幕宽度
     * 
     * @param context
     * @return
     */
    public static int getScreenHeight(Context context)
    {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrics = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrics);
        return outMetrics.heightPixels;
    }
    /**
     * 获得状�?�栏的高�?
     * 
     * @param context
     * @return
     */
    public static int getStatusHeight(Context context)
    {
        int statusHeight = -1;
        try
        {
            Class<?> clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int height = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            statusHeight = context.getResources().getDimensionPixelSize(height);
        } catch (Exception e)
        {
            e.printStackTrace();
        }
        return statusHeight;
    }
    /**
     * 获取当前屏幕截图,包含状态栏
     * 
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithStatusBar(Activity activity)
    {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, 0, width, height);
        view.destroyDrawingCache();
        return bp;
    }
    /**
     * 获取当前屏幕截图,不包含状�?�栏
     * 
     * @param activity
     * @return
     */
    public static Bitmap snapShotWithoutStatusBar(Activity activity)
    {
        View view = activity.getWindow().getDecorView();
        view.setDrawingCacheEnabled(true);
        view.buildDrawingCache();
        Bitmap bmp = view.getDrawingCache();
        Rect frame = new Rect();
        activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
        int statusBarHeight = frame.top;
        int width = getScreenWidth(activity);
        int height = getScreenHeight(activity);
        Bitmap bp = null;
        bp = Bitmap.createBitmap(bmp, 0, statusBarHeight, width, height
                - statusBarHeight);
        view.destroyDrawingCache();
        return bp;
    }
}

其实就用到了一个获取屏幕宽度的方法.

3.看看activity_main.xml
<com.example.mytest.MySlideMenu xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/id_menu"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:zhy="http://schemas.android.com/apk/res/com.example.mytest"
    android:layout_width="wrap_content"
    android:layout_height="fill_parent"
    android:background="@drawable/img_frame_background"
    android:scrollbars="none"
    zhy:rightPadding="100dp" >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:orientation="horizontal" >
        <include layout="@layout/layout_menu" />
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:background="@drawable/qq" >
            <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:onClick="toggleMenu"
                android:text="切换菜单" />
        </LinearLayout>
    </LinearLayout>

</com.example.mytest.MySlideMenu>


xml视图中就包含了两个View,一个是Menu,一个是Content.

4,再看Menu视图
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#0000" >
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:orientation="vertical" >
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/one"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/img_1" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/one"
                android:text="第1个Item"
                android:textColor="#f0f0f0"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/two"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/img_2" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/two"
                android:text="第2个Item"
                android:textColor="#f0f0f0"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/three"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/img_3" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/three"
                android:text="第3个Item"
                android:textColor="#f0f0f0"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/four"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/img_4" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/four"
                android:text="第一个Item"
                android:textColor="#f0f0f0"
                android:textSize="20sp" />
        </RelativeLayout>
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
            <ImageView
                android:id="@+id/five"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_marginTop="20dp"
                android:src="@drawable/img_5" />
            <TextView
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:layout_marginLeft="20dp"
                android:layout_toRightOf="@id/five"
                android:text="第5个Item"
                android:textColor="#f0f0f0"
                android:textSize="20sp" />
        </RelativeLayout>
    </LinearLayout>
</RelativeLayout>

也就是一些简单的线性排列而已.

5,最后一步,打开MainActivity.java
public class MainActivity extends Activity
{
    private MySlideMenu mMenu;
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mMenu = (MySlideMenu) findViewById(R.id.id_menu);
    }
    public void toggleMenu(View view)
    {
        mMenu.toggle();
    }
}

如此,轻松实现QQ侧滑效果.
 









android仿QQ的SlideMenu的更多相关文章

  1. Android仿QQ ios dialog,仿QQ退出向上菜单

    Android仿QQ ios dialog,仿QQ退出向上菜单 EasyDialog两种模式 仿QQ退出向上菜单,自己定义向上菜单              github地址:https://gith ...

  2. Android 仿QQ首页的消息和电话的切换,首页的头部(完全用布局控制)

    Android 仿QQ首页的消息和电话的切换,首页的头部(完全用布局控制) 首先贴上七个控制布局代码 1.title_text_sel.xml 字体颜色的切换 放到color文件夹下面 <?xm ...

  3. android 仿QQ手机版

    千人2群开启,欢迎大家围观打酱油,群号145667827     您当前位置 : JavaApk-安卓应用游戏源码服务专家 » QQ » Android项目源码界面超级华丽的仿QQ最新版本 Andro ...

  4. Android仿QQ登录下拉历史列表

    demo中包含了Sqlite数据库增删改查,对存储的账号进行按照最新的时间排序,限制了最多存储5条数据. 效果图: 1.首先创建MyHelper建表: public class MyHelper ex ...

  5. Android仿QQ窗口的抖动的动画效果

    就是仿照QQ窗口的抖动效果,在项目的res下创建anim文件夹,再创建两个xml文件:cycle.xml  . myanim.xml   cycle.xml  :   <?xml version ...

  6. 【转】Android仿QQ截图应用测试

    使用过QQ的同学应该都用过QQ截图,Ctrl+Alt+A进入截图操作,通过拉伸,移动高亮区域的框体可以快速截取我们需要的图片.在android应用中,我们也经常需要截图操作,以下实现了一个类似QQ截图 ...

  7. android仿qq空间、微信朋友圈图片展示

    废话不多说,先上效果图 由于近期须要做朋友圈功能,所以在此记录一下,事实上非常多人不明确的一点应该是在图片的排列上面吧,不规则的排列,事实上非常easy的.就是一个GridView.然而你xml光光写 ...

  8. Android仿qq聊天记录长按删除功能效果

    最近项目在做IM即时通讯开发,在删除聊天列表的时候跟删除聊天详细信息的时候,产品经理想要跟ios一样,在当前选中行上方弹出一个删除窗口.于是先从网上找demo,找了一个发现是Dialog做的,我感觉没 ...

  9. Android 仿QQ消息界面

    values 下面 dimens.xml <resources> <!-- Default screen margins, per the Android Design guidel ...

随机推荐

  1. Windows 2008 server + IIS 7 设置身份模拟(ASP.NET impersonation)

    IIS7 与 IIS 6 相比有了很大的改动,原来在 IIS 6 下可以的设置到了 IIS 7 下有的会发生变化.身份模拟的配置上,IIS7 和 IIS6有很大不同,网上IIS6的身份模拟的文章比较多 ...

  2. 滑动窗口(poj,线段树维护区间最值)

    题目描述 现在有一堆数字共N个数字(N<=10^6),以及一个大小为k的窗口.现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值. 例如: The array i ...

  3. 【PTA 天梯赛】L2-026. 小字辈(广搜+邻接表)

    本题给定一个庞大家族的家谱,要请你给出最小一辈的名单. 输入格式: 输入在第一行给出家族人口总数 N(不超过 100 000 的正整数) —— 简单起见,我们把家族成员从 1 到 N 编号.随后第二行 ...

  4. 树莓派官方推荐的VNC Viewer配置详解Raspberry Pi3 B+

    1GB内存,16GB硬盘容量.这是我目前使用的Pi3树莓派. SVN Viewer远程连接,台式机192.168.1.102连接局域网192.168.1.110上的树莓派.使用的软件是: https: ...

  5. ECSHOP和SHOPEX快递单号查询申通插件V8.6专版

    发布ECSHOP说明: ECSHOP快递物流单号查询插件特色 本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅 ...

  6. js 节点

    var chils= s.childNodes; //得到s的全部子节点 var par=s.parentNode;  //得到s的父节点 var ns=s.nextSbiling;  //获得s的下 ...

  7. Flask初见

    Flask是一个使用 Python 编写的轻量级 Web 应用框架.其 WSIG工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 .Flask使用 BSD 授权. Flask也被称为 “m ...

  8. 贪心算法之Kruskal

    克鲁斯卡尔Kruskal算法同Prim算法一样,都是求最小生成树.Kruskal是不断的找最短边,加入集合,且不构成回路. 所以,我们可以给每个点定义一个集合,一边的起点和终点查看是否属于同一集合,如 ...

  9. YSZOJ:#247. [福利]可持久化线段树 (最适合可持久化线段树入门)

    题目链接:https://syzoj.com/problem/247 解题心得: 可持久化线段树其实就是一个线段树功能的加强版,加强在哪里呢?那就是如果一颗普通的线段树多次修改之后还能知道最开始的线段 ...

  10. Java——自动生成30道四则运算---18.09.27

    package chuti;import java.io.PrintWriter;import java.util.Scanner;import java.io.FileNotFoundExcepti ...