├── .gitignore
├── README-CN.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── jkb
│ │ └── slidemenulayout
│ │ ├── MainActivity.java
│ │ ├── adapter
│ │ ├── ContentAdapter.java
│ │ ├── FriendAdapter.java
│ │ ├── SlideLeftAdapter.java
│ │ ├── SlideRightMenuAdapter.java
│ │ └── TabTwoAdapter.java
│ │ └── ui
│ │ ├── ChatFragment.java
│ │ ├── FriendFragment.java
│ │ ├── TabOneFragment.java
│ │ └── TabTwoFragment.java
│ └── res
│ ├── drawable-xxhdpi
│ ├── ic_action_conversations.png
│ └── ic_action_menu.png
│ ├── layout
│ ├── activity_main.xml
│ ├── content_menu_left.xml
│ ├── content_menu_right.xml
│ ├── frg_chat.xml
│ ├── frg_friend.xml
│ ├── frg_tab_one.xml
│ ├── frg_tab_two.xml
│ ├── item_friend.xml
│ └── item_tab_two.xml
│ ├── mipmap-hdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-mdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── mipmap-xxxhdpi
│ ├── ic_launcher.png
│ └── ic_launcher_round.png
│ ├── values-v19
│ └── style.xml
│ ├── values-v20
│ └── style.xml
│ ├── values-v21
│ └── style.xml
│ ├── values-v22
│ └── style.xml
│ ├── values-v23
│ └── style.xml
│ ├── values-v24
│ └── style.xml
│ ├── values-v25
│ └── style.xml
│ └── values
│ ├── colors.xml
│ ├── strings.xml
│ ├── style.xml
│ └── styles.xml
├── build.gradle
├── config.gradle
├── gif
├── demo.gif
└── demo2.gif
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
├── sign
├── JustKiddingBaby.jks
└── README.txt
└── slidemenu
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
└── main
├── AndroidManifest.xml
├── java
└── com
│ └── jkb
│ └── slidemenu
│ ├── OnSlideChangedListener.java
│ ├── SlideMenuAction.java
│ └── SlideMenuLayout.java
└── res
└── values
├── attrs.xml
└── strings.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | /captures
7 | .externalNativeBuild
8 | /.idea
--------------------------------------------------------------------------------
/README-CN.md:
--------------------------------------------------------------------------------
1 | # SlideMenuLayout
2 | ## 简介
3 | 一个支持左右滑动并带有视差滑动效果的安卓滑动菜单控件。
4 | [](http://developer.android.com/index.html)
5 |
6 | [](https://android-arsenal.com/api?level=11)
7 |
8 | ## 演示
9 | 封装不同场景下的滑动嵌套
10 |
11 |
12 | ## 特性
13 | - [x] **支持滑动方向的配置**
14 | - [x] **直接作为控件使用**
15 | - [x] **处理各个场景下的滑动冲突**
16 | - [x] **侧滑菜单打开时候点击主体布局关闭侧滑菜单(可配置)**
17 | - [x] **侧滑菜单打开/关闭的时候主体布局暗度自动变化(可配置)**
18 | - [x] **支持滑动视差效果(可配置)**
19 |
20 | ## 最新版本
21 | |模块|slideMenuLayout|
22 | |---|---|
23 | |最新版本||
24 |
25 | ## 集成
26 | #### Maven集成
27 | ```xml
28 |
29 | com.justkiddingbaby
30 | slidemenu
31 | 最新版本
32 | pom
33 |
34 | ```
35 | #### JCenter集成
36 | 第一步 在项目build.gradle中添加
37 | ```gradle
38 | repositories {
39 | jcenter()
40 | }
41 | ```
42 | 第一步 在module的build.gradle中添加
43 | ```gradle
44 | compile 'com.justkiddingbaby:slidemenu:最新版本'
45 | ```
46 |
47 | ## 属性说明
48 | |属性|说明|值|
49 | |---|---|---|
50 | |[slideMode](/slidemenu/src/main/res/values/attrs.xml)|滑动模式|left right both none|
51 | |[slidePadding](/slidemenu/src/main/res/values/attrs.xml)|滑动菜单打开时候主视图预留边界|dimension|
52 | |[slideTime](/slidemenu/src/main/res/values/attrs.xml)|滑动菜单单开的时间,默认800ms|integer|
53 | |[parallax](/slidemenu/src/main/res/values/attrs.xml)|是否允許滑动视差效果,默认true|boolean|
54 | |[contentAlpha](/slidemenu/src/main/res/values/attrs.xml)|设置侧滑菜单打开时候ContentView的阴影透明度(范围0
92 |
93 |
94 |
95 |
96 | ```
97 | #### 注意
98 | **[SlideMenuLayout](/slidemenu/src/main/java/com/jkb/slidemenu/SlideMenuLayout.java)中布局的顺序是侧滑菜单布局在前,主体内容在后(为了防止右滑菜单重叠问题)。**
99 | 要是slideMode为both时,则SlideMenuLayout必须要有三个子视图,否则会抛出异常。
100 |
101 | ## 发布历史
102 | #### v1.3.0(2017/12/25)
103 | 1、添加特性:添加禁止拖动菜单(只能通过打开/关闭/切换方法打开)支持.
104 | 2、添加特性:添加菜单打开变化时候的监听器.
105 | #### v1.2.2(2017/12/18)
106 | 1、修复[issue#5](https://github.com/JustKiddingBaby/SlideMenuLayout/issues/5)
107 | #### v1.2.1(2017/9/18)
108 | 1、当`contentToggle`属性的值为`true`时,拦截`content view`的touch事件.
109 | #### v1.2.0(2017/8/20)
110 | 1、添加特性:侧滑菜单打开时候点击主体布局关闭侧滑菜单(可配置).
111 | 2、添加特性:侧滑菜单打开/关闭的时候主体布局暗度自动变化(可配置).
112 | 3、添加特性:支持滑动视差效果(可配置).
113 | #### v1.0.1(2017/6/9)
114 | 1、修改最低版本SDK为12.
115 | #### v1.0.0(2017/6/8)
116 | 1、发布SlideMenuLayout,处理各个场景下的滑动冲突。
117 | 2、封装demo。
118 |
119 | ## License
120 | 
121 |
122 | 本框架遵循MIT开源协议. 浏览[LICENSE](https://opensource.org/licenses/MIT)查看更多信息.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SlideMenuLayout
2 | ## Introduction
3 | An android slide menu that supports left and right swipes and slides with parallax.
4 | 一个支持左右滑动并带有视差滑动效果的安卓滑动菜单控件。([中文版入口](README-CN.md))
5 | [](http://developer.android.com/index.html)
6 |
7 | [](https://android-arsenal.com/api?level=11)
8 |
9 | ## Demo
10 | Encapsulate the sliding nesting of different scenarios.
11 |
12 |
13 | ## Features
14 | - [x] **Support for sliding direction configuration**
15 | - [x] **Can be used as ``ViewGroup``**
16 | - [x] **Handle the sliding conflicts in each scenarios**
17 | - [x] **Option to click on content view to close menu when it's opening**
18 | - [x] **Option to dim the content view automatically**
19 | - [x] **Option to toggle the parallax effect**
20 |
21 | ## Version
22 | |name|SlideMenuLayout|
23 | |---|---|
24 | |latest||
25 |
26 | ## Configure
27 | #### Maven
28 | ```xml
29 |
30 | com.justkiddingbaby
31 | slidemenu
32 | the latest version
33 | pom
34 |
35 | ```
36 | #### JCenter
37 | First. add to project build.gradle
38 | ```gradle
39 | repositories {
40 | jcenter()
41 | }
42 | ```
43 | Second. add to module build.gradle
44 | ```gradle
45 | compile 'com.justkiddingbaby:slidemenu:the latest version'
46 | ```
47 |
48 | ## Attributes instruction
49 | |attribute|instruction|value|
50 | |---|---|---|
51 | |[slideMode](/slidemenu/src/main/res/values/attrs.xml)|sliding mode|left right both none|
52 | |[slidePadding](/slidemenu/src/main/res/values/attrs.xml)|the content view padding when slide menu is opened|dimension|
53 | |[slideTime](/slidemenu/src/main/res/values/attrs.xml)|the time of slide menu open,the default value is 800ms|integer|
54 | |[parallax](/slidemenu/src/main/res/values/attrs.xml)|option to toggle the parallax effect,default is true|boolean|
55 | |[contentAlpha](/slidemenu/src/main/res/values/attrs.xml)|the alpha of shadow for `ContentView` when menu is opened.(0
93 |
94 |
95 |
96 |
97 | ```
98 | #### Mind
99 | **when you use [SlideMenuLayout](/slidemenu/src/main/java/com/jkb/slidemenu/SlideMenuLayout.java) in layout,it can only host three child view,and the left slide menu view and the right slide menu view must add before the content view (for prevent the right slide menu from overlapping).**
100 | if slideMode is both then the SlideViewLayout must host three child views.
101 |
102 | ## Release history
103 | #### v1.3.0(2017/12/25)
104 | 1、Add feature: Enables or disables dragging for this view.
105 | 2、Add feature: Add listener to register a callback to be invoked when this slide is changed.
106 | #### v1.2.2(2017/12/18)
107 | 1、Fix [issue#5](https://github.com/JustKiddingBaby/SlideMenuLayout/issues/5)
108 | #### v1.2.1(2017/9/18)
109 | 1、Intercept the touch action of `content view` when `contentToggle` attribute's value is true.
110 | #### v1.2.0(2017/8/20)
111 | 1、Add feature: Option to click on content view to close menu when it's opening.
112 | 2、Add feature: Option to dim the content view automatically.
113 | 3、Add feature: Option to toggle the parallax effect.
114 | #### v1.0.1(2017/6/29)
115 | 1、Update minSdkVersion to SDK 12.
116 | #### v1.0.0(2017/6/8)
117 | 1、Release SlideMenuLayout,Handle the sliding conflicts in each scenarios.
118 | 2、Encapsulation demo.
119 |
120 | ## License
121 | 
122 |
123 | This library is available under the MIT license. See the [LICENSE](https://opensource.org/licenses/MIT) file for more info.
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 |
5 | compileSdkVersion rootProject.ext.android.compileSdkVersion
6 | buildToolsVersion rootProject.ext.android.buildToolsVersion
7 |
8 | defaultConfig {
9 | applicationId rootProject.ext.app.applicationId
10 | minSdkVersion rootProject.ext.android.minSdkVersion
11 | targetSdkVersion rootProject.ext.android.targetSdkVersion
12 | versionCode rootProject.ext.app.versionCode
13 | versionName rootProject.ext.app.versionName
14 | }
15 |
16 | compileOptions {
17 | sourceCompatibility rootProject.ext.android.sourceCompatibilityVersion
18 | targetCompatibility rootProject.ext.android.targetCompatibilityVersion
19 | }
20 |
21 | signingConfigs {
22 | myConfig {
23 | storeFile file(rootProject.ext.store.storeKey)
24 | storePassword rootProject.ext.store.storePassword
25 | keyAlias rootProject.ext.store.keyAlias
26 | keyPassword rootProject.ext.store.keyPassword
27 | v2SigningEnabled false
28 | }
29 | }
30 |
31 | buildTypes {
32 | release {
33 | minifyEnabled true
34 | //是否清理无用资源
35 | shrinkResources true
36 | //是否启用zipAlign压缩
37 | zipAlignEnabled true
38 | signingConfig signingConfigs.myConfig
39 | versionNameSuffix rootProject.ext.app.versionNameSuffix
40 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
41 | }
42 | debug {
43 | signingConfig signingConfigs.myConfig
44 | versionNameSuffix rootProject.ext.app.versionNameSuffix
45 | }
46 | }
47 |
48 | lintOptions {
49 | abortOnError false
50 | }
51 | }
52 |
53 | dependencies {
54 | compile rootProject.ext.dependencies.design
55 | compile project(":slidemenu")
56 | }
57 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/yangjing/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout;
2 |
3 | import android.os.Build;
4 | import android.os.Bundle;
5 | import android.support.design.widget.TabLayout;
6 | import android.support.v4.view.ViewPager;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.util.Log;
11 | import android.view.View;
12 | import android.view.WindowManager;
13 |
14 | import com.jkb.slidemenu.OnSlideChangedListener;
15 | import com.jkb.slidemenu.SlideMenuLayout;
16 | import com.jkb.slidemenulayout.adapter.ContentAdapter;
17 | import com.jkb.slidemenulayout.adapter.SlideLeftAdapter;
18 | import com.jkb.slidemenulayout.adapter.SlideRightMenuAdapter;
19 |
20 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
21 |
22 | private String TAG = this.getClass().getSimpleName();
23 | //ui
24 | private SlideMenuLayout slideMenuLayout;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.activity_main);
30 | initStatusBar();
31 | initView();
32 | }
33 |
34 | /**
35 | * 初始化View
36 | */
37 | private void initView() {
38 | slideMenuLayout = (SlideMenuLayout) findViewById(R.id.mainSlideMenu);
39 |
40 | //right
41 | TabLayout slideTabLayout = (TabLayout) findViewById(R.id.fmr_tab);
42 | ViewPager slideViewPager = (ViewPager) findViewById(R.id.fmr_vp);
43 | slideTabLayout.addTab(slideTabLayout.newTab());
44 | slideTabLayout.addTab(slideTabLayout.newTab());
45 | slideViewPager.setAdapter(new SlideRightMenuAdapter(getSupportFragmentManager()));
46 | slideTabLayout.setupWithViewPager(slideViewPager);
47 | //left
48 | RecyclerView leftRecyclerView = (RecyclerView) findViewById(R.id.cml_rv);
49 | leftRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
50 | SlideLeftAdapter slideLeftAdapter = new SlideLeftAdapter(this);
51 | leftRecyclerView.setAdapter(slideLeftAdapter);
52 | //content
53 | TabLayout contentTabLayout = (TabLayout) findViewById(R.id.am_tab);
54 | ViewPager contentViewPager = (ViewPager) findViewById(R.id.am_vp);
55 | contentTabLayout.addTab(contentTabLayout.newTab());
56 | contentTabLayout.addTab(contentTabLayout.newTab());
57 | contentViewPager.setAdapter(new ContentAdapter(getSupportFragmentManager()));
58 | contentTabLayout.setupWithViewPager(contentViewPager);
59 |
60 | findViewById(R.id.fm_leftMenu).setOnClickListener(this);
61 | findViewById(R.id.fm_rightMenu).setOnClickListener(this);
62 | slideMenuLayout.addOnSlideChangedListener(new OnSlideChangedListener() {
63 | @Override
64 | public void onSlideChanged(SlideMenuLayout slideMenu, boolean isLeftSlideOpen, boolean isRightSlideOpen) {
65 | Log.d(TAG, "onSlideChanged:isLeftSlideOpen=" + isLeftSlideOpen + ":isRightSlideOpen=" + isRightSlideOpen);
66 | }
67 | });
68 | }
69 |
70 | /**
71 | * 初始化沉浸式状态栏
72 | */
73 | private void initStatusBar() {
74 | //设置是否沉浸式
75 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
76 | int flag_translucent_status = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
77 | //透明状态栏
78 | getWindow().setFlags(flag_translucent_status, flag_translucent_status);
79 | }
80 |
81 | @Override
82 | public void onClick(View v) {
83 | switch (v.getId()) {
84 | case R.id.fm_leftMenu:
85 | slideMenuLayout.toggleLeftSlide();
86 | break;
87 | case R.id.fm_rightMenu:
88 | slideMenuLayout.toggleRightSlide();
89 | break;
90 | }
91 | }
92 |
93 | @Override
94 | public void onBackPressed() {
95 | if (slideMenuLayout.isLeftSlideOpen() || slideMenuLayout.isRightSlideOpen()) {
96 | slideMenuLayout.closeLeftSlide();
97 | slideMenuLayout.closeRightSlide();
98 | } else {
99 | super.onBackPressed();
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/adapter/ContentAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentPagerAdapter;
6 |
7 | import com.jkb.slidemenulayout.ui.ChatFragment;
8 | import com.jkb.slidemenulayout.ui.FriendFragment;
9 | import com.jkb.slidemenulayout.ui.TabOneFragment;
10 | import com.jkb.slidemenulayout.ui.TabTwoFragment;
11 |
12 | /**
13 | * 右滑菜单适配器
14 | * Created by yangjing on 17-6-7.
15 | */
16 |
17 | public class ContentAdapter extends FragmentPagerAdapter {
18 |
19 | private String[] menuNames = new String[]{
20 | "One", "Two"
21 | };
22 |
23 | public ContentAdapter(FragmentManager fm) {
24 | super(fm);
25 | }
26 |
27 | @Override
28 | public Fragment getItem(int position) {
29 | if (position == 0) {
30 | return TabOneFragment.newInstance();
31 | } else {
32 | return TabTwoFragment.newInstance();
33 | }
34 | }
35 |
36 | @Override
37 | public int getCount() {
38 | return menuNames.length;
39 | }
40 |
41 | @Override
42 | public CharSequence getPageTitle(int position) {
43 | return menuNames[position];
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/adapter/FriendAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import com.jkb.slidemenulayout.R;
11 |
12 | /**
13 | * 好友列表的数据适配器
14 | * Created by yangjing on 17-6-8.
15 | */
16 |
17 | public class FriendAdapter extends RecyclerView.Adapter {
18 |
19 | private Context context;
20 |
21 | public FriendAdapter(Context context) {
22 | this.context = context;
23 | }
24 |
25 | @Override
26 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
27 | View view = LayoutInflater.from(context).inflate(R.layout.item_friend, parent, false);
28 | return new ViewHolder(view);
29 | }
30 |
31 | @Override
32 | public void onBindViewHolder(ViewHolder holder, int position) {
33 | holder.tvFriend.setText("friend" + position);
34 | }
35 |
36 | @Override
37 | public int getItemCount() {
38 | return 20;
39 | }
40 |
41 | class ViewHolder extends RecyclerView.ViewHolder {
42 |
43 | TextView tvFriend;
44 |
45 | public ViewHolder(View itemView) {
46 | super(itemView);
47 | tvFriend = (TextView) itemView.findViewById(R.id.if_tv);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/adapter/SlideLeftAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import com.jkb.slidemenulayout.R;
11 |
12 | /**
13 | * 好友列表的数据适配器
14 | * Created by yangjing on 17-6-8.
15 | */
16 |
17 | public class SlideLeftAdapter extends RecyclerView.Adapter {
18 |
19 | private Context context;
20 |
21 | public SlideLeftAdapter(Context context) {
22 | this.context = context;
23 | }
24 |
25 | @Override
26 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
27 | View view = LayoutInflater.from(context).inflate(R.layout.item_friend, parent, false);
28 | return new ViewHolder(view);
29 | }
30 |
31 | @Override
32 | public void onBindViewHolder(ViewHolder holder, int position) {
33 | holder.tvFriend.setText("menu" + position);
34 | }
35 |
36 | @Override
37 | public int getItemCount() {
38 | return 20;
39 | }
40 |
41 | class ViewHolder extends RecyclerView.ViewHolder {
42 |
43 | TextView tvFriend;
44 |
45 | public ViewHolder(View itemView) {
46 | super(itemView);
47 | tvFriend = (TextView) itemView.findViewById(R.id.if_tv);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/adapter/SlideRightMenuAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.adapter;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.support.v4.app.FragmentManager;
5 | import android.support.v4.app.FragmentPagerAdapter;
6 |
7 | import com.jkb.slidemenulayout.ui.ChatFragment;
8 | import com.jkb.slidemenulayout.ui.FriendFragment;
9 |
10 | /**
11 | * 右滑菜单适配器
12 | * Created by yangjing on 17-6-7.
13 | */
14 |
15 | public class SlideRightMenuAdapter extends FragmentPagerAdapter {
16 |
17 | private String[] menuNames = new String[]{
18 | "chat", "friend"
19 | };
20 |
21 | public SlideRightMenuAdapter(FragmentManager fm) {
22 | super(fm);
23 | }
24 |
25 | @Override
26 | public Fragment getItem(int position) {
27 | if (position == 0) {
28 | return ChatFragment.newInstance();
29 | } else {
30 | return FriendFragment.newInstance();
31 | }
32 | }
33 |
34 | @Override
35 | public int getCount() {
36 | return menuNames.length;
37 | }
38 |
39 | @Override
40 | public CharSequence getPageTitle(int position) {
41 | return menuNames[position];
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/adapter/TabTwoAdapter.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.adapter;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import com.jkb.slidemenulayout.R;
11 |
12 | /**
13 | * TabTwo的数据适配器
14 | * Created by yangjing on 17-6-8.
15 | */
16 |
17 | public class TabTwoAdapter extends RecyclerView.Adapter {
18 |
19 | private Context context;
20 |
21 | public TabTwoAdapter(Context context) {
22 | this.context = context;
23 | }
24 |
25 | @Override
26 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
27 | View view = LayoutInflater.from(context).inflate(R.layout.item_tab_two, parent, false);
28 | return new ViewHolder(view);
29 | }
30 |
31 | @Override
32 | public void onBindViewHolder(ViewHolder holder, int position) {
33 | holder.tvFriend.setText("Tab two item" + position);
34 | }
35 |
36 | @Override
37 | public int getItemCount() {
38 | return 20;
39 | }
40 |
41 | class ViewHolder extends RecyclerView.ViewHolder {
42 |
43 | TextView tvFriend;
44 |
45 | public ViewHolder(View itemView) {
46 | super(itemView);
47 | tvFriend = (TextView) itemView.findViewById(R.id.if_tv);
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/ui/ChatFragment.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.jkb.slidemenulayout.R;
11 |
12 | /**
13 | * 好友列表
14 | * Created by yangjing on 17-6-7.
15 | */
16 |
17 | public class ChatFragment extends Fragment {
18 |
19 | public static ChatFragment newInstance() {
20 | Bundle args = new Bundle();
21 | ChatFragment fragment = new ChatFragment();
22 | fragment.setArguments(args);
23 | return fragment;
24 | }
25 |
26 | @Nullable
27 | @Override
28 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
29 | View rootView = inflater.inflate(R.layout.frg_chat, container, false);
30 | return rootView;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/ui/FriendFragment.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.ui;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.jkb.slidemenulayout.R;
14 | import com.jkb.slidemenulayout.adapter.FriendAdapter;
15 |
16 | /**
17 | * 好友列表
18 | * Created by yangjing on 17-6-7.
19 | */
20 |
21 | public class FriendFragment extends Fragment {
22 |
23 | public static FriendFragment newInstance() {
24 | Bundle args = new Bundle();
25 | FriendFragment fragment = new FriendFragment();
26 | fragment.setArguments(args);
27 | return fragment;
28 | }
29 |
30 | //ui
31 | private Context mContext;
32 |
33 | @Nullable
34 | @Override
35 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
36 | View rootView = inflater.inflate(R.layout.frg_friend, container, false);
37 | RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.ff_rv);
38 | recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
39 | FriendAdapter friendAdapter = new FriendAdapter(mContext);
40 | recyclerView.setAdapter(friendAdapter);
41 | return rootView;
42 | }
43 |
44 | @Override
45 | public void onAttach(Context context) {
46 | super.onAttach(context);
47 | mContext = context;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/ui/TabOneFragment.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.ui;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.support.v4.app.Fragment;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.jkb.slidemenulayout.R;
11 |
12 | /**
13 | * TabOne
14 | * Created by yangjing on 17-6-7.
15 | */
16 |
17 | public class TabOneFragment extends Fragment {
18 |
19 | public static TabOneFragment newInstance() {
20 | Bundle args = new Bundle();
21 | TabOneFragment fragment = new TabOneFragment();
22 | fragment.setArguments(args);
23 | return fragment;
24 | }
25 |
26 | @Nullable
27 | @Override
28 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
29 | View rootView = inflater.inflate(R.layout.frg_tab_one, container, false);
30 | return rootView;
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/jkb/slidemenulayout/ui/TabTwoFragment.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenulayout.ui;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.support.v7.widget.LinearLayoutManager;
8 | import android.support.v7.widget.RecyclerView;
9 | import android.view.LayoutInflater;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 |
13 | import com.jkb.slidemenulayout.R;
14 | import com.jkb.slidemenulayout.adapter.FriendAdapter;
15 | import com.jkb.slidemenulayout.adapter.TabTwoAdapter;
16 |
17 | /**
18 | * TabTwo
19 | * Created by yangjing on 17-6-7.
20 | */
21 |
22 | public class TabTwoFragment extends Fragment {
23 |
24 | public static TabTwoFragment newInstance() {
25 | Bundle args = new Bundle();
26 | TabTwoFragment fragment = new TabTwoFragment();
27 | fragment.setArguments(args);
28 | return fragment;
29 | }
30 |
31 | //ui
32 | private Context mContext;
33 |
34 | @Nullable
35 | @Override
36 | public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
37 | View rootView = inflater.inflate(R.layout.frg_tab_two, container, false);
38 | RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.ff_rv);
39 | recyclerView.setLayoutManager(new LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false));
40 | TabTwoAdapter tabTwoAdapter = new TabTwoAdapter(mContext);
41 | recyclerView.setAdapter(tabTwoAdapter);
42 | return rootView;
43 | }
44 |
45 | @Override
46 | public void onAttach(Context context) {
47 | super.onAttach(context);
48 | mContext = context;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_conversations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/drawable-xxhdpi/ic_action_conversations.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable-xxhdpi/ic_action_menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/drawable-xxhdpi/ic_action_menu.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
19 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
35 |
36 |
39 |
40 |
49 |
50 |
59 |
60 |
69 |
70 |
71 |
72 |
84 |
85 |
86 |
92 |
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_menu_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
17 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/content_menu_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
20 |
31 |
32 |
33 |
38 |
39 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/frg_chat.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/frg_friend.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/frg_tab_one.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/frg_tab_two.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_friend.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_tab_two.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values-v19/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v20/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v21/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v22/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v23/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v24/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values-v25/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #bd3e27
5 | #702314
6 | #bd3e27
7 |
8 | #00FFFFFF
9 | #e7e7e7
10 | #fdfdfe
11 | #333333
12 | #999999
13 |
14 |
15 | #FFFFFF
16 | #000000
17 | #C0C0C0
18 | #FF0000
19 | #2b8ad6
20 | #26292b
21 |
22 |
23 | #666666
24 | #999999
25 | #fbba39
26 | #83b6f7
27 |
28 |
29 | #1a000000
30 | #46000000
31 | #46FFFFFF
32 | #1EFFFFFF
33 | #99ffffff
34 | #55c0c0c0
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SlideMenuLayout
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/style.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
15 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
13 |
14 |
15 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | apply from: "config.gradle"
4 |
5 | buildscript {
6 | repositories {
7 | jcenter()
8 | }
9 | dependencies {
10 | classpath 'com.android.tools.build:gradle:2.3.2'
11 |
12 | classpath 'com.novoda:bintray-release:0.3.4'
13 |
14 | // NOTE: Do not place your application dependencies here; they belong
15 | // in the individual module build.gradle files
16 | }
17 | }
18 |
19 | allprojects {
20 | repositories {
21 | jcenter()
22 | maven { url 'https://jitpack.io' }
23 | }
24 | tasks.withType(Javadoc) {
25 | options.addStringOption('Xdoclint:none', '-quiet')
26 | options.addStringOption('encoding', 'UTF-8')
27 | }
28 | }
29 |
30 | task clean(type: Delete) {
31 | delete rootProject.buildDir
32 | }
33 |
--------------------------------------------------------------------------------
/config.gradle:
--------------------------------------------------------------------------------
1 | import java.util.regex.Matcher
2 | import java.util.regex.Pattern
3 |
4 | ext {
5 | app = [
6 | appVerCode : 1,
7 | appVerName : "0.0.1" + "-${releaseTime()}",
8 | applicationId : "com.jkb.supportfragment.demo",
9 | versionNameSuffix: getCurrentVersionSuffix(),
10 | minSdkVersion : 14
11 | ]
12 |
13 | slidemenu = [
14 | publishCode : 6,
15 | publishVersion: "1.3.0",
16 |
17 | userOrg : 'jkb',
18 | groupId : 'com.justkiddingbaby',
19 | artifactId : 'slidemenu',
20 | desc : 'An Android slide menu layout that support left slide and right slide.',
21 | website : 'https://github.com/YangJing96/SlideMenuLayout'
22 | ]
23 |
24 | android = [
25 | minSdkVersion : 12,
26 | targetSdkVersion : 23,
27 | compileSdkVersion : 23,
28 | buildToolsVersion : "25.0.0",
29 | sourceCompatibilityVersion: JavaVersion.VERSION_1_7,
30 | targetCompatibilityVersion: JavaVersion.VERSION_1_7
31 | ]
32 |
33 | dependencies = [
34 | appcompatV7: 'com.android.support:appcompat-v7:23.0.1',
35 | design : 'com.android.support:design:24.0.0',
36 | ]
37 |
38 | store = [
39 | storeKey : '../sign/JustKiddingBaby.jks',
40 | storePassword: 'mimajiushiwo',
41 | keyAlias : 'JustKiddingBaby',
42 | keyPassword : 'mimajiushiwo'
43 | ]
44 | }
45 |
46 | def static releaseTime() {
47 | return new Date().format("yyyyMMdd", TimeZone.getTimeZone("GMT+8"))
48 | }
49 |
50 | def getCurrentVersionSuffix() {
51 | def currentFlavor = getCurrentFlavor()
52 | if (currentFlavor == "prod") {
53 | return "-prod"
54 | } else if (currentFlavor == "uat") {
55 | return "-uat"
56 | } else if (currentFlavor == "dev") {
57 | return "-dev"
58 | }
59 | }
60 |
61 | def getCurrentFlavor() {
62 | String taskRequestName = getGradle().getStartParameter().getTaskRequests().toString()
63 | Pattern pattern;
64 | if (taskRequestName.contains("assemble")) {
65 | pattern = Pattern.compile("assemble(\\w+)(Release|Debug)")
66 | } else {
67 | pattern = Pattern.compile("generate(\\w+)(Release|Debug)")
68 | }
69 | Matcher matcher = pattern.matcher(taskRequestName)
70 | if (matcher.find()) {
71 | return matcher.group(1).toLowerCase()
72 | } else {
73 | return "";
74 | }
75 | }
--------------------------------------------------------------------------------
/gif/demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/gif/demo.gif
--------------------------------------------------------------------------------
/gif/demo2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/gif/demo2.gif
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 07 14:54:00 CST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':slidemenu'
2 |
--------------------------------------------------------------------------------
/sign/JustKiddingBaby.jks:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JingYeoh/SlideMenuLayout/4428467efc11cc62ba2aee15a38ec666fbfd8722/sign/JustKiddingBaby.jks
--------------------------------------------------------------------------------
/sign/README.txt:
--------------------------------------------------------------------------------
1 | Password:mimajiushiwo
2 | Alians:JustKiddingBaby
3 | Password:mimajiushiwo
--------------------------------------------------------------------------------
/slidemenu/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/slidemenu/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.novoda.bintray-release'
3 |
4 |
5 | publish {
6 | userOrg = rootProject.ext.slidemenu.userOrg
7 | groupId = rootProject.ext.slidemenu.groupId
8 | artifactId = rootProject.ext.slidemenu.artifactId
9 | publishVersion = rootProject.ext.slidemenu.publishVersion
10 | desc = rootProject.ext.slidemenu.desc
11 | website = rootProject.ext.slidemenu.website
12 | }
13 |
14 | android {
15 |
16 | compileSdkVersion rootProject.ext.android.compileSdkVersion
17 | buildToolsVersion rootProject.ext.android.buildToolsVersion
18 |
19 | defaultConfig {
20 | minSdkVersion rootProject.ext.android.minSdkVersion
21 | targetSdkVersion rootProject.ext.android.targetSdkVersion
22 | versionCode rootProject.ext.slidemenu.publishCode
23 | versionName rootProject.ext.slidemenu.publishVersion
24 | }
25 |
26 | compileOptions {
27 | sourceCompatibility rootProject.ext.android.sourceCompatibilityVersion
28 | targetCompatibility rootProject.ext.android.targetCompatibilityVersion
29 | }
30 |
31 | buildTypes {
32 | release {
33 | minifyEnabled false
34 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
35 | }
36 | }
37 |
38 | lintOptions {
39 | abortOnError false
40 | }
41 | }
42 |
43 | dependencies {
44 | compile rootProject.ext.dependencies.appcompatV7
45 | }
46 |
--------------------------------------------------------------------------------
/slidemenu/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /home/yangjing/Android/Sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/slidemenu/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/slidemenu/src/main/java/com/jkb/slidemenu/OnSlideChangedListener.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenu;
2 |
3 | /**
4 | * 侧滑菜单变化时候的监听器.
5 | *
6 | * @author JingYeoh
7 | * Email me
8 | * Github
9 | * Blog
10 | * @since Dec 25,2017
11 | */
12 |
13 | public interface OnSlideChangedListener {
14 |
15 | /**
16 | * 侧滑菜单状态变化
17 | *
18 | * @param slideMenu 侧滑菜单{@link SlideMenuLayout}
19 | * @param isLeftSlideOpen 左滑菜单是否打开
20 | * @param isRightSlideOpen 右滑菜单是否打开
21 | */
22 | void onSlideChanged(SlideMenuLayout slideMenu, boolean isLeftSlideOpen, boolean isRightSlideOpen);
23 | }
24 |
--------------------------------------------------------------------------------
/slidemenu/src/main/java/com/jkb/slidemenu/SlideMenuAction.java:
--------------------------------------------------------------------------------
1 | package com.jkb.slidemenu;
2 |
3 | import android.support.annotation.ColorRes;
4 | import android.support.annotation.FloatRange;
5 | import android.support.annotation.IntDef;
6 | import android.view.View;
7 |
8 | import java.lang.annotation.Retention;
9 | import java.lang.annotation.RetentionPolicy;
10 |
11 | /**
12 | * 侧滑菜单的动作
13 | * Created by JustKiddingBaby on 2017/6/3.
14 | */
15 |
16 | public interface SlideMenuAction {
17 |
18 | /**
19 | * 只支持左侧滑
20 | */
21 | int SLIDE_MODE_LEFT = 1001;
22 | /**
23 | * 只支持右侧滑
24 | */
25 | int SLIDE_MODE_RIGHT = 1002;
26 | /**
27 | * 支持左侧滑和右侧滑
28 | */
29 | int SLIDE_MODE_LEFT_RIGHT = 1003;
30 | /**
31 | * 左滑右滑均不支持
32 | */
33 | int SLIDE_MODE_NONE = 1004;
34 |
35 | /**
36 | * set slide mode.(设置Slide模式)
37 | *
38 | * @param slideMode {@link #SLIDE_MODE_LEFT},{@link #SLIDE_MODE_LEFT_RIGHT},
39 | * {@link #SLIDE_MODE_RIGHT},{@link #SLIDE_MODE_NONE}
40 | */
41 | void setSlideMode(@SlideMode int slideMode);
42 |
43 | /**
44 | * 设置侧滑菜单打开时候距离主视图的padding
45 | *
46 | * @param slidePadding 单位px
47 | */
48 | void setSlidePadding(int slidePadding);
49 |
50 | /**
51 | * 设置滑动菜单打开的时间
52 | *
53 | * @param slideTime 单位ms
54 | */
55 | void setSlideTime(int slideTime);
56 |
57 | /**
58 | * 设置视差效果开关
59 | *
60 | * @param parallax 视差效果开关,Default:true
61 | */
62 | void setParallaxSwitch(boolean parallax);
63 |
64 | /**
65 | * 设置在侧滑菜单打开时候的ContentView的透明度,该值会在侧滑的时候不断变化,从1.0变化至设置的值.
66 | *
67 | * @param contentAlpha 0 3) {
122 | throw new IllegalStateException("SlideMenuLayout can host only three direct child");
123 | }
124 | super.addView(child);
125 | }
126 |
127 | @Override
128 | public void addView(View child, int index) {
129 | if (getChildCount() > 3) {
130 | throw new IllegalStateException("SlideMenuLayout can host only three direct child");
131 | }
132 | super.addView(child, index);
133 | }
134 |
135 | @Override
136 | public void addView(View child, LayoutParams params) {
137 | if (getChildCount() > 3) {
138 | throw new IllegalStateException("SlideMenuLayout can host only three direct child");
139 | }
140 | super.addView(child, params);
141 | }
142 |
143 | @Override
144 | public void addView(View child, int index, LayoutParams params) {
145 | if (getChildCount() > 3) {
146 | throw new IllegalStateException("SlideMenuLayout can host only three direct child");
147 | }
148 | super.addView(child, index, params);
149 | }
150 |
151 | @Override
152 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
153 | //默认全屏
154 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
155 | int widthSize = MeasureSpec.getSize(widthMeasureSpec);
156 | int widthResult = 0;
157 | if (widthMode == MeasureSpec.EXACTLY) {
158 | widthResult = widthSize;
159 | } else {
160 | widthResult = screenWidth;
161 | }
162 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
163 | int heightSize = MeasureSpec.getSize(heightMeasureSpec);
164 | int heightResult = 0;
165 | if (heightMode == MeasureSpec.EXACTLY) {
166 | heightResult = heightSize;
167 | } else {
168 | heightResult = screenHeight;
169 | }
170 | //初始化侧滑菜单
171 | initSlideView(widthResult, heightResult);
172 |
173 | measureSlideChild(mContentView, widthMeasureSpec, heightMeasureSpec);
174 | measureSlideChild(mLeftView, widthMeasureSpec, heightMeasureSpec);
175 | measureSlideChild(mRightView, widthMeasureSpec, heightMeasureSpec);
176 |
177 | setMeasuredDimension(mContentWidth, mContentHeight);
178 | }
179 |
180 | @Override
181 | protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
182 | boolean result = super.drawChild(canvas, child, drawingTime);
183 | if (child == mContentView) {
184 | int rX = Math.abs(getScrollX());
185 | int alpha = 0;
186 | if (rX == 0) {
187 | alpha = 0;
188 | } else if (rX >= mSlideWidth) {
189 | alpha = (int) ((1.0f - mContentAlpha) * 255);
190 | } else {
191 | alpha = (int) (Math.abs((1.0f - mContentAlpha) / mSlideWidth) * rX * 255);
192 | }
193 | alpha = alpha < 0 ? 255 : alpha;
194 | alpha = alpha > 255 ? 255 : alpha;
195 |
196 | mContentShadowPaint.setAlpha(alpha);
197 | canvas.drawRect(mContentView.getLeft(), mContentView.getTop(), mContentView.getRight(),
198 | mContentView.getBottom(), mContentShadowPaint);//画出阴影
199 | }
200 | return result;
201 | }
202 |
203 | @Override
204 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
205 | if (mLeftView != null) {
206 | mLeftView.layout(-mSlideWidth, 0, 0, mContentHeight);
207 | }
208 | if (mRightView != null) {
209 | mRightView.layout(mContentWidth, 0, mContentWidth + mSlideWidth, mContentHeight);
210 | }
211 | if (mContentView != null) {
212 | mContentView.layout(0, 0, mContentWidth, mContentHeight);
213 | }
214 | }
215 |
216 | @Override
217 | public void computeScroll() {
218 | super.computeScroll();
219 | if (mScroller.computeScrollOffset()) {
220 | scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
221 | if (mLeftView != null) {
222 | leftMenuParallax();
223 | }
224 | if (mRightView != null) {
225 | rightMenuParallax();
226 | }
227 | postInvalidate();
228 | changeContentViewAlpha();
229 | }
230 | }
231 |
232 | @Override
233 | public boolean onInterceptTouchEvent(MotionEvent ev) {
234 | boolean intercept = false;
235 | int x = (int) ev.getX();
236 | int y = (int) ev.getY();
237 | switch (ev.getAction()) {
238 | case MotionEvent.ACTION_DOWN:
239 | intercept = false;
240 | break;
241 | case MotionEvent.ACTION_MOVE:
242 | int deltaX = (int) ev.getX() - mLastXIntercept;
243 | int deltaY = (int) ev.getY() - mLastYIntercept;
244 | if (Math.abs(deltaX) > Math.abs(deltaY)) {//横向滑动
245 | if (mTriggerSlideLeft) {
246 | intercept = x > mSlideWidth;
247 | } else if (mTriggerSlideRight) {
248 | intercept = x < mSlidePadding;
249 | } else {
250 | //当手指在边缘地区的时候拦截事件
251 | //以下判断条件主要为了区分边界滑动
252 | if (mSlideMode == SLIDE_MODE_LEFT && deltaX > 0) {//左滑
253 | intercept = x <= mSlidePadding / 2;
254 | } else if (mSlideMode == SLIDE_MODE_RIGHT && deltaX < 0) {//右滑
255 | intercept = x >= mSlideWidth - mSlidePadding / 2;
256 | } else if (mSlideMode == SLIDE_MODE_LEFT_RIGHT) {//双向滑动
257 | if (deltaX > 0) intercept = x <= mSlidePadding / 2;
258 | if (deltaX < 0) intercept = x >= mSlideWidth - mSlidePadding / 2;
259 | } else {
260 | intercept = false;
261 | }
262 | }
263 | } else {//纵向滑动
264 | intercept = false;
265 | }
266 | break;
267 | case MotionEvent.ACTION_UP:
268 | // intercept = false;
269 | //点击ContentView后关闭侧滑菜单
270 | intercept = touchContentViewToCloseSlide();
271 | break;
272 | }
273 | mLastX = x;
274 | mLastXIntercept = x;
275 | mLastYIntercept = y;
276 | return intercept;
277 | }
278 |
279 | @Override
280 | public boolean onTouchEvent(MotionEvent event) {
281 | if (!mAllowDragging) return false;
282 | int action = event.getAction();
283 | switch (action) {
284 | case MotionEvent.ACTION_DOWN:
285 | mLastX = (int) event.getX();
286 | break;
287 | case MotionEvent.ACTION_MOVE:
288 | int currentX = (int) event.getX();
289 | //拿到x方向的偏移量
290 | int dx = currentX - mLastX;
291 | if (dx < 0) {//向左滑动
292 | scrollLeft(dx);
293 | } else {//向右滑动
294 | scrollRight(dx);
295 | }
296 | mLastX = currentX;
297 | mDx = dx;
298 | break;
299 | case MotionEvent.ACTION_UP:
300 | case MotionEvent.ACTION_CANCEL:
301 | if (mDx > 0) {//右滑
302 | inertiaScrollRight();
303 | } else {
304 | inertiaScrollLeft();
305 | }
306 | mDx = 0;
307 | break;
308 | }
309 | return true;
310 | }
311 |
312 | /**
313 | * 点击ContentView后关闭侧滑菜单
314 | */
315 | private boolean touchContentViewToCloseSlide() {
316 | if (!mContentToggle) return false;
317 | if (Math.abs(getScrollX()) < mSlideWidth) return false;
318 | int dX = getScrollX();
319 | if (dX < 0) {//左滑菜单打开
320 | if (mLastX > mSlideWidth) {
321 | closeLeftSlide();
322 | } else {
323 | return false;
324 | }
325 | } else if (dX > 0) {
326 | if (mLastX < (mContentWidth - mSlideWidth)) {
327 | closeRightSlide();
328 | } else {
329 | return false;
330 | }
331 | }
332 | return true;
333 | }
334 |
335 | /**
336 | * 惯性左滑
337 | */
338 | private void inertiaScrollLeft() {
339 | if (mSlideMode == SLIDE_MODE_RIGHT) {
340 | if (getScrollX() >= mSlideWidth / 2) {
341 | openRightSlide();
342 | } else {
343 | if (!mTriggerSlideRight) {
344 | closeRightSlide();
345 | }
346 | }
347 | } else if (mSlideMode == SLIDE_MODE_LEFT) {
348 | if (-getScrollX() <= mSlideWidth / 2) {
349 | closeLeftSlide();
350 | } else {
351 | if (mTriggerSlideLeft) {
352 | openLeftSlide();
353 | }
354 | }
355 | } else if (mSlideMode == SLIDE_MODE_LEFT_RIGHT) {
356 | if (!mTriggerSlideLeft && !mTriggerSlideRight) {//左右滑动菜单都关闭状态
357 | if (getScrollX() >= mSlideWidth / 2) {
358 | openRightSlide();
359 | } else {
360 | closeRightSlide();
361 | }
362 | } else if (mTriggerSlideLeft || getScrollX() < 0) {
363 | if (-getScrollX() <= mSlideWidth / 2) {
364 | closeLeftSlide();
365 | } else {
366 | openLeftSlide();
367 | }
368 | }
369 | }
370 | }
371 |
372 | /**
373 | * 惯性右滑
374 | */
375 | private void inertiaScrollRight() {
376 | if (mSlideMode == SLIDE_MODE_LEFT) {
377 | if (-getScrollX() >= mSlideWidth / 2) {
378 | openLeftSlide();
379 | } else {
380 | if (!mTriggerSlideLeft) {
381 | closeLeftSlide();
382 | }
383 | }
384 | } else if (mSlideMode == SLIDE_MODE_RIGHT) {
385 | if (getScrollX() <= mSlideWidth / 2) {
386 | closeRightSlide();
387 | } else {
388 | if (mTriggerSlideRight) {
389 | openRightSlide();
390 | }
391 | }
392 | } else if (mSlideMode == SLIDE_MODE_LEFT_RIGHT) {
393 | if (!mTriggerSlideLeft && !mTriggerSlideRight) {//左右滑动菜单都关闭状态
394 | if (-getScrollX() >= mSlideWidth / 2) {
395 | openLeftSlide();
396 | } else {
397 | closeLeftSlide();
398 | }
399 | } else if (mTriggerSlideRight || getScrollX() > 0) {
400 | if (getScrollX() <= mSlideWidth / 2) {
401 | closeRightSlide();
402 | } else {
403 | openRightSlide();
404 | }
405 | }
406 | }
407 | }
408 |
409 | /**
410 | * 向左滑动
411 | */
412 | private void scrollLeft(int dx) {
413 | if (mSlideMode == SLIDE_MODE_RIGHT) {
414 | //右滑菜单已经打开,不做操作
415 | if (mTriggerSlideRight || getScrollX() - dx >= mSlideWidth) {
416 | openRightSlide();
417 | return;
418 | }
419 | rightMenuParallax();
420 | } else if (mSlideMode == SLIDE_MODE_LEFT) {
421 | //左滑菜单未打开,不做操作
422 | if (!mTriggerSlideLeft || getScrollX() - dx >= 0) {
423 | closeLeftSlide();
424 | return;
425 | }
426 | leftMenuParallax();
427 | } else if (mSlideMode == SLIDE_MODE_LEFT_RIGHT) {
428 | //右滑菜单已经打开,不做操作
429 | if (mTriggerSlideRight || getScrollX() - dx >= mSlideWidth) {
430 | openRightSlide();
431 | return;
432 | }
433 | leftMenuParallax();
434 | rightMenuParallax();
435 | }
436 | scrollBy(-dx, 0);
437 | changeContentViewAlpha();
438 | }
439 |
440 | /**
441 | * 向右滑动
442 | */
443 | private void scrollRight(int dx) {
444 | if (mSlideMode == SLIDE_MODE_LEFT) {
445 | //左滑菜单已经打开,不做操作
446 | if (mTriggerSlideLeft || getScrollX() - dx <= -mSlideWidth) {
447 | openLeftSlide();
448 | return;
449 | }
450 | leftMenuParallax();
451 | } else if (mSlideMode == SLIDE_MODE_RIGHT) {
452 | //右滑菜单未打开,不做操作
453 | if (!mTriggerSlideRight || getScrollX() - dx <= 0) {
454 | closeRightSlide();
455 | return;
456 | }
457 | rightMenuParallax();
458 | } else if (mSlideMode == SLIDE_MODE_LEFT_RIGHT) {
459 | //左滑菜单已经打开,不做操作
460 | if (mTriggerSlideLeft || getScrollX() - dx <= -mSlideWidth) {
461 | openLeftSlide();
462 | return;
463 | }
464 | leftMenuParallax();
465 | rightMenuParallax();
466 | }
467 | scrollBy(-dx, 0);
468 | changeContentViewAlpha();
469 | }
470 |
471 | /**
472 | * 改变ContentView的透明度
473 | */
474 | private void changeContentViewAlpha() {
475 | /*int rX = Math.abs(getScrollX());
476 | float alpha = 1.0f;
477 | if (rX == 0) {
478 | alpha = 1.0f;
479 | } else if (rX == mSlideWidth) {
480 | alpha = mContentAlpha;
481 | } else {
482 | alpha = Math.abs(1.0f - ((1.0f - mContentAlpha) / mSlideWidth) * rX);
483 | }
484 | alpha = alpha < 0.1f ? 0.1f : alpha;
485 | alpha = alpha > 1.0f ? 1.0f : alpha;
486 | mContentView.setAlpha(alpha);*/
487 | postInvalidate();
488 | }
489 |
490 | /**
491 | * 右滑菜单的视差效果
492 | */
493 | private void rightMenuParallax() {
494 | if (!mParallax) return;
495 | int rightTranslationX = 2 * (-mSlideWidth + getScrollX()) / 3;
496 | //有菜单打开或者关闭的时候回恢复原位X
497 | if (getScrollX() == 0 || getScrollX() == mSlideWidth || getScrollX() == -mSlideWidth) {
498 | rightTranslationX = 0;
499 | }
500 | mRightView.setTranslationX(rightTranslationX);
501 | }
502 |
503 | /**
504 | * 左滑菜单的视差效果
505 | */
506 | private void leftMenuParallax() {
507 | if (!mParallax) return;
508 | int leftTranslationX = 2 * (mSlideWidth + getScrollX()) / 3;
509 | //有菜单打开或者关闭的时候回恢复原位
510 | if (getScrollX() == 0 || getScrollX() >= mSlideWidth || getScrollX() <= -mSlideWidth) {
511 | leftTranslationX = 0;
512 | }
513 | mLeftView.setTranslationX(leftTranslationX);
514 | }
515 |
516 | /**
517 | * 缓慢滑动
518 | */
519 | private void smoothScrollTo(int destX, int destY) {
520 | int scrollX = getScrollX();
521 | int deltaX = destX - scrollX;
522 | float time = deltaX * 1.0f / (mSlideWidth * 1.0f / mSlideTime);
523 | time = Math.abs(time);
524 | mScroller.startScroll(scrollX, 0, deltaX, destY, (int) time);
525 | invalidate();
526 | //Update listener
527 | if (mSlideChangedListener != null) {
528 | if (destX == -mSlideWidth) {//左滑打开
529 | mSlideChangedListener.onSlideChanged(this, true, false);
530 | } else if (destX == 0) {//关闭侧滑
531 | mSlideChangedListener.onSlideChanged(this, false, false);
532 | } else if (destX == mSlideWidth) {//右滑打开
533 | mSlideChangedListener.onSlideChanged(this, false, true);
534 | }
535 | }
536 | }
537 |
538 | /**
539 | * 测量子视图
540 | */
541 | private void measureSlideChild(View childView, int widthMeasureSpec, int heightMeasureSpec) {
542 | if (childView == null) return;
543 | LayoutParams lp = childView.getLayoutParams();
544 | int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec,
545 | getPaddingLeft() + getPaddingRight(), lp.width);
546 | int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec,
547 | getPaddingTop() + getPaddingBottom(), lp.height);
548 | childView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
549 | }
550 |
551 | /**
552 | * 初始化SlideMenu的视图
553 | */
554 | private void initSlideView(int widthResult, int heightResult) {
555 | if (getChildCount() == 0) {
556 | throw new IllegalStateException("SlideMenuLayout must host one direct child");
557 | }
558 | mSlideWidth = widthResult - mSlidePadding;
559 | mContentWidth = widthResult;
560 | mContentHeight = heightResult;
561 | switch (getChildCount()) {
562 | case 1:
563 | mSlideMode = SLIDE_MODE_NONE;
564 | mContentView = getChildAt(0);
565 | break;
566 | case 2:
567 | if (mSlideMode == SLIDE_MODE_LEFT) {
568 | mLeftView = getChildAt(0);
569 | mContentView = getChildAt(1);
570 | } else if (mSlideMode == SLIDE_MODE_RIGHT) {
571 | mRightView = getChildAt(0);
572 | mContentView = getChildAt(1);
573 | } else {
574 | throw new IllegalStateException("SlideMenuLayout must host only three direct child when slideMode" +
575 | " " +
576 | "is both");
577 | }
578 | break;
579 | case 3:
580 | mLeftView = getChildAt(0);
581 | mRightView = getChildAt(1);
582 | mContentView = getChildAt(2);
583 | break;
584 | }
585 | if (mLeftView != null) {
586 | mLeftView.getLayoutParams().width = mSlideWidth;
587 | }
588 | if (mRightView != null) {
589 | mRightView.getLayoutParams().width = mSlideWidth;
590 | }
591 |
592 | LayoutParams contentParams = mContentView.getLayoutParams();
593 | contentParams.width = widthResult;
594 | contentParams.height = heightResult;
595 | }
596 |
597 | @Override
598 | public void setSlideMode(@SlideMode int slideMode) {
599 | switch (slideMode) {
600 | case SLIDE_MODE_LEFT:
601 | closeRightSlide();
602 | break;
603 | case SLIDE_MODE_RIGHT:
604 | closeLeftSlide();
605 | break;
606 | case SLIDE_MODE_NONE:
607 | closeLeftSlide();
608 | closeRightSlide();
609 | break;
610 | }
611 | mSlideMode = slideMode;
612 | }
613 |
614 | @Override
615 | public void setSlidePadding(int slidePadding) {
616 | mSlidePadding = slidePadding;
617 | }
618 |
619 | @Override
620 | public void setSlideTime(int slideTime) {
621 | mSlideTime = slideTime;
622 | }
623 |
624 | @Override
625 | public void setParallaxSwitch(boolean parallax) {
626 | mParallax = parallax;
627 | }
628 |
629 | @Override
630 | public void setContentAlpha(@FloatRange(from = 0f, to = 1.0f) float contentAlpha) {
631 | mContentAlpha = contentAlpha;
632 | }
633 |
634 | @Override
635 | public void setContentShadowColor(@ColorRes int color) {
636 | mContentShadowColor = color;
637 | if (mContentShadowPaint == null) initContentShadowPaint();
638 | mContentShadowPaint.setColor(ContextCompat.getColor(getContext(), mContentShadowColor));
639 | postInvalidate();
640 | }
641 |
642 | @Override
643 | public void setContentToggle(boolean contentToggle) {
644 | mContentToggle = contentToggle;
645 | }
646 |
647 | @Override
648 | public void setAllowTogging(boolean allowTogging) {
649 | this.mAllowDragging = allowTogging;
650 | }
651 |
652 | @Override
653 | public View getSlideLeftView() {
654 | return mLeftView;
655 | }
656 |
657 | @Override
658 | public View getSlideRightView() {
659 | return mRightView;
660 | }
661 |
662 | @Override
663 | public View getSlideContentView() {
664 | return mContentView;
665 | }
666 |
667 | @Override
668 | public void toggleLeftSlide() {
669 | if (mTriggerSlideLeft) {
670 | closeLeftSlide();
671 | } else {
672 | openLeftSlide();
673 | }
674 | }
675 |
676 | @Override
677 | public void openLeftSlide() {
678 | if (mSlideMode == SLIDE_MODE_RIGHT || mSlideMode == SLIDE_MODE_NONE) return;
679 | mTriggerSlideLeft = true;
680 | smoothScrollTo(-mSlideWidth, 0);
681 | }
682 |
683 | @Override
684 | public void closeLeftSlide() {
685 | if (mSlideMode == SLIDE_MODE_RIGHT || mSlideMode == SLIDE_MODE_NONE) return;
686 | mTriggerSlideLeft = false;
687 | smoothScrollTo(0, 0);
688 | }
689 |
690 | @Override
691 | public boolean isLeftSlideOpen() {
692 | return mTriggerSlideLeft;
693 | }
694 |
695 | @Override
696 | public void toggleRightSlide() {
697 | if (mTriggerSlideRight) {
698 | closeRightSlide();
699 | } else {
700 | openRightSlide();
701 | }
702 | }
703 |
704 | @Override
705 | public void openRightSlide() {
706 | if (mSlideMode == SLIDE_MODE_LEFT || mSlideMode == SLIDE_MODE_NONE) return;
707 | mTriggerSlideRight = true;
708 | smoothScrollTo(mSlideWidth, 0);
709 | }
710 |
711 | @Override
712 | public void closeRightSlide() {
713 | if (mSlideMode == SLIDE_MODE_LEFT || mSlideMode == SLIDE_MODE_NONE) return;
714 | mTriggerSlideRight = false;
715 | smoothScrollTo(0, 0);
716 | }
717 |
718 | @Override
719 | public boolean isRightSlideOpen() {
720 | return mTriggerSlideRight;
721 | }
722 |
723 | @Override
724 | public void addOnSlideChangedListener(OnSlideChangedListener listener) {
725 | mSlideChangedListener = listener;
726 | }
727 | }
728 |
--------------------------------------------------------------------------------
/slidemenu/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/slidemenu/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | SlideMenu
3 |
4 |
--------------------------------------------------------------------------------