zoukankan      html  css  js  c++  java
  • 侧滑菜单 ——仿QQ实现动画效果

    1、首先实现侧滑菜单,这里用HorizontalScrollView来进行实现

    2、SideMenu为自定义view 继承horizontalScrollView

    3、这个自定义命名空间 :xmlns:lyl="http://schemas.android.com/apk/res/com.example.horizontalscrollview_qq"

      中的res/下面为项目的包名 可以复制manifest.xml中的包名

    4、<include />中包含的是侧滑菜单的布局   可以自行定义
    5、内部的linearlayout 为内容布局  也可以自行定义

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:lyl="http://schemas.android.com/apk/res/com.example.horizontalscrollview_qq"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.example.horizontalscrollview_qq.MainActivity" >
    
        <com.example.sidemenu.SideMenu
            android:id="@+id/menu"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@drawable/img_frame_background"
            lyl:MenuPadding="50dp" >
    
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal" >
    
                <include layout="@layout/side_menu" />
    
                <LinearLayout
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:background="@drawable/qq" >
    
                    <Button
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:background="@android:color/transparent"
                        android:onClick="toggleMenu"
                        android:text="@string/back"
                        android:textColor="@android:color/white"
                        android:textSize="30sp" />
                </LinearLayout>
            </LinearLayout>
        </com.example.sidemenu.SideMenu>
    
    </RelativeLayout>

    自定义View

    1、构造方法

      一个参数 context

      两个参数 context attr

      三个参数  context attr defStyle

    三个参数的构造方法中含有 自定义属性的值  所以 在一个参数的构造方法中使用this(context ,null)调用两个参数的,以此类推

    2、复写 onMeasure()方法

      定义子视图 设置子视图的大小

    3、复写 onLayout()方法

      设置子视图的位置

    4、动画效果

      这里为更好的兼容3.0以下的版本 导入nineoldAndroid.jar包

      nineoldAndroid的API和Honeycomb API完全一样,只是改变了使用com.nineoldandroids.XXX的入口。
           

    package com.example.sidemenu;
    
    import com.example.horizontalscrollview_qq.R;
    import com.nineoldandroids.view.ViewHelper;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.util.AttributeSet;
    import android.util.DisplayMetrics;
    import android.util.TypedValue;
    import android.view.MotionEvent;
    import android.view.ViewGroup;
    import android.view.WindowManager;
    import android.view.animation.AnimationSet;
    import android.view.animation.TranslateAnimation;
    import android.widget.HorizontalScrollView;
    import android.widget.LinearLayout;
    
    public class SideMenu extends HorizontalScrollView {
        private LinearLayout mWapper;
        private ViewGroup mMenu;
        private ViewGroup mContent;
    
        private int mScreenWidth;
        private int mMenuRightpadding = 50;
        private boolean once;
    
        private int mMenuWidth;
        private int mContentWidth;
    
        private boolean isOpen;
    
        public SideMenu(Context context) {
            // super(context);
            // 调用两个参数的构造方法
            this(context, null);
    
        }
    
        public SideMenu(Context context, AttributeSet attrs) {
            // super(context, attrs);
            // 调用含有自定义属性参数的构造方法
            this(context, attrs, 0);
    
        }
    
        public SideMenu(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            // 读取所有自定义参数
            TypedArray array = context.getTheme().obtainStyledAttributes(attrs,
                    R.styleable.sidemenu, defStyleAttr, 0);
            // 获得属性数组的数量
            int n = array.getIndexCount();
    
            for (int i = 0; i < n; i++) {
                int attr = array.getIndex(i);
                switch (attr) {
                case R.styleable.sidemenu_MenuPadding:
                    // 1 、设置自定义属性值
                    // 2、设置默认值
                    mMenuRightpadding = array.getDimensionPixelSize(attr,
                            (int) TypedValue.applyDimension(
                                    TypedValue.COMPLEX_UNIT_DIP, 50, context
                                            .getResources().getDisplayMetrics()));
                    break;
                default:
                    break;
                }
            }
            // 回收
            array.recycle();
            WindowManager manager = (WindowManager) context
                    .getSystemService(Context.WINDOW_SERVICE);
            DisplayMetrics outMetrics = new DisplayMetrics();
            manager.getDefaultDisplay().getMetrics(outMetrics);
            mScreenWidth = outMetrics.widthPixels;
    
        }
    
        // 自定义视图时,需要复写这几个方法 onMeasure onLayout
        // onMeasure 计算子View的宽和高,以及设置自己的宽和高
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            if (!once) {
                // 先初始化linearLayout
                mWapper = (LinearLayout) getChildAt(0);
                // linearLayout内装入子视图
                mMenu = (ViewGroup) mWapper.getChildAt(0);
                // 在装入第二个子视图
                mContent = (ViewGroup) mWapper.getChildAt(1);
                // 设置 第一个 视图的 宽度
                mMenuWidth = mMenu.getLayoutParams().width = mScreenWidth
                        - mMenuRightpadding;
                // 设置第二个视图的宽度
                mContentWidth = mContent.getLayoutParams().width = mScreenWidth;
                // 只计算一次
                once = true;
            }
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
        // onLayout 决定子View的布局的位置
        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);
                isOpen = false;
            }
        }
    
        // 触摸事件处理
        public boolean onTouchEvent(MotionEvent ev) {
            switch (ev.getAction()) {
            case MotionEvent.ACTION_UP:
                int scrollX = getScrollX();
                if (scrollX >= mMenuWidth / 2) {
                    this.smoothScrollTo(mMenuWidth, 0);
                    isOpen = false;
                } else {
                    this.smoothScrollTo(0, 0);
                    isOpen = true;
    
                }
                return true;
            }
    
            return super.onTouchEvent(ev);
        }
    
        // 打开菜单
        public void open() {
            this.smoothScrollTo(0, 0);
            isOpen = true;
        }
    
        // 关闭菜单
        public void close() {
            this.smoothScrollTo(mMenuWidth, 0);
            isOpen = false;
        }
    
        // 按钮开关
        public void toggle() {
            if (isOpen) {
                close();
            } else {
                open();
            }
        }
    
        // 实现侧滑的抽屉效果
        protected void onScrollChanged(int l, int t, int oldl, int oldt) {
            super.onScrollChanged(l, t, oldl, oldt);
            // l: horizontalScroll起始的水平位置
            // t: 起始的垂直位置
            // 调用动画属性 设置translation
            // mMenu.setTranslationX(l);
            // 这里为更好的兼容3.0以下的版本 导入nineoldAndroid.jar包
    
            // 该API和Honeycomb API完全一样,只是改变了使用com.nineoldandroids.XXX的入口。
            ViewHelper.setTranslationX(mMenu, l*0.7f);
            float scale = l * 1.0f / mMenuWidth;
            // 实现内容区域的缩放
            // 设置缩放的中心点
            ViewHelper.setPivotX(mContent, 0);
            ViewHelper.setPivotY(mContent, mContent.getHeight() / 2);
            // 从1.0缩放到0.7
            ViewHelper.setScaleX(mContent, 0.7f + 0.3f * scale);
            ViewHelper.setScaleY(mContent, 0.7f + 0.3f * scale);
            // mMenu 的缩放从0.7到1.0
            ViewHelper.setScaleX(mMenu, 1.0f - 0.3f * scale);
            ViewHelper.setScaleY(mMenu, 1.0f - 0.3f * scale);
            // 设置mMenu 的透明度 0.6到1.0
            ViewHelper.setAlpha(mMenu, 1.0f - 0.6f * scale);
    
        }
    
    }

     上面的自定义属性需要声明

      自定义属性(styleable)的名字为sidemenu 属性名为 MenuPadding

      在自定义view中使用 需要自定义命名空间 

        xmlns:lyl="http://schemas.android.com/apk/res/com.example.horizontalscrollview_qq"

      在res/下为项目的包名 可以在manifest.xml中复制
      在自定义视图中使用:lyl:MenuPadding="50dp"

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <attr name="MenuPadding" format="dimension"></attr>
    
        <declare-styleable name="sidemenu">
            <attr name="MenuPadding" ></attr>
        </declare-styleable>
    </resources>

    1、自定义view中 可以通过 TypedArray来获得自定义的所有属性

      TypedArray array = context.getTheme().obtainStyledAttributes(attrs,
                      R.styleable.sidemenu, defStyleAttr, 0);

    2、 获得自定义属性可以通过 getDimensionPixelSize(index, defValue)来获得   并设置默认值

      当需要将参数值的单位进行转化时可以用 

      TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, context
                                            .getResources().getDisplayMetrics());
          单位为dip  即返回的的结果为:50dp乘以显示密度density(dpi/160)。即为像素px

     

     

    mian里面实现了菜单的开关按钮

    package com.example.horizontalscrollview_qq;
    
    import com.example.horizontalscrollview_qq.R.id;
    import com.example.sidemenu.SideMenu;
    
    import android.app.Activity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    import android.view.View;
    import android.view.Window;
    
    
    public class MainActivity extends Activity {
    private SideMenu menu;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            requestWindowFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.main_activity);    
            menu=(SideMenu) findViewById(id.menu);
            
        }
    
        public void toggleMenu(View view){
            menu.toggle();
        }
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            // Handle action bar item clicks here. The action bar will
            // automatically handle clicks on the Home/Up button, so long
            // as you specify a parent activity in AndroidManifest.xml.
            int id = item.getItemId();
            if (id == R.id.action_settings) {
                return true;
            }
            return super.onOptionsItemSelected(item);
        }
    }

     

     

     

     

  • 相关阅读:
    pzrNB!!!
    biu biu biu
    大笑三声再往下看!
    Selenium之Chrome浏览器的启动
    Selenium IDE脚本录制步骤简介
    Selenium IDE的一些操作
    Selenium IDE编辑区域修改操作学习
    在firefox安装Selenium IDE
    执行Java脚本firefox启动成功,不运行test方法,且提示NullPointerException
    Selenium+Python学习之一
  • 原文地址:https://www.cnblogs.com/mydomainlistentome/p/4740267.html
Copyright © 2011-2022 走看看