Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authora.marchuk <a.marchuk@corp.mail.ru>2015-07-15 19:30:03 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-23 02:56:01 +0300
commit1769eec1df2e105c23d70b01eed3d8738edfe381 (patch)
tree3dd1e6ba29d5c5eeb98043a9dcc7c6e442749b88 /android/3rd_party
parent6c5b3f86d5ae94fad67f6419f466f06e6e2f4876 (diff)
[android] refactor: BottomSheet integrated as sub-module instead of library.
Diffstat (limited to 'android/3rd_party')
-rw-r--r--android/3rd_party/BottomSheet/AndroidManifest.xml4
-rw-r--r--android/3rd_party/BottomSheet/build.gradle23
-rw-r--r--android/3rd_party/BottomSheet/gradle.properties1
-rw-r--r--android/3rd_party/BottomSheet/gradlew164
-rw-r--r--android/3rd_party/BottomSheet/gradlew.bat90
-rw-r--r--android/3rd_party/BottomSheet/src/main/AndroidManifest.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenu.java324
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenuItem.java296
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java860
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ClosableSlidingLayout.java228
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/FillerView.java34
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/HeaderLayout.java40
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/PinnedSectionGridView.java120
-rw-r--r--android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/SimpleSectionedGridAdapter.java348
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_item_in.xml8
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_layout_anim_in.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim/bs_list_item_in.xml8
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim/bs_list_layout_anim_in.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_enter.xml24
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_exit.xml24
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear.pngbin0 -> 246 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear_light.pngbin0 -> 244 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more.pngbin0 -> 352 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more_light.pngbin0 -> 163 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear.pngbin0 -> 182 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear_light.pngbin0 -> 192 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more.pngbin0 -> 276 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more_light.pngbin0 -> 130 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_dark_selector.xml7
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_selector.xml8
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear.pngbin0 -> 280 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear_light.pngbin0 -> 289 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more.pngbin0 -> 431 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more_light.pngbin0 -> 182 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear.pngbin0 -> 426 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear_light.pngbin0 -> 439 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more.pngbin0 -> 595 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more_light.pngbin0 -> 272 bytes
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_dark_selector.xml16
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_selector.xml16
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/layout/bottom_sheet_dialog.xml50
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/layout/bs_grid_entry.xml20
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/layout/bs_list_divider.xml9
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/layout/bs_list_entry.xml20
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values-land/integer.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values-sw600dp-land/integer.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values-sw600dp/integer.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values-zh/string.xml4
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/attrs.xml19
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/colors.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/dimens.xml7
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/ids.xml4
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/integer.xml6
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/string.xml4
-rw-r--r--android/3rd_party/BottomSheet/src/main/res/values/styles.xml165
55 files changed, 2993 insertions, 0 deletions
diff --git a/android/3rd_party/BottomSheet/AndroidManifest.xml b/android/3rd_party/BottomSheet/AndroidManifest.xml
new file mode 100644
index 0000000000..96bc9ad32a
--- /dev/null
+++ b/android/3rd_party/BottomSheet/AndroidManifest.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8" standalone="no"?>
+<manifest>
+ <application/>
+</manifest>
diff --git a/android/3rd_party/BottomSheet/build.gradle b/android/3rd_party/BottomSheet/build.gradle
new file mode 100644
index 0000000000..375b7ce36c
--- /dev/null
+++ b/android/3rd_party/BottomSheet/build.gradle
@@ -0,0 +1,23 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.2.3'
+ }
+}
+
+
+apply plugin: 'com.android.library'
+
+
+dependencies {
+ compile 'com.android.support:support-v4:22.2.0'
+}
+
+
+android {
+ compileSdkVersion propTargetSdkVersion.toInteger()
+ buildToolsVersion propBuildToolsVersion
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/gradle.properties b/android/3rd_party/BottomSheet/gradle.properties
new file mode 100644
index 0000000000..c29e2d0984
--- /dev/null
+++ b/android/3rd_party/BottomSheet/gradle.properties
@@ -0,0 +1 @@
+manifestmerger.enabled=false
diff --git a/android/3rd_party/BottomSheet/gradlew b/android/3rd_party/BottomSheet/gradlew
new file mode 100644
index 0000000000..91a7e269e1
--- /dev/null
+++ b/android/3rd_party/BottomSheet/gradlew
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn ( ) {
+ echo "$*"
+}
+
+die ( ) {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+esac
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched.
+if $cygwin ; then
+ [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
+fi
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >&-
+APP_HOME="`pwd -P`"
+cd "$SAVED" >&-
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
+function splitJvmOpts() {
+ JVM_OPTS=("$@")
+}
+eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
+JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+
+exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
diff --git a/android/3rd_party/BottomSheet/gradlew.bat b/android/3rd_party/BottomSheet/gradlew.bat
new file mode 100644
index 0000000000..8a0b282aa6
--- /dev/null
+++ b/android/3rd_party/BottomSheet/gradlew.bat
@@ -0,0 +1,90 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windowz variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+if "%@eval[2+2]" == "4" goto 4NT_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+goto execute
+
+:4NT_args
+@rem Get arguments from the 4NT Shell from JP Software
+set CMD_LINE_ARGS=%$
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/android/3rd_party/BottomSheet/src/main/AndroidManifest.xml b/android/3rd_party/BottomSheet/src/main/AndroidManifest.xml
new file mode 100644
index 0000000000..942c6c4b05
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/AndroidManifest.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.cocosw.bottomsheet">
+ <application/>
+</manifest>
+
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenu.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenu.java
new file mode 100644
index 0000000000..2d1672465c
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenu.java
@@ -0,0 +1,324 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cocosw.bottomsheet;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.support.v4.internal.view.SupportMenu;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+
+/**
+ * @hide
+ */
+ class ActionMenu implements SupportMenu {
+ private Context mContext;
+
+ private boolean mIsQwerty;
+
+ private static final int[] sCategoryToOrder = new int[]{
+ 1, /* No category */
+ 4, /* CONTAINER */
+ 5, /* SYSTEM */
+ 3, /* SECONDARY */
+ 2, /* ALTERNATIVE */
+ 0, /* SELECTED_ALTERNATIVE */
+ };
+
+ private ArrayList<ActionMenuItem> mItems;
+
+ public ActionMenu(Context context) {
+ mContext = context;
+ mItems = new ArrayList<>();
+ }
+
+ public Context getContext() {
+ return mContext;
+ }
+
+ public MenuItem add(CharSequence title) {
+ return add(0, 0, 0, title);
+ }
+
+ public MenuItem add(int titleRes) {
+ return add(0, 0, 0, titleRes);
+ }
+
+ public MenuItem add(int groupId, int itemId, int order, int titleRes) {
+ return add(groupId, itemId, order, mContext.getResources().getString(titleRes));
+ }
+
+ public MenuItem add(int groupId, int itemId, int order, CharSequence title) {
+ ActionMenuItem item = new ActionMenuItem(getContext(),
+ groupId, itemId, 0, order, title);
+ mItems.add(findInsertIndex(mItems, getOrdering(order)), item);
+ return item;
+ }
+
+
+ private static int findInsertIndex(ArrayList<ActionMenuItem> items, int ordering) {
+ for (int i = items.size() - 1; i >= 0; i--) {
+ ActionMenuItem item = items.get(i);
+ if (item.getOrder() <= ordering) {
+ return i + 1;
+ }
+ }
+ return 0;
+ }
+
+ MenuItem add(ActionMenuItem item) {
+ mItems.add(findInsertIndex(mItems, getOrdering(item.getOrder())),item);
+ return item;
+ }
+
+ /**
+ * Returns the ordering across all items. This will grab the category from
+ * the upper bits, find out how to order the category with respect to other
+ * categories, and combine it with the lower bits.
+ *
+ * @param categoryOrder The category order for a particular item (if it has
+ * not been or/add with a category, the default category is
+ * assumed).
+ * @return An ordering integer that can be used to order this item across
+ * all the items (even from other categories).
+ */
+ private static int getOrdering(int categoryOrder) {
+ final int index = (categoryOrder & CATEGORY_MASK) >> CATEGORY_SHIFT;
+
+ if (index < 0 || index >= sCategoryToOrder.length) {
+ throw new IllegalArgumentException("order does not contain a valid category.");
+ }
+
+ return (sCategoryToOrder[index] << CATEGORY_SHIFT) | (categoryOrder & USER_MASK);
+ }
+
+ public int addIntentOptions(int groupId, int itemId, int order,
+ ComponentName caller, Intent[] specifics, Intent intent, int flags,
+ MenuItem[] outSpecificItems) {
+ PackageManager pm = mContext.getPackageManager();
+ final List<ResolveInfo> lri =
+ pm.queryIntentActivityOptions(caller, specifics, intent, 0);
+ final int N = lri != null ? lri.size() : 0;
+
+ if ((flags & FLAG_APPEND_TO_GROUP) == 0) {
+ removeGroup(groupId);
+ }
+
+ for (int i=0; i<N; i++) {
+ final ResolveInfo ri = lri.get(i);
+ Intent rintent = new Intent(
+ ri.specificIndex < 0 ? intent : specifics[ri.specificIndex]);
+ rintent.setComponent(new ComponentName(
+ ri.activityInfo.applicationInfo.packageName,
+ ri.activityInfo.name));
+ final MenuItem item = add(groupId, itemId, order, ri.loadLabel(pm))
+ .setIcon(ri.loadIcon(pm))
+ .setIntent(rintent);
+ if (outSpecificItems != null && ri.specificIndex >= 0) {
+ outSpecificItems[ri.specificIndex] = item;
+ }
+ }
+
+ return N;
+ }
+
+ public SubMenu addSubMenu(CharSequence title) {
+ // TODO Implement submenus
+ return null;
+ }
+
+ public SubMenu addSubMenu(int titleRes) {
+ // TODO Implement submenus
+ return null;
+ }
+
+ public SubMenu addSubMenu(int groupId, int itemId, int order,
+ CharSequence title) {
+ // TODO Implement submenus
+ return null;
+ }
+
+ public SubMenu addSubMenu(int groupId, int itemId, int order, int titleRes) {
+ // TODO Implement submenus
+ return null;
+ }
+
+ public void clear() {
+ mItems.clear();
+ }
+
+ public void close() {
+ }
+
+ private int findItemIndex(int id) {
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+ for (int i = 0; i < itemCount; i++) {
+ if (items.get(i).getItemId() == id) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public MenuItem findItem(int id) {
+ return mItems.get(findItemIndex(id));
+ }
+
+ public MenuItem getItem(int index) {
+ return mItems.get(index);
+ }
+
+ public boolean hasVisibleItems() {
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+
+ for (int i = 0; i < itemCount; i++) {
+ if (items.get(i).isVisible()) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private ActionMenuItem findItemWithShortcut(int keyCode, KeyEvent event) {
+ // TODO Make this smarter.
+ final boolean qwerty = mIsQwerty;
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+
+ for (int i = 0; i < itemCount; i++) {
+ ActionMenuItem item = items.get(i);
+ final char shortcut = qwerty ? item.getAlphabeticShortcut() :
+ item.getNumericShortcut();
+ if (keyCode == shortcut) {
+ return item;
+ }
+ }
+ return null;
+ }
+
+ public boolean isShortcutKey(int keyCode, KeyEvent event) {
+ return findItemWithShortcut(keyCode, event) != null;
+ }
+
+ public boolean performIdentifierAction(int id, int flags) {
+ final int index = findItemIndex(id);
+ if (index < 0) {
+ return false;
+ }
+
+ return mItems.get(index).invoke();
+ }
+
+ public boolean performShortcut(int keyCode, KeyEvent event, int flags) {
+ ActionMenuItem item = findItemWithShortcut(keyCode, event);
+ if (item == null) {
+ return false;
+ }
+
+ return item.invoke();
+ }
+
+ public void removeGroup(int groupId) {
+ final ArrayList<ActionMenuItem> items = mItems;
+ int itemCount = items.size();
+ int i = 0;
+ while (i < itemCount) {
+ if (items.get(i).getGroupId() == groupId) {
+ items.remove(i);
+ itemCount--;
+ } else {
+ i++;
+ }
+ }
+ }
+
+ public void removeItem(int id) {
+ mItems.remove(findItemIndex(id));
+ }
+
+ public void setGroupCheckable(int group, boolean checkable,
+ boolean exclusive) {
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+
+ for (int i = 0; i < itemCount; i++) {
+ ActionMenuItem item = items.get(i);
+ if (item.getGroupId() == group) {
+ item.setCheckable(checkable);
+ item.setExclusiveCheckable(exclusive);
+ }
+ }
+ }
+
+ public void setGroupEnabled(int group, boolean enabled) {
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+
+ for (int i = 0; i < itemCount; i++) {
+ ActionMenuItem item = items.get(i);
+ if (item.getGroupId() == group) {
+ item.setEnabled(enabled);
+ }
+ }
+ }
+
+ public void setGroupVisible(int group, boolean visible) {
+ final ArrayList<ActionMenuItem> items = mItems;
+ final int itemCount = items.size();
+
+ for (int i = 0; i < itemCount; i++) {
+ ActionMenuItem item = items.get(i);
+ if (item.getGroupId() == group) {
+ item.setVisible(visible);
+ }
+ }
+ }
+
+ public void setQwertyMode(boolean isQwerty) {
+ mIsQwerty = isQwerty;
+ }
+
+ public int size() {
+ return mItems.size();
+ }
+
+ ActionMenu clone(int size) {
+ ActionMenu out = new ActionMenu(getContext());
+ out.mItems = new ArrayList<>(this.mItems.subList(0,size));
+ return out;
+ }
+
+ void removeInvisible() {
+ Iterator<ActionMenuItem> iter = mItems.iterator();
+ while (iter.hasNext()) {
+ ActionMenuItem item = iter.next();
+ if (!item.isVisible()) iter.remove();
+ }
+ }
+}
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenuItem.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenuItem.java
new file mode 100644
index 0000000000..26719ade26
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ActionMenuItem.java
@@ -0,0 +1,296 @@
+package com.cocosw.bottomsheet;
+
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.drawable.Drawable;
+import android.support.v4.content.ContextCompat;
+import android.support.v4.internal.view.SupportMenuItem;
+import android.support.v4.view.MenuItemCompat;
+import android.view.ActionProvider;
+import android.view.ContextMenu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.View;
+
+
+ class ActionMenuItem implements SupportMenuItem {
+
+
+ private final int mId;
+ private final int mGroup;
+ private final int mCategoryOrder;
+ private final int mOrdering;
+
+ private CharSequence mTitle;
+ private CharSequence mTitleCondensed;
+ private Intent mIntent;
+ private char mShortcutNumericChar;
+ private char mShortcutAlphabeticChar;
+
+ private Drawable mIconDrawable;
+ private int mIconResId = NO_ICON;
+
+ private Context mContext;
+
+ private SupportMenuItem.OnMenuItemClickListener mClickListener;
+
+ private static final int NO_ICON = 0;
+
+ private int mFlags = ENABLED;
+ private static final int CHECKABLE = 0x00000001;
+ private static final int CHECKED = 0x00000002;
+ private static final int EXCLUSIVE = 0x00000004;
+ private static final int HIDDEN = 0x00000008;
+ private static final int ENABLED = 0x00000010;
+
+ public ActionMenuItem(Context context, int group, int id, int categoryOrder, int ordering,
+ CharSequence title) {
+ mContext = context;
+ mId = id;
+ mGroup = group;
+ mCategoryOrder = categoryOrder;
+ mOrdering = ordering;
+ mTitle = title;
+ }
+
+ public char getAlphabeticShortcut() {
+ return mShortcutAlphabeticChar;
+ }
+
+ public int getGroupId() {
+ return mGroup;
+ }
+
+ public Drawable getIcon() {
+ return mIconDrawable;
+ }
+
+ public Intent getIntent() {
+ return mIntent;
+ }
+
+ public int getItemId() {
+ return mId;
+ }
+
+ public ContextMenu.ContextMenuInfo getMenuInfo() {
+ return null;
+ }
+
+ public char getNumericShortcut() {
+ return mShortcutNumericChar;
+ }
+
+ public int getOrder() {
+ return mOrdering;
+ }
+
+ public SubMenu getSubMenu() {
+ return null;
+ }
+
+ public CharSequence getTitle() {
+ return mTitle;
+ }
+
+ public CharSequence getTitleCondensed() {
+ return mTitleCondensed != null ? mTitleCondensed : mTitle;
+ }
+
+ public boolean hasSubMenu() {
+ return false;
+ }
+
+ public boolean isCheckable() {
+ return (mFlags & CHECKABLE) != 0;
+ }
+
+ public boolean isChecked() {
+ return (mFlags & CHECKED) != 0;
+ }
+
+ public boolean isEnabled() {
+ return (mFlags & ENABLED) != 0;
+ }
+
+ public boolean isVisible() {
+ return (mFlags & HIDDEN) == 0;
+ }
+
+ public MenuItem setAlphabeticShortcut(char alphaChar) {
+ mShortcutAlphabeticChar = alphaChar;
+ return this;
+ }
+
+ public MenuItem setCheckable(boolean checkable) {
+ mFlags = (mFlags & ~CHECKABLE) | (checkable ? CHECKABLE : 0);
+ return this;
+ }
+
+ public ActionMenuItem setExclusiveCheckable(boolean exclusive) {
+ mFlags = (mFlags & ~EXCLUSIVE) | (exclusive ? EXCLUSIVE : 0);
+ return this;
+ }
+
+ public MenuItem setChecked(boolean checked) {
+ mFlags = (mFlags & ~CHECKED) | (checked ? CHECKED : 0);
+ return this;
+ }
+
+ public MenuItem setEnabled(boolean enabled) {
+ mFlags = (mFlags & ~ENABLED) | (enabled ? ENABLED : 0);
+ return this;
+ }
+
+ public MenuItem setIcon(Drawable icon) {
+ mIconDrawable = icon;
+ mIconResId = NO_ICON;
+ return this;
+ }
+
+ public MenuItem setIcon(int iconRes) {
+ mIconResId = iconRes;
+ if (iconRes>0)
+ mIconDrawable = ContextCompat.getDrawable(mContext, iconRes);
+ return this;
+ }
+
+ public MenuItem setIntent(Intent intent) {
+ mIntent = intent;
+ return this;
+ }
+
+ public MenuItem setNumericShortcut(char numericChar) {
+ mShortcutNumericChar = numericChar;
+ return this;
+ }
+
+ public MenuItem setOnMenuItemClickListener(OnMenuItemClickListener menuItemClickListener) {
+ mClickListener = menuItemClickListener;
+ return this;
+ }
+
+ public MenuItem setShortcut(char numericChar, char alphaChar) {
+ mShortcutNumericChar = numericChar;
+ mShortcutAlphabeticChar = alphaChar;
+ return this;
+ }
+
+ public MenuItem setTitle(CharSequence title) {
+ mTitle = title;
+ return this;
+ }
+
+ public MenuItem setTitle(int title) {
+ mTitle = mContext.getResources().getString(title);
+ return this;
+ }
+
+ public MenuItem setTitleCondensed(CharSequence title) {
+ mTitleCondensed = title;
+ return this;
+ }
+
+ public MenuItem setVisible(boolean visible) {
+ mFlags = (mFlags & HIDDEN) | (visible ? 0 : HIDDEN);
+ return this;
+ }
+
+ public boolean invoke() {
+ if (mClickListener != null && mClickListener.onMenuItemClick(this)) {
+ return true;
+ }
+
+ if (mIntent != null) {
+ mContext.startActivity(mIntent);
+ return true;
+ }
+
+ return false;
+ }
+
+ public void setShowAsAction(int show) {
+ // Do nothing. ActionMenuItems always show as action buttons.
+ }
+
+ public SupportMenuItem setActionView(View actionView) {
+ throw new UnsupportedOperationException();
+ }
+
+ public View getActionView() {
+ return null;
+ }
+
+ @Override
+ public MenuItem setActionProvider(android.view.ActionProvider actionProvider) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public android.view.ActionProvider getActionProvider() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SupportMenuItem setActionView(int resId) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public android.support.v4.view.ActionProvider getSupportActionProvider() {
+ return null;
+ }
+
+ @Override
+ public SupportMenuItem setSupportActionProvider(android.support.v4.view.ActionProvider actionProvider) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SupportMenuItem setShowAsActionFlags(int actionEnum) {
+ setShowAsAction(actionEnum);
+ return this;
+ }
+
+ @Override
+ public boolean expandActionView() {
+ return false;
+ }
+
+ @Override
+ public boolean collapseActionView() {
+ return false;
+ }
+
+ @Override
+ public boolean isActionViewExpanded() {
+ return false;
+ }
+
+ @Override
+ public MenuItem setOnActionExpandListener(MenuItem.OnActionExpandListener listener) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public SupportMenuItem setSupportOnActionExpandListener(MenuItemCompat.OnActionExpandListener listener) {
+ // No need to save the listener; ActionMenuItem does not support collapsing items.
+ return this;
+ }
+ }
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java
new file mode 100644
index 0000000000..0fd5cbe07f
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/BottomSheet.java
@@ -0,0 +1,860 @@
+/*
+ * Copyright 2011, 2015 Kai Liao
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.cocosw.bottomsheet;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.app.Activity;
+import android.app.Dialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.IntegerRes;
+import android.support.annotation.MenuRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.StringRes;
+import android.support.annotation.StyleRes;
+import android.transition.ChangeBounds;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.util.DisplayMetrics;
+import android.util.SparseIntArray;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.view.WindowManager;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+
+
+/**
+ * One way to present a set of actions to a user is with bottom sheets, a sheet of paper that slides up from the bottom edge of the screen. Bottom sheets offer flexibility in the display of clear and simple actions that do not need explanation.
+ * <p/>
+ * https://www.google.com/design/spec/components/bottom-sheets.html
+ * <p/>
+ * Project: BottomSheet
+ * Created by Kai Liao on 2014/9/21.
+ */
+@SuppressWarnings("unused")
+public class BottomSheet extends Dialog implements DialogInterface {
+
+ private String moreText;
+ private Drawable close;
+ private Drawable more;
+ private boolean collapseListIcons;
+ private int mStatusBarHeight;
+ private GridView list;
+ private SimpleSectionedGridAdapter adapter;
+ private Builder builder;
+
+ private final SparseIntArray hidden = new SparseIntArray();
+
+ // translucent support
+ private static final String STATUS_BAR_HEIGHT_RES_NAME = "status_bar_height";
+ private static final String NAV_BAR_HEIGHT_RES_NAME = "navigation_bar_height";
+ private static final String NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME = "navigation_bar_height_landscape";
+ private static final String SHOW_NAV_BAR_RES_NAME = "config_showNavigationBar";
+ private boolean mInPortrait;
+ private String sNavBarOverride;
+ private boolean mNavBarAvailable;
+ private float mSmallestWidthDp;
+
+
+ private ImageView icon;
+
+ private int limit = -1;
+ private boolean cancelOnTouchOutside = true;
+ private boolean cancelOnSwipeDown = true;
+ private ActionMenu fullMenuItem;
+ private ActionMenu menuItem;
+ private ActionMenu actions;
+ private OnDismissListener dismissListener;
+
+ BottomSheet(Context context) {
+ super(context, R.style.BottomSheet_Dialog);
+ }
+
+ @SuppressWarnings("WeakerAccess")
+ BottomSheet(Context context, int theme) {
+ super(context, theme);
+
+ TypedArray a = getContext()
+ .obtainStyledAttributes(null, R.styleable.BottomSheet, R.attr.bottomSheetStyle, 0);
+ try {
+ more = a.getDrawable(R.styleable.BottomSheet_bs_moreDrawable);
+ close = a.getDrawable(R.styleable.BottomSheet_bs_closeDrawable);
+ moreText = a.getString(R.styleable.BottomSheet_bs_moreText);
+ collapseListIcons = a.getBoolean(R.styleable.BottomSheet_bs_collapseListIcons, true);
+ } finally {
+ a.recycle();
+ }
+
+ // https://github.com/jgilfelt/SystemBarTint/blob/master/library/src/com/readystatesoftware/systembartint/SystemBarTintManager.java
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+ mInPortrait = (context.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT);
+ try {
+ Class c = Class.forName("android.os.SystemProperties");
+ @SuppressWarnings("unchecked") Method m = c.getDeclaredMethod("get", String.class);
+ m.setAccessible(true);
+ sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");
+ } catch (Throwable e) {
+ sNavBarOverride = null;
+ }
+
+ // check theme attrs
+ int[] as = {android.R.attr.windowTranslucentNavigation};
+ a = context.obtainStyledAttributes(as);
+ try {
+ mNavBarAvailable = a.getBoolean(0, false);
+ } finally {
+ a.recycle();
+ }
+
+ // check window flags
+ WindowManager.LayoutParams winParams = ((Activity) context).getWindow().getAttributes();
+
+ int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+ if ((winParams.flags & bits) != 0) {
+ mNavBarAvailable = true;
+ }
+
+ mSmallestWidthDp = getSmallestWidthDp(wm);
+ if (mNavBarAvailable)
+ setTranslucentStatus(true);
+ mStatusBarHeight = getInternalDimensionSize(context.getResources(), STATUS_BAR_HEIGHT_RES_NAME);
+ }
+ }
+
+ @SuppressLint("NewApi")
+ private float getSmallestWidthDp(WindowManager wm) {
+ DisplayMetrics metrics = new DisplayMetrics();
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
+ wm.getDefaultDisplay().getRealMetrics(metrics);
+ } else {
+ //this is not correct, but we don't really care pre-kitkat
+ wm.getDefaultDisplay().getMetrics(metrics);
+ }
+ float widthDp = metrics.widthPixels / metrics.density;
+ float heightDp = metrics.heightPixels / metrics.density;
+ return Math.min(widthDp, heightDp);
+ }
+
+ @TargetApi(14)
+ private int getNavigationBarHeight(Context context) {
+ Resources res = context.getResources();
+ int result = 0;
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
+ if (hasNavBar(context)) {
+ String key;
+ if (mInPortrait) {
+ key = NAV_BAR_HEIGHT_RES_NAME;
+ } else {
+ if (!isNavigationAtBottom())
+ return 0;
+ key = NAV_BAR_HEIGHT_LANDSCAPE_RES_NAME;
+ }
+ return getInternalDimensionSize(res, key);
+ }
+ }
+ return result;
+ }
+
+ @TargetApi(14)
+ private boolean hasNavBar(Context context) {
+ Resources res = context.getResources();
+ int resourceId = res.getIdentifier(SHOW_NAV_BAR_RES_NAME, "bool", "android");
+ if (resourceId != 0) {
+ boolean hasNav = res.getBoolean(resourceId);
+ // check override flag (see static block)
+ if ("1".equals(sNavBarOverride)) {
+ hasNav = false;
+ } else if ("0".equals(sNavBarOverride)) {
+ hasNav = true;
+ }
+ return hasNav;
+ } else { // fallback
+ return !ViewConfiguration.get(context).hasPermanentMenuKey();
+ }
+ }
+
+ private int getInternalDimensionSize(Resources res, String key) {
+ int result = 0;
+ int resourceId = res.getIdentifier(key, "dimen", "android");
+ if (resourceId > 0) {
+ result = res.getDimensionPixelSize(resourceId);
+ }
+ return result;
+ }
+
+ /**
+ * Should a navigation bar appear at the bottom of the screen in the current
+ * device configuration? A navigation bar may appear on the right side of
+ * the screen in certain configurations.
+ *
+ * @return True if navigation should appear at the bottom of the screen, False otherwise.
+ */
+ private boolean isNavigationAtBottom() {
+ return (mSmallestWidthDp >= 600 || mInPortrait);
+ }
+
+ /**
+ * Hacky way to get gridview's column number
+ */
+ private int getNumColumns() {
+ try {
+ Field numColumns = GridView.class.getDeclaredField("mRequestedNumColumns");
+ numColumns.setAccessible(true);
+ return numColumns.getInt(list);
+ } catch (Exception e) {
+ return 1;
+ }
+ }
+
+ @Override
+ public void setCanceledOnTouchOutside(boolean cancel) {
+ super.setCanceledOnTouchOutside(cancel);
+ cancelOnTouchOutside = cancel;
+ }
+
+ /**
+ * Sets whether this dialog is canceled when swipe it down
+ *
+ * @param cancel whether this dialog is canceled when swipe it down
+ */
+ public void setCanceledOnSwipeDown(boolean cancel) {
+ cancelOnSwipeDown = cancel;
+ }
+
+ private void init(final Context context) {
+ setCanceledOnTouchOutside(cancelOnTouchOutside);
+ final ClosableSlidingLayout mDialogView = (ClosableSlidingLayout) View.inflate(context, R.layout.bottom_sheet_dialog, null);
+ setContentView(mDialogView);
+ if (!cancelOnSwipeDown)
+ mDialogView.swipeable = cancelOnSwipeDown;
+ mDialogView.setSlideListener(new ClosableSlidingLayout.SlideListener() {
+ @Override
+ public void onClosed() {
+ BottomSheet.this.dismiss();
+ }
+
+ @Override
+ public void onOpened() {
+ showFullItems();
+ }
+ });
+
+
+ this.setOnShowListener(new OnShowListener() {
+ @Override
+ public void onShow(DialogInterface dialogInterface) {
+ list.setAdapter(adapter);
+ list.startLayoutAnimation();
+ if (builder.icon == null)
+ icon.setVisibility(View.GONE);
+ else {
+ icon.setVisibility(View.VISIBLE);
+ icon.setImageDrawable(builder.icon);
+ }
+ }
+ });
+ int[] location = new int[2];
+ mDialogView.getLocationOnScreen(location);
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ mDialogView.setPadding(0, location[0] == 0 ? mStatusBarHeight : 0, 0, 0);
+ mDialogView.getChildAt(0).setPadding(0, 0, 0, mNavBarAvailable ? getNavigationBarHeight(getContext()) + mDialogView.getPaddingBottom() : 0);
+ }
+
+ final TextView title = (TextView) mDialogView.findViewById(R.id.bottom_sheet_title);
+ if (builder.title != null) {
+ title.setVisibility(View.VISIBLE);
+ title.setText(builder.title);
+ }
+
+ icon = (ImageView) mDialogView.findViewById(R.id.bottom_sheet_title_image);
+
+
+ list = (GridView) mDialogView.findViewById(R.id.bottom_sheet_gridview);
+ mDialogView.mTarget = list;
+ if (!builder.grid) {
+ list.setNumColumns(1);
+ }
+
+ if (builder.grid) {
+ for (int i = 0; i < getMenu().size(); i++) {
+ if (getMenu().getItem(i).getIcon() == null)
+ throw new IllegalArgumentException("You must set icon for each items in grid style");
+ }
+ }
+
+ if (builder.limit > 0)
+ limit = builder.limit * getNumColumns();
+ else
+ limit = Integer.MAX_VALUE;
+
+ mDialogView.setCollapsible(false);
+
+ actions = builder.menu;
+ menuItem = actions;
+ // over the initial numbers
+ if (getMenu().size() > limit) {
+ fullMenuItem = builder.menu;
+ menuItem = builder.menu.clone(limit - 1);
+ ActionMenuItem item = new ActionMenuItem(context, 0, R.id.bs_more, 0, limit - 1, moreText);
+ item.setIcon(more);
+ menuItem.add(item);
+ actions = menuItem;
+ mDialogView.setCollapsible(true);
+ }
+
+ BaseAdapter baseAdapter = new BaseAdapter() {
+
+
+ @Override
+ public int getCount() {
+ return actions.size() - hidden.size();
+ }
+
+ @Override
+ public MenuItem getItem(int position) {
+ return actions.getItem(position);
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return position;
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return 1;
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ return getItem(position).isEnabled();
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return false;
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ViewHolder holder;
+ if (convertView == null) {
+ LayoutInflater inflater = (LayoutInflater) getContext()
+ .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ if (builder.grid)
+ convertView = inflater.inflate(R.layout.bs_grid_entry, parent, false);
+ else
+ convertView = inflater.inflate(R.layout.bs_list_entry, parent, false);
+ holder = new ViewHolder();
+ holder.title = (TextView) convertView.findViewById(R.id.bs_list_title);
+ holder.image = (ImageView) convertView.findViewById(R.id.bs_list_image);
+ convertView.setTag(holder);
+ } else {
+ holder = (ViewHolder) convertView.getTag();
+ }
+
+ for (int i = 0; i < hidden.size(); i++) {
+ if (hidden.valueAt(i) <= position)
+ position++;
+ }
+
+ MenuItem item = getItem(position);
+
+ holder.title.setText(item.getTitle());
+ if (item.getIcon() == null)
+ holder.image.setVisibility(collapseListIcons ? View.GONE : View.INVISIBLE);
+ else {
+ holder.image.setVisibility(View.VISIBLE);
+ holder.image.setImageDrawable(item.getIcon());
+ }
+
+ holder.image.setEnabled(item.isEnabled());
+ holder.title.setEnabled(item.isEnabled());
+
+ return convertView;
+ }
+
+ class ViewHolder {
+ private TextView title;
+ private ImageView image;
+ }
+ };
+
+ adapter = new SimpleSectionedGridAdapter(context, baseAdapter, R.layout.bs_list_divider, R.id.headerlayout, R.id.header);
+ list.setAdapter(adapter);
+ adapter.setGridView(list);
+
+ updateSection();
+
+ list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+ @Override
+ public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+ if (((MenuItem) adapter.getItem(position)).getItemId() == R.id.bs_more) {
+ showFullItems();
+ mDialogView.setCollapsible(false);
+ return;
+ }
+
+ if (!((ActionMenuItem) adapter.getItem(position)).invoke()) {
+ if (builder.menulistener != null)
+ builder.menulistener.onMenuItemClick((MenuItem) adapter.getItem(position));
+ else if (builder.listener != null)
+ builder.listener.onClick(BottomSheet.this, ((MenuItem) adapter.getItem(position)).getItemId());
+ }
+ dismiss();
+ }
+ });
+
+ if (builder.dismissListener != null) {
+ setOnDismissListener(builder.dismissListener);
+ }
+ setListLayout();
+ }
+
+
+ private void updateSection() {
+ actions.removeInvisible();
+
+ if (!builder.grid && actions.size() > 0) {
+ int groupId = actions.getItem(0).getGroupId();
+ ArrayList<SimpleSectionedGridAdapter.Section> sections = new ArrayList<>();
+ for (int i = 0; i < actions.size(); i++) {
+ if (actions.getItem(i).getGroupId() != groupId) {
+ groupId = actions.getItem(i).getGroupId();
+ sections.add(new SimpleSectionedGridAdapter.Section(i, null));
+ }
+ }
+ if (sections.size() > 0) {
+ SimpleSectionedGridAdapter.Section[] s = new SimpleSectionedGridAdapter.Section[sections.size()];
+ sections.toArray(s);
+ adapter.setSections(s);
+ } else {
+ adapter.mSections.clear();
+ }
+ }
+ }
+
+ private void showFullItems() {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
+ Transition changeBounds = new ChangeBounds();
+ changeBounds.setDuration(300);
+ TransitionManager.beginDelayedTransition(list, changeBounds);
+ }
+ actions = fullMenuItem;
+ updateSection();
+ adapter.notifyDataSetChanged();
+ list.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
+ icon.setVisibility(View.VISIBLE);
+ icon.setImageDrawable(close);
+ icon.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ showShortItems();
+ }
+ });
+ setListLayout();
+ }
+
+ private void showShortItems() {
+ actions = menuItem;
+ updateSection();
+ adapter.notifyDataSetChanged();
+ setListLayout();
+
+ if (builder.icon == null)
+ icon.setVisibility(View.GONE);
+ else {
+ icon.setVisibility(View.VISIBLE);
+ icon.setImageDrawable(builder.icon);
+ }
+ }
+
+ private boolean hasDivider() {
+ return adapter.mSections.size() > 0;
+ }
+
+ private void setListLayout() {
+ // without divider, the height of gridview is correct
+ if (!hasDivider())
+ return;
+ list.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
+ @Override
+ public void onGlobalLayout() {
+ if (Build.VERSION.SDK_INT < 16) {
+ //noinspection deprecation
+ list.getViewTreeObserver().removeGlobalOnLayoutListener(this);
+ } else {
+ list.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+ }
+ View lastChild = list.getChildAt(list.getChildCount() - 1);
+ if (lastChild != null)
+ list.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, lastChild.getBottom() + lastChild.getPaddingBottom() + list.getPaddingBottom()));
+ }
+ });
+ }
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ init(getContext());
+
+ WindowManager.LayoutParams params = getWindow().getAttributes();
+ params.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ params.gravity = Gravity.BOTTOM;
+
+ TypedArray a = getContext().obtainStyledAttributes(new int[]{android.R.attr.layout_width});
+ try {
+ params.width = a.getLayoutDimension(0, ViewGroup.LayoutParams.MATCH_PARENT);
+ } finally {
+ a.recycle();
+ }
+ super.setOnDismissListener(new OnDismissListener() {
+ @Override
+ public void onDismiss(DialogInterface dialog) {
+ if (dismissListener != null)
+ dismissListener.onDismiss(dialog);
+ if (limit != Integer.MAX_VALUE)
+ showShortItems();
+ }
+ });
+ getWindow().setAttributes(params);
+ }
+
+ @SuppressWarnings("SameParameterValue")
+ @TargetApi(19)
+ private void setTranslucentStatus(boolean on) {
+ Window win = getWindow();
+ WindowManager.LayoutParams winParams = win.getAttributes();
+ final int bits = WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
+ if (on) {
+ winParams.flags |= bits;
+ } else {
+ winParams.flags &= ~bits;
+ }
+
+ win.setAttributes(winParams);
+ // instance
+ win.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
+ WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ }
+
+ public Menu getMenu() {
+ return builder.menu;
+ }
+
+ /**
+ * If you make any changes to menu and try to apply it immediately to your bottomsheet, you should call this.
+ */
+ public void invalidate() {
+ updateSection();
+ adapter.notifyDataSetChanged();
+ setListLayout();
+ }
+
+ @Override
+ public void setOnDismissListener(OnDismissListener listener) {
+ this.dismissListener = listener;
+ }
+
+ /**
+ * Constructor using a context for this builder and the {@link com.cocosw.bottomsheet.BottomSheet} it creates.
+ */
+ public static class Builder {
+
+ private final Context context;
+ private int theme;
+ private final ActionMenu menu;
+ private CharSequence title;
+ private boolean grid;
+ private OnClickListener listener;
+ private OnDismissListener dismissListener;
+ private Drawable icon;
+ private int limit = -1;
+ private MenuItem.OnMenuItemClickListener menulistener;
+
+
+ /**
+ * Constructor using a context for this builder and the {@link com.cocosw.bottomsheet.BottomSheet} it creates.
+ *
+ * @param context A Context for built BottomSheet.
+ */
+ public Builder(@NonNull Activity context) {
+ this(context, R.style.BottomSheet_Dialog);
+ TypedArray ta = context.getTheme().obtainStyledAttributes(new int[]{R.attr.bottomSheetStyle});
+ try {
+ theme = ta.getResourceId(0, R.style.BottomSheet_Dialog);
+ } finally {
+ ta.recycle();
+ }
+ }
+
+ /**
+ * Constructor using a context for this builder and the {@link com.cocosw.bottomsheet.BottomSheet} it creates with given style
+ *
+ * @param context A Context for built BottomSheet.
+ * @param theme The theme id will be apply to BottomSheet
+ */
+ public Builder(Context context, @StyleRes int theme) {
+ this.context = context;
+ this.theme = theme;
+ this.menu = new ActionMenu(context);
+ }
+
+ /**
+ * Set menu resources as list item to display in BottomSheet
+ *
+ * @param xmlRes menu resource id
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder sheet(@MenuRes int xmlRes) {
+ new MenuInflater(context).inflate(xmlRes, menu);
+ return this;
+ }
+
+
+ /**
+ * Add one item into BottomSheet
+ *
+ * @param id ID of item
+ * @param iconRes icon resource
+ * @param textRes text resource
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder sheet(int id, @DrawableRes int iconRes, @StringRes int textRes) {
+ ActionMenuItem item = new ActionMenuItem(context, 0, id, 0, 0, context.getText(textRes));
+ item.setIcon(iconRes);
+ menu.add(item);
+ return this;
+ }
+
+ /**
+ * Add one item into BottomSheet
+ *
+ * @param id ID of item
+ * @param icon icon
+ * @param text text
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder sheet(int id, @NonNull Drawable icon, @NonNull CharSequence text) {
+ ActionMenuItem item = new ActionMenuItem(context, 0, id, 0, 0, text);
+ item.setIcon(icon);
+ menu.add(item);
+ return this;
+ }
+
+ /**
+ * Add one item without icon into BottomSheet
+ *
+ * @param id ID of item
+ * @param textRes text resource
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder sheet(int id, @StringRes int textRes) {
+ menu.add(0, id, 0, textRes);
+ return this;
+ }
+
+ /**
+ * Add one item without icon into BottomSheet
+ *
+ * @param id ID of item
+ * @param text text
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder sheet(int id, @NonNull CharSequence text) {
+ menu.add(0, id, 0, text);
+ return this;
+ }
+
+ /**
+ * Set title for BottomSheet
+ *
+ * @param titleRes title for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder title(@StringRes int titleRes) {
+ title = context.getText(titleRes);
+ return this;
+ }
+
+ /**
+ * Remove an item from BottomSheet
+ *
+ * @param id ID of item
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ @Deprecated
+ public Builder remove(int id) {
+ menu.removeItem(id);
+ return this;
+ }
+
+ /**
+ * Set title for BottomSheet
+ *
+ * @param icon icon for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder icon(Drawable icon) {
+ this.icon = icon;
+ return this;
+ }
+
+ /**
+ * Set title for BottomSheet
+ *
+ * @param iconRes icon resource id for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder icon(@DrawableRes int iconRes) {
+ this.icon = context.getResources().getDrawable(iconRes);
+ return this;
+ }
+
+ /**
+ * Set OnclickListener for BottomSheet
+ *
+ * @param listener OnclickListener for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder listener(@NonNull OnClickListener listener) {
+ this.listener = listener;
+ return this;
+ }
+
+ /**
+ * Set OnMenuItemClickListener for BottomSheet
+ *
+ * @param listener OnMenuItemClickListener for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder listener(@NonNull MenuItem.OnMenuItemClickListener listener) {
+ this.menulistener = listener;
+ return this;
+ }
+
+
+ /**
+ * Show BottomSheet in dark color theme looking
+ *
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder darkTheme() {
+ theme = R.style.BottomSheet_Dialog_Dark;
+ return this;
+ }
+
+
+ /**
+ * Show BottomSheet
+ *
+ * @return Instance of bottomsheet
+ */
+ public BottomSheet show() {
+ BottomSheet dialog = build();
+ dialog.show();
+ return dialog;
+ }
+
+ /**
+ * Show items in grid instead of list
+ *
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder grid() {
+ this.grid = true;
+ return this;
+ }
+
+ /**
+ * Set initial number of actions which will be shown in current sheet.
+ * If more actions need to be shown, a "more" action will be displayed in the last position.
+ *
+ * @param limitRes resource id for initial number of actions
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder limit(@IntegerRes int limitRes) {
+ limit = context.getResources().getInteger(limitRes);
+ return this;
+ }
+
+
+ /**
+ * Create a BottomSheet but not show it
+ *
+ * @return Instance of bottomsheet
+ */
+ @SuppressLint("Override")
+ public BottomSheet build() {
+ BottomSheet dialog = new BottomSheet(context, theme);
+ dialog.builder = this;
+ return dialog;
+ }
+
+ /**
+ * Set title for BottomSheet
+ *
+ * @param title title for BottomSheet
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder title(CharSequence title) {
+ this.title = title;
+ return this;
+ }
+
+ /**
+ * Set the OnDismissListener for BottomSheet
+ *
+ * @param listener OnDismissListener for Bottom
+ * @return This Builder object to allow for chaining of calls to set methods
+ */
+ public Builder setOnDismissListener(@NonNull OnDismissListener listener) {
+ this.dismissListener = listener;
+ return this;
+ }
+ }
+
+
+}
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ClosableSlidingLayout.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ClosableSlidingLayout.java
new file mode 100644
index 0000000000..beee1783e5
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/ClosableSlidingLayout.java
@@ -0,0 +1,228 @@
+package com.cocosw.bottomsheet;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.os.Build;
+import android.support.annotation.NonNull;
+import android.support.v4.view.MotionEventCompat;
+import android.support.v4.view.ViewCompat;
+import android.support.v4.widget.ViewDragHelper;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.widget.AbsListView;
+import android.widget.FrameLayout;
+
+/**
+ * Project: gradle
+ * Created by LiaoKai(soarcn) on 2014/11/25.
+ */
+class ClosableSlidingLayout extends FrameLayout {
+
+ private final float MINVEL;
+ private ViewDragHelper mDragHelper;
+ private SlideListener mListener;
+ private int height;
+ private int top;
+ private int mActivePointerId;
+ private boolean mIsBeingDragged;
+ private float mInitialMotionY;
+ private static final int INVALID_POINTER = -1;
+ View mTarget;
+
+ private boolean collapsible = false;
+ private float yDiff;
+
+ boolean swipeable = true;
+
+ public ClosableSlidingLayout(Context context) {
+ this(context, null);
+ }
+
+ public ClosableSlidingLayout(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ public ClosableSlidingLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mDragHelper = ViewDragHelper.create(this, 0.8f, new ViewDragCallback());
+ MINVEL = getResources().getDisplayMetrics().density * 400;
+ }
+
+ @Override
+ public boolean onInterceptTouchEvent(@NonNull MotionEvent event) {
+ final int action = MotionEventCompat.getActionMasked(event);
+
+ if (!isEnabled() || canChildScrollUp()) {
+ // Fail fast if we're not in a state where a swipe is possible
+ return false;
+ }
+
+ if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {
+ mActivePointerId = INVALID_POINTER;
+ mIsBeingDragged = false;
+ if (collapsible && -yDiff > mDragHelper.getTouchSlop()) {
+ expand(mDragHelper.getCapturedView(), 0);
+ }
+ mDragHelper.cancel();
+ return false;
+ }
+
+ switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ height = getChildAt(0).getHeight();
+ top = getChildAt(0).getTop();
+ mActivePointerId = MotionEventCompat.getPointerId(event, 0);
+ mIsBeingDragged = false;
+ final float initialMotionY = getMotionEventY(event, mActivePointerId);
+ if (initialMotionY == -1) {
+ return false;
+ }
+ mInitialMotionY = initialMotionY;
+ yDiff = 0;
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (mActivePointerId == INVALID_POINTER) {
+ return false;
+ }
+ final float y = getMotionEventY(event, mActivePointerId);
+ if (y == -1) {
+ return false;
+ }
+ yDiff = y - mInitialMotionY;
+ if (swipeable && yDiff > mDragHelper.getTouchSlop() && !mIsBeingDragged) {
+ mIsBeingDragged = true;
+ mDragHelper.captureChildView(getChildAt(0), 0);
+ }
+ break;
+ }
+ mDragHelper.shouldInterceptTouchEvent(event);
+ return mIsBeingDragged;
+ }
+
+ @Override
+ public void requestDisallowInterceptTouchEvent(boolean b) {
+ // Nope.
+ }
+
+ /**
+ * @return Whether it is possible for the child view of this layout to
+ * scroll up. Override this if the child view is a custom view.
+ */
+ private boolean canChildScrollUp() {
+ if (android.os.Build.VERSION.SDK_INT < 14) {
+ if (mTarget instanceof AbsListView) {
+ final AbsListView absListView = (AbsListView) mTarget;
+ return absListView.getChildCount() > 0
+ && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
+ .getTop() < absListView.getPaddingTop());
+ } else {
+ return mTarget.getScrollY() > 0;
+ }
+ } else {
+ return ViewCompat.canScrollVertically(mTarget, -1);
+ }
+ }
+
+ private float getMotionEventY(MotionEvent ev, int activePointerId) {
+ final int index = MotionEventCompat.findPointerIndex(ev, activePointerId);
+ if (index < 0) {
+ return -1;
+ }
+ return MotionEventCompat.getY(ev, index);
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent ev) {
+ if (!isEnabled() || canChildScrollUp()) {
+ return super.onTouchEvent(ev);
+ }
+
+ try {
+ if (swipeable)
+ mDragHelper.processTouchEvent(ev);
+ } catch (Exception ignored) {
+ }
+ return true;
+ }
+
+ @Override
+ public void computeScroll() {
+ if (mDragHelper.continueSettling(true)) {
+ ViewCompat.postInvalidateOnAnimation(this);
+ }
+ }
+
+ public void setSlideListener(SlideListener listener) {
+ mListener = listener;
+ }
+
+ void setCollapsible(boolean collapsible) {
+ this.collapsible = collapsible;
+ }
+
+ /**
+ * Callback
+ */
+ private class ViewDragCallback extends ViewDragHelper.Callback {
+
+
+ @Override
+ public boolean tryCaptureView(View child, int pointerId) {
+ return true;
+ }
+
+ @Override
+ public void onViewReleased(View releasedChild, float xvel, float yvel) {
+ if (yvel > MINVEL) {
+ dismiss(releasedChild, yvel);
+ } else {
+ if (releasedChild.getTop() >= top + height / 2) {
+ dismiss(releasedChild, yvel);
+ } else {
+ mDragHelper.smoothSlideViewTo(releasedChild, 0, top);
+ }
+ }
+ ViewCompat.postInvalidateOnAnimation(ClosableSlidingLayout.this);
+ }
+
+ @Override
+ public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
+ invalidate();
+ }
+ if (height-top <1 && mListener!=null) {
+ mListener.onClosed();
+ }
+ }
+
+ @Override
+ public int clampViewPositionVertical(View child, int top, int dy) {
+ return Math.max(top, ClosableSlidingLayout.this.top);
+ }
+ }
+
+ private void expand(View releasedChild, float yvel) {
+ if (mListener != null) {
+ mListener.onOpened();
+ }
+ }
+
+ private void dismiss(View view, float yvel) {
+ mDragHelper.smoothSlideViewTo(view, 0, top + height);
+ mDragHelper.cancel();
+ ViewCompat.postInvalidateOnAnimation(ClosableSlidingLayout.this);
+ }
+
+
+ /**
+ * set listener
+ */
+ interface SlideListener {
+ void onClosed();
+
+ void onOpened();
+ }
+
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/FillerView.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/FillerView.java
new file mode 100644
index 0000000000..0f205c7089
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/FillerView.java
@@ -0,0 +1,34 @@
+package com.cocosw.bottomsheet;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.LinearLayout;
+
+class FillerView extends LinearLayout {
+ private View mMeasureTarget;
+
+
+ public FillerView(Context context) {
+ super(context);
+ }
+
+
+ public void setMeasureTarget(View lastViewSeen) {
+ mMeasureTarget = lastViewSeen;
+ }
+
+
+ public FillerView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ if(null != mMeasureTarget)
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(
+ mMeasureTarget.getMeasuredHeight(), MeasureSpec.EXACTLY);
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/HeaderLayout.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/HeaderLayout.java
new file mode 100644
index 0000000000..f04b410d12
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/HeaderLayout.java
@@ -0,0 +1,40 @@
+package com.cocosw.bottomsheet;
+
+
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+
+class HeaderLayout extends FrameLayout {
+ private int mHeaderWidth = 1;
+
+
+ public HeaderLayout(Context context) {
+ super(context);
+ }
+
+
+ public HeaderLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+
+ public HeaderLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public void setHeaderWidth(int width) {
+ mHeaderWidth = width;
+ }
+
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ int widthMeasureSpecNew = mHeaderWidth == 1
+ ? widthMeasureSpec
+ : MeasureSpec.makeMeasureSpec(mHeaderWidth, MeasureSpec.getMode(widthMeasureSpec));
+ super.onMeasure(widthMeasureSpecNew, heightMeasureSpec);
+ }
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/PinnedSectionGridView.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/PinnedSectionGridView.java
new file mode 100644
index 0000000000..a422ec3ee3
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/PinnedSectionGridView.java
@@ -0,0 +1,120 @@
+package com.cocosw.bottomsheet;
+
+
+/*
+ * Copyright 2013 Hari Krishna Dulipudi
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+ import android.content.Context;
+ import android.database.DataSetObserver;
+ import android.graphics.Canvas;
+ import android.graphics.Color;
+ import android.graphics.PointF;
+ import android.graphics.Rect;
+ import android.graphics.drawable.GradientDrawable;
+ import android.graphics.drawable.GradientDrawable.Orientation;
+ import android.os.Parcelable;
+ import android.util.AttributeSet;
+ import android.view.MotionEvent;
+ import android.view.SoundEffectConstants;
+ import android.view.View;
+ import android.view.ViewConfiguration;
+ import android.view.accessibility.AccessibilityEvent;
+ import android.widget.AbsListView;
+ import android.widget.GridView;
+
+/**
+ * ListView capable to pin views at its top while the rest is still scrolled.
+ */
+ class PinnedSectionGridView extends GridView {
+
+
+ // -- class fields
+
+ private int mNumColumns;
+ private int mHorizontalSpacing;
+ private int mColumnWidth;
+ private int mAvailableWidth;
+
+ public PinnedSectionGridView(Context context) {
+ super(context);
+ }
+
+ public PinnedSectionGridView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public PinnedSectionGridView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+
+ @Override
+ public void setNumColumns(int numColumns) {
+ mNumColumns = numColumns;
+ super.setNumColumns(numColumns);
+ }
+
+ public int getNumColumns(){
+ return mNumColumns;
+ }
+
+ @Override
+ public void setHorizontalSpacing(int horizontalSpacing) {
+ mHorizontalSpacing = horizontalSpacing;
+ super.setHorizontalSpacing(horizontalSpacing);
+ }
+
+ public int getHorizontalSpacing(){
+ return mHorizontalSpacing;
+ }
+
+ @Override
+ public void setColumnWidth(int columnWidth) {
+ mColumnWidth = columnWidth;
+ super.setColumnWidth(columnWidth);
+ }
+
+ public int getColumnWidth(){
+ return mColumnWidth;
+ }
+
+ public int getAvailableWidth(){
+ return mAvailableWidth != 0 ? mAvailableWidth : getWidth();
+ }
+
+// @Override
+// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+// if (mNumColumns == GridView.AUTO_FIT) {
+// mAvailableWidth = MeasureSpec.getSize(widthMeasureSpec);
+// if (mColumnWidth > 0) {
+// int availableSpace = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
+// // Client told us to pick the number of columns
+// mNumColumns = (availableSpace + mHorizontalSpacing) /
+// (mColumnWidth + mHorizontalSpacing);
+// } else {
+// // Just make up a number if we don't have enough info
+// mNumColumns = 2;
+// }
+// if(null != getAdapter()){
+// if(getAdapter() instanceof SimpleSectionedGridAdapter){
+// ((SimpleSectionedGridAdapter)getAdapter()).setSections();
+// }
+// }
+// }
+// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+// }
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/SimpleSectionedGridAdapter.java b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/SimpleSectionedGridAdapter.java
new file mode 100644
index 0000000000..df5f6ed213
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/java/com/cocosw/bottomsheet/SimpleSectionedGridAdapter.java
@@ -0,0 +1,348 @@
+package com.cocosw.bottomsheet;
+
+
+import java.util.Arrays;
+import java.util.Comparator;
+
+import android.content.Context;
+import android.database.DataSetObserver;
+import android.text.TextUtils;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.GridView;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.TextView;
+
+class SimpleSectionedGridAdapter extends BaseAdapter{
+ protected static final int TYPE_FILLER = 0;
+ protected static final int TYPE_HEADER = 1;
+ protected static final int TYPE_HEADER_FILLER = 2;
+ private boolean mValid = true;
+ private int mSectionResourceId;
+ private LayoutInflater mLayoutInflater;
+ private ListAdapter mBaseAdapter;
+ SparseArray<Section> mSections = new SparseArray<Section>();
+ private Section[] mInitialSections = new Section[0];
+ private Context mContext;
+ private View mLastViewSeen;
+ private int mHeaderWidth;
+ private int mNumColumns;
+ private int mWidth;
+ private int mColumnWidth;
+ private int mHorizontalSpacing;
+ private int mStrechMode;
+ private int requestedColumnWidth;
+ private int requestedHorizontalSpacing;
+ private GridView mGridView;
+ private int mHeaderLayoutResId;
+ private int mHeaderTextViewResId;
+
+ public static class Section {
+ int firstPosition;
+ int sectionedPosition;
+ CharSequence title;
+ int type = 0;
+
+ public Section(int firstPosition, CharSequence title) {
+ this.firstPosition = firstPosition;
+ this.title =title;
+ }
+
+ public CharSequence getTitle() {
+ return title;
+ }
+ }
+
+ public SimpleSectionedGridAdapter(Context context, BaseAdapter baseAdapter, int sectionResourceId, int headerLayoutResId,
+ int headerTextViewResId) {
+ mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+ mSectionResourceId = sectionResourceId;
+ mHeaderLayoutResId = headerLayoutResId;
+ mHeaderTextViewResId = headerTextViewResId;
+ mBaseAdapter = baseAdapter;
+ mContext = context;
+ mBaseAdapter.registerDataSetObserver(new DataSetObserver() {
+ @Override
+ public void onChanged() {
+ mValid = !mBaseAdapter.isEmpty();
+ notifyDataSetChanged();
+ }
+
+ @Override
+ public void onInvalidated() {
+ mValid = false;
+ notifyDataSetInvalidated();
+ }
+ });
+ }
+
+ public void setGridView(GridView gridView){
+ if(!(gridView instanceof PinnedSectionGridView)){
+ throw new IllegalArgumentException("Does your grid view extends PinnedSectionGridView?");
+ }
+ mGridView = gridView;
+ mStrechMode = gridView.getStretchMode();
+ mWidth = gridView.getWidth() - (mGridView.getPaddingLeft() + mGridView.getPaddingRight());
+ mNumColumns = ((PinnedSectionGridView)gridView).getNumColumns();
+ requestedColumnWidth = ((PinnedSectionGridView)gridView).getColumnWidth();
+ requestedHorizontalSpacing = ((PinnedSectionGridView)gridView).getHorizontalSpacing();
+ }
+
+ private int getHeaderSize(){
+ if(mHeaderWidth > 0){
+ return mHeaderWidth;
+ }
+ if(mWidth != mGridView.getWidth()){
+ mStrechMode = mGridView.getStretchMode();
+ mWidth = ((PinnedSectionGridView)mGridView).getAvailableWidth() - (mGridView.getPaddingLeft() + mGridView.getPaddingRight());
+ mNumColumns = ((PinnedSectionGridView)mGridView).getNumColumns();
+ requestedColumnWidth = ((PinnedSectionGridView)mGridView).getColumnWidth();
+ requestedHorizontalSpacing = ((PinnedSectionGridView)mGridView).getHorizontalSpacing();
+ }
+
+ int spaceLeftOver = mWidth - (mNumColumns * requestedColumnWidth) -
+ ((mNumColumns - 1) * requestedHorizontalSpacing);
+ switch (mStrechMode) {
+ case GridView.NO_STRETCH: // Nobody stretches
+ mWidth -= spaceLeftOver;
+ mColumnWidth = requestedColumnWidth;
+ mHorizontalSpacing = requestedHorizontalSpacing;
+ break;
+
+ case GridView.STRETCH_COLUMN_WIDTH:
+ mColumnWidth = requestedColumnWidth + spaceLeftOver / mNumColumns;
+ mHorizontalSpacing = requestedHorizontalSpacing;
+ break;
+
+ case GridView.STRETCH_SPACING:
+ mColumnWidth = requestedColumnWidth;
+ if (mNumColumns > 1) {
+ mHorizontalSpacing = requestedHorizontalSpacing +
+ spaceLeftOver / (mNumColumns - 1);
+ } else {
+ mHorizontalSpacing = requestedHorizontalSpacing + spaceLeftOver;
+ }
+ break;
+
+ case GridView.STRETCH_SPACING_UNIFORM:
+ mColumnWidth = requestedColumnWidth;
+ mHorizontalSpacing = requestedHorizontalSpacing;
+ mWidth = mWidth - spaceLeftOver + (2 * mHorizontalSpacing);
+ break;
+ }
+ mHeaderWidth = mWidth + ((mNumColumns - 1) * (mColumnWidth + mHorizontalSpacing)) ;
+ return mHeaderWidth;
+ }
+
+
+ public void setSections(Section... sections) {
+ mInitialSections = sections;
+ setSections();
+ }
+
+ public void setSections() {
+ mSections.clear();
+
+ getHeaderSize();
+ Arrays.sort(mInitialSections, new Comparator<Section>() {
+ @Override
+ public int compare(Section o, Section o1) {
+ return (o.firstPosition == o1.firstPosition)
+ ? 0
+ : ((o.firstPosition < o1.firstPosition) ? -1 : 1);
+ }
+ });
+
+ int offset = 0; // offset positions for the headers we're adding
+ for (int i = 0; i < mInitialSections.length; i++) {
+ Section section = mInitialSections[i];
+ Section sectionAdd;
+
+ for (int j = 0; j < mNumColumns - 1; j++) {
+ sectionAdd = new Section(section.firstPosition, section.title);
+ sectionAdd.type = TYPE_HEADER_FILLER;
+ sectionAdd.sectionedPosition = sectionAdd.firstPosition + offset;
+ mSections.append(sectionAdd.sectionedPosition, sectionAdd);
+ ++offset;
+ }
+
+ sectionAdd = new Section(section.firstPosition, section.title);
+ sectionAdd.type = TYPE_HEADER;
+ sectionAdd.sectionedPosition = sectionAdd.firstPosition + offset;
+ mSections.append(sectionAdd.sectionedPosition, sectionAdd);
+ ++offset;
+
+ if(i < mInitialSections.length - 1){
+ int nextPos = mInitialSections[i+1].firstPosition;
+ int itemsCount = nextPos - section.firstPosition;
+ int dummyCount = mNumColumns - (itemsCount % mNumColumns);
+ if(mNumColumns != dummyCount){
+ for (int k = 0 ;k < dummyCount; k++) {
+ sectionAdd = new Section(section.firstPosition, section.title);
+ sectionAdd.type = TYPE_FILLER;
+ sectionAdd.sectionedPosition = nextPos + offset;
+ mSections.append(sectionAdd.sectionedPosition, sectionAdd);
+ ++offset;
+ }
+ }
+ }
+ }
+
+ notifyDataSetChanged();
+ }
+
+ public int positionToSectionedPosition(int position) {
+ int offset = 0;
+ for (int i = 0; i < mSections.size(); i++) {
+ if (mSections.valueAt(i).firstPosition > position) {
+ break;
+ }
+ ++offset;
+ }
+ return position + offset;
+ }
+
+ public int sectionedPositionToPosition(int sectionedPosition) {
+ if (isSectionHeaderPosition(sectionedPosition)) {
+ return ListView.INVALID_POSITION;
+ }
+
+ int offset = 0;
+ for (int i = 0; i < mSections.size(); i++) {
+ if (mSections.valueAt(i).sectionedPosition > sectionedPosition) {
+ break;
+ }
+ --offset;
+ }
+ return sectionedPosition + offset;
+ }
+
+ public boolean isSectionHeaderPosition(int position) {
+ return mSections.get(position) != null;
+ }
+
+ @Override
+ public int getCount() {
+ return (mValid ? mBaseAdapter.getCount() + mSections.size() : 0);
+ }
+
+ @Override
+ public Object getItem(int position) {
+ return isSectionHeaderPosition(position)
+ ? mSections.get(position)
+ : mBaseAdapter.getItem(sectionedPositionToPosition(position));
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return isSectionHeaderPosition(position)
+ ? Integer.MAX_VALUE - mSections.indexOfKey(position)
+ : mBaseAdapter.getItemId(sectionedPositionToPosition(position));
+ }
+
+ @Override
+ public int getItemViewType(int position) {
+ return isSectionHeaderPosition(position)
+ ? getViewTypeCount() - 1
+ : mBaseAdapter.getItemViewType(sectionedPositionToPosition(position));
+ }
+
+ @Override
+ public boolean isEnabled(int position) {
+ //noinspection SimplifiableConditionalExpression
+ return isSectionHeaderPosition(position)
+ ? false
+ : mBaseAdapter.isEnabled(sectionedPositionToPosition(position));
+ }
+
+ @Override
+ public int getViewTypeCount() {
+ return mBaseAdapter.getViewTypeCount() + 1; // the section headings
+ }
+
+ @Override
+ public boolean areAllItemsEnabled() {
+ return mBaseAdapter.areAllItemsEnabled();
+ }
+
+ @Override
+ public boolean hasStableIds() {
+ return mBaseAdapter.hasStableIds();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return mBaseAdapter.isEmpty();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ if (isSectionHeaderPosition(position)) {
+ HeaderLayout header;
+ TextView view;
+ if (null == convertView) {
+ convertView = mLayoutInflater.inflate(mSectionResourceId, parent, false);
+ } else {
+ if (null == convertView.findViewById(mHeaderLayoutResId)) {
+ convertView = mLayoutInflater.inflate(mSectionResourceId, parent, false);
+ }
+ }
+ switch (mSections.get(position).type) {
+ case TYPE_HEADER:
+ header = (HeaderLayout) convertView.findViewById(mHeaderLayoutResId);
+ if (!TextUtils.isEmpty(mSections.get(position).title)) {
+ view = (TextView) convertView.findViewById(mHeaderTextViewResId);
+ view.setText(mSections.get(position).title);
+ }
+ header.setHeaderWidth(getHeaderSize());
+ break;
+ case TYPE_HEADER_FILLER:
+ header = (HeaderLayout) convertView.findViewById(mHeaderLayoutResId);
+ if (!TextUtils.isEmpty(mSections.get(position).title)) {
+ view = (TextView) convertView.findViewById(mHeaderTextViewResId);
+ view.setText(mSections.get(position).title);
+ }
+ header.setHeaderWidth(0);
+ break;
+ default:
+ convertView = getFillerView(mLastViewSeen);
+ }
+ } else {
+ convertView = mBaseAdapter.getView(sectionedPositionToPosition(position), convertView, parent);
+ mLastViewSeen = convertView;
+ }
+ return convertView;
+ }
+
+ private FillerView getFillerView(final View lastViewSeen) {
+ final FillerView fillerView = new FillerView(mContext);
+ fillerView.setMeasureTarget(lastViewSeen);
+ return fillerView;
+ }
+
+ public int getHeaderLayoutResId() {
+ return mHeaderLayoutResId;
+ }
+
+ public static class ViewHolder {
+ @SuppressWarnings("unchecked")
+ public static <T extends View> T get(View view, int id) {
+ SparseArray<View> viewHolder = (SparseArray<View>) view.getTag();
+ if (viewHolder == null) {
+ viewHolder = new SparseArray<View>();
+ view.setTag(viewHolder);
+ }
+ View childView = viewHolder.get(id);
+ if (childView == null) {
+ childView = view.findViewById(id);
+ viewHolder.put(id, childView);
+ }
+ return (T) childView;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_item_in.xml b/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_item_in.xml
new file mode 100644
index 0000000000..6e63d9b837
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_item_in.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:interpolator/fast_out_slow_in">
+ <translate android:fromYDelta="600%" android:toYDelta="0"
+ android:duration="250"/>
+</set>
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_layout_anim_in.xml b/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_layout_anim_in.xml
new file mode 100644
index 0000000000..0219dbbe4b
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim-v21/bs_list_layout_anim_in.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="12%"
+ android:animation="@anim/bs_list_item_in"
+ android:interpolator="@android:interpolator/fast_out_slow_in"/> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_item_in.xml b/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_item_in.xml
new file mode 100644
index 0000000000..7c696e0779
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_item_in.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/decelerate_interpolator">
+ <translate android:fromYDelta="600%" android:toYDelta="0"
+ android:duration="250"/>
+</set>
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_layout_anim_in.xml b/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_layout_anim_in.xml
new file mode 100644
index 0000000000..8d994ee2e1
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim/bs_list_layout_anim_in.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
+ android:delay="12%"
+ android:animation="@anim/bs_list_item_in"
+ android:interpolator="@android:anim/decelerate_interpolator"/> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_enter.xml b/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_enter.xml
new file mode 100644
index 0000000000..c9d4283d20
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_enter.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- Animation for when a dock window at the bottom of the screen is entering. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/decelerate_interpolator">
+ <translate android:fromYDelta="100%" android:toYDelta="0"
+ android:duration="250"/>
+</set>
diff --git a/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_exit.xml b/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_exit.xml
new file mode 100644
index 0000000000..d01e1e4526
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/anim/dock_bottom_exit.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* Copyright 2012, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+
+<!-- Animation for when a dock window at the bottom of the screen is exiting. -->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:interpolator="@android:anim/accelerate_interpolator">
+ <translate android:fromYDelta="0" android:toYDelta="100%"
+ android:startOffset="100" android:duration="250"/>
+</set>
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear.png b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear.png
new file mode 100644
index 0000000000..45fef78a24
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear_light.png
new file mode 100644
index 0000000000..ea21b1bf2d
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_clear_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more.png b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more.png
new file mode 100644
index 0000000000..7f1e16254a
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more_light.png
new file mode 100644
index 0000000000..9c7e47428c
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-hdpi/bs_ic_more_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear.png b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear.png
new file mode 100644
index 0000000000..6c3a59fe65
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear_light.png
new file mode 100644
index 0000000000..cfb1679945
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_clear_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more.png b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more.png
new file mode 100644
index 0000000000..4e4f883b08
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more_light.png
new file mode 100644
index 0000000000..0e483d5f3b
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-mdpi/bs_ic_more_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_dark_selector.xml b/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_dark_selector.xml
new file mode 100644
index 0000000000..b5e07b3f29
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_dark_selector.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#40ffffff">
+ <item android:id="@android:id/mask">
+ <color android:color="@android:color/white" />
+ </item>
+</ripple> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_selector.xml b/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_selector.xml
new file mode 100644
index 0000000000..bc8e1afdb6
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-v21/bs_list_selector.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="#40000000">
+ <item android:id="@android:id/mask">
+ <color android:color="@android:color/white" />
+ </item>
+</ripple>
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear.png
new file mode 100644
index 0000000000..2eb9589dd6
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear_light.png
new file mode 100644
index 0000000000..0aaf7e2df4
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_clear_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more.png
new file mode 100644
index 0000000000..36328793dd
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more_light.png
new file mode 100644
index 0000000000..dd8d74338f
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xhdpi/bs_ic_more_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear.png
new file mode 100644
index 0000000000..3ec1adb77d
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear_light.png
new file mode 100644
index 0000000000..61817c96bb
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_clear_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more.png
new file mode 100644
index 0000000000..045c2ae440
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more_light.png b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more_light.png
new file mode 100644
index 0000000000..dea04ab546
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable-xxhdpi/bs_ic_more_light.png
Binary files differ
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_dark_selector.xml b/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_dark_selector.xml
new file mode 100644
index 0000000000..6ac9df0b3e
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_dark_selector.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#1AFFFFFF" />
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape>
+ <solid android:color="#77FFFFFF" />
+ </shape>
+ </item>
+ <item android:drawable="@android:color/transparent" />
+
+</selector> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_selector.xml b/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_selector.xml
new file mode 100644
index 0000000000..8d993f4f27
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/drawable/bs_list_selector.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <item android:state_pressed="true">
+ <shape>
+ <solid android:color="#1A000000" />
+ </shape>
+ </item>
+ <item android:state_focused="true">
+ <shape>
+ <solid android:color="#77000000" />
+ </shape>
+ </item>
+ <item android:drawable="@android:color/transparent" />
+
+</selector> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/layout/bottom_sheet_dialog.xml b/android/3rd_party/BottomSheet/src/main/res/layout/bottom_sheet_dialog.xml
new file mode 100644
index 0000000000..c68e74a4b6
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/layout/bottom_sheet_dialog.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<com.cocosw.bottomsheet.ClosableSlidingLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
+
+ <LinearLayout
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:background="?bs_dialogBackground"
+ tools:ignore="Overdraw"
+ android:layout_gravity="bottom">
+
+ <View
+ style="@style/BottomSheet.TopDivider" />
+
+ <LinearLayout
+ android:layout_width="fill_parent"
+ android:layout_height="wrap_content"
+ android:orientation="horizontal"
+ android:gravity="center_vertical"
+ tools:ignore="UseCompoundDrawables">
+
+ <ImageView
+ android:id="@+id/bottom_sheet_title_image"
+ android:visibility="gone"
+ tools:ignore="ContentDescription"
+ style="@style/BottomSheet.Icon" />
+
+ <TextView
+ android:id="@+id/bottom_sheet_title"
+ android:visibility="gone"
+ style="@style/BottomSheet.Title" />
+
+ </LinearLayout>
+
+ <com.cocosw.bottomsheet.PinnedSectionGridView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:id="@+id/bottom_sheet_gridview"
+ android:numColumns="?bs_numColumns"
+ android:fadingEdge="none"
+ style="?bs_listStyle"
+ tools:listitem="@layout/bs_grid_entry" />
+
+ </LinearLayout>
+
+</com.cocosw.bottomsheet.ClosableSlidingLayout> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/layout/bs_grid_entry.xml b/android/3rd_party/BottomSheet/src/main/res/layout/bs_grid_entry.xml
new file mode 100644
index 0000000000..77883fd0f9
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/layout/bs_grid_entry.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="vertical" android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ style="@style/BottomSheet.GridItem"
+ tools:ignore="UseCompoundDrawables">
+
+ <ImageView
+ style="@style/BottomSheet.GridItemImage"
+ android:id="@+id/bs_list_image"
+ tools:ignore="ContentDescription" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/BottomSheet.GridItemTitle"
+ android:id="@+id/bs_list_title" />
+</LinearLayout> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_divider.xml b/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_divider.xml
new file mode 100644
index 0000000000..627e9b77ea
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_divider.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<com.cocosw.bottomsheet.HeaderLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_height="wrap_content"
+ android:layout_width="fill_parent"
+ android:id="@+id/headerlayout">
+
+ <View style="@style/BottomSheet.ListDivider" android:id="@+id/header"/>
+</com.cocosw.bottomsheet.HeaderLayout> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_entry.xml b/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_entry.xml
new file mode 100644
index 0000000000..bf3907f7a3
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/layout/bs_list_entry.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:orientation="horizontal" android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ style="@style/BottomSheet.ListItem"
+ tools:ignore="UseCompoundDrawables">
+
+ <ImageView
+ style="@style/BottomSheet.ListItemImage"
+ android:id="@+id/bs_list_image"
+ tools:ignore="ContentDescription" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="@style/BottomSheet.ListItemTitle"
+ android:id="@+id/bs_list_title" />
+</LinearLayout> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values-land/integer.xml b/android/3rd_party/BottomSheet/src/main/res/values-land/integer.xml
new file mode 100644
index 0000000000..14b618e725
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values-land/integer.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="bs_grid_colum">4</integer>
+ <integer name="bs_initial_grid_row">2</integer>
+ <integer name="bs_initial_list_row">3</integer>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values-sw600dp-land/integer.xml b/android/3rd_party/BottomSheet/src/main/res/values-sw600dp-land/integer.xml
new file mode 100644
index 0000000000..b9f4d35128
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values-sw600dp-land/integer.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="bs_grid_colum">5</integer>
+ <integer name="bs_initial_grid_row">2</integer>
+ <integer name="bs_initial_list_row">4</integer>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values-sw600dp/integer.xml b/android/3rd_party/BottomSheet/src/main/res/values-sw600dp/integer.xml
new file mode 100644
index 0000000000..59e2da2350
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values-sw600dp/integer.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="bs_grid_colum">4</integer>
+ <integer name="bs_initial_grid_row">3</integer>
+ <integer name="bs_initial_list_row">5</integer>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values-zh/string.xml b/android/3rd_party/BottomSheet/src/main/res/values-zh/string.xml
new file mode 100644
index 0000000000..3028014861
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values-zh/string.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="bs_more">更多</string>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml b/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml
new file mode 100644
index 0000000000..efeacc3378
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/attrs.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <declare-styleable name="BottomSheet">
+ <attr name="bottomSheetStyle" format="reference"/>
+ <attr name="bs_dialogBackground" format="color|reference" />
+ <attr name="bs_listStyle" format="reference"/>
+ <attr name="bs_dividerColor" format="color|reference" />
+ <attr name="bs_numColumns" format="integer"/>
+ <attr name="bs_titleTextAppearance" format="reference" />
+ <attr name="bs_listItemTitleTextAppearance" format="reference" />
+ <attr name="bs_gridItemTitleTextAppearance" format="reference" />
+ <attr name="bs_moreDrawable" format="reference"/>
+ <attr name="bs_moreText" format="string"/>
+ <attr name="bs_closeDrawable" format="reference"/>
+ <attr name="bs_collapseListIcons" format="boolean"/>
+ </declare-styleable>
+
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/colors.xml b/android/3rd_party/BottomSheet/src/main/res/values/colors.xml
new file mode 100644
index 0000000000..c9cfaa2198
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/colors.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <color name="bs_divider_color">#1f000000</color>
+ <color name="bs_dark_divider_color">#1fffffff</color>
+
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/dimens.xml b/android/3rd_party/BottomSheet/src/main/res/values/dimens.xml
new file mode 100644
index 0000000000..f44cb5bb3f
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+<dimen name="bs_grid_left_padding">8dp</dimen>
+ <dimen name="bs_grid_top_padding">0dp</dimen>
+ <dimen name="bs_grid_right_padding">8dp</dimen>
+ <dimen name="bs_grid_bottom_padding">8dp</dimen>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/ids.xml b/android/3rd_party/BottomSheet/src/main/res/values/ids.xml
new file mode 100644
index 0000000000..267747edcc
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/ids.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <item name="bs_more" type="id" />
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/integer.xml b/android/3rd_party/BottomSheet/src/main/res/values/integer.xml
new file mode 100644
index 0000000000..151505b1b0
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/integer.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <integer name="bs_grid_colum">3</integer>
+ <integer name="bs_initial_grid_row">3</integer>
+ <integer name="bs_initial_list_row">5</integer>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/string.xml b/android/3rd_party/BottomSheet/src/main/res/values/string.xml
new file mode 100644
index 0000000000..b3d0b5166a
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/string.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="bs_more">More</string>
+</resources> \ No newline at end of file
diff --git a/android/3rd_party/BottomSheet/src/main/res/values/styles.xml b/android/3rd_party/BottomSheet/src/main/res/values/styles.xml
new file mode 100644
index 0000000000..4644e2b4a3
--- /dev/null
+++ b/android/3rd_party/BottomSheet/src/main/res/values/styles.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources xmlns:tools="http://schemas.android.com/tools">
+
+ <style name="BottomSheet" />
+
+ <style name="BottomSheet.Dialog" parent="android:style/Theme.Dialog">
+ <item name="android:windowFrame">@null</item>
+ <item name="android:textColor">@null</item>
+ <item name="android:windowNoTitle">true</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:windowBackground">@android:color/transparent</item>
+ <item name="android:windowIsFloating">true</item>
+ <item name="android:windowContentOverlay">@null</item>
+ <item name="android:windowIsTranslucent">true</item>
+ <item name="android:backgroundDimAmount">0.3</item>
+ <item name="android:backgroundDimEnabled">true</item>
+ <item name="android:windowAnimationStyle">@style/BottomSheet.Animation</item>
+ <item name="android:textColorPrimary">#DD000000</item>
+ <item name="android:textColorSecondary">#8A000000</item>
+ <item name="android:textColorHint">#42000000</item>
+ <item name="bs_dialogBackground">@android:color/background_light</item>
+ <item name="bs_dividerColor">@color/bs_divider_color</item>
+ <item name="bs_numColumns">@integer/bs_grid_colum</item>
+ <item name="bs_titleTextAppearance">@style/Text.Headline</item>
+ <item name="bs_listItemTitleTextAppearance">@style/Text.Title</item>
+ <item name="bs_gridItemTitleTextAppearance">@style/Text.Hint</item>
+ <item name="bs_moreText">@string/bs_more</item>
+ <item name="bs_closeDrawable">@drawable/bs_ic_clear_light</item>
+ <item name="bs_moreDrawable">@drawable/bs_ic_more_light</item>
+ <item name="bs_listStyle">@style/BottomSheet.List</item>
+ <item name="bs_collapseListIcons">true</item>
+ </style>
+
+ <style name="BottomSheet.Dialog.Dark" parent="BottomSheet.Dialog">
+ <item name="android:textColorPrimary">#DDffffff</item>
+ <item name="android:textColorSecondary">#8Affffff</item>
+ <item name="android:textColorHint">#42ffffff</item>
+ <item name="bs_dialogBackground">@android:color/background_dark</item>
+ <item name="bs_dividerColor">@color/bs_dark_divider_color</item>
+ <item name="bs_listStyle">@style/BottomSheet.List.Dark</item>
+ <item name="bs_closeDrawable">@drawable/bs_ic_clear</item>
+ <item name="bs_moreDrawable">@drawable/bs_ic_more</item>
+ </style>
+
+ <style name="Text"/>
+
+ <style name="Text.Headline">
+ <item name="android:textSize">16sp</item>
+ <item name="android:fontFamily" tools:ignore="NewApi">sans-serif</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">?android:textColorSecondary</item>
+ </style>
+
+ <style name="Text.Title">
+ <item name="android:textSize">16sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">?android:textColorPrimary</item>
+ <item name="android:fontFamily" tools:ignore="NewApi">sans-serif-medium</item>
+ </style>
+
+ <style name="Text.Hint">
+ <item name="android:textSize">12sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">?android:textColorHint</item>
+ <item name="android:fontFamily" tools:ignore="NewApi">sans-serif-medium</item>
+ </style>
+
+ <style name="Text.Subhead">
+ <item name="android:textSize">16sp</item>
+ <item name="android:textStyle">normal</item>
+ <item name="android:textColor">?android:textColorPrimary</item>
+ <item name="android:fontFamily" tools:ignore="NewApi">sans-serif</item>
+ </style>
+
+ <style name="BottomSheet.Title">
+ <item name="android:singleLine">true</item>
+ <item name="android:minHeight">56dp</item>
+ <item name="android:layout_marginLeft">16dp</item>
+ <item name="android:layout_marginRight">16dp</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:textAppearance">?bs_titleTextAppearance</item>
+ <item name="android:gravity">center_vertical</item>
+ </style>
+
+ <style name="BottomSheet.Icon">
+ <item name="android:layout_width">40dp</item>
+ <item name="android:layout_height">40dp</item>
+ <item name="android:layout_marginLeft">16dp</item>
+ </style>
+
+ <style name="BottomSheet.List">
+ <item name="android:listSelector">@drawable/bs_list_selector</item>
+ <item name="android:drawSelectorOnTop">false</item>
+ <item name="android:layoutAnimation">@anim/bs_list_layout_anim_in</item>
+ <item name="android:paddingBottom">8dp</item>
+ <item name="android:clipToPadding">false</item>
+ </style>
+
+ <style name="BottomSheet.List.Dark">
+ <item name="android:listSelector">@drawable/bs_list_dark_selector</item>
+ </style>
+
+ <style name="BottomSheet.ListItem">
+ <item name="android:minHeight">48dp</item>
+ <item name="android:gravity">center_vertical</item>
+ <item name="android:layoutAnimation">@null</item>
+ </style>
+
+ <style name="BottomSheet.ListItemImage">
+ <item name="android:layout_marginLeft">16dp</item>
+ <item name="android:layout_height">24dp</item>
+ <item name="android:layout_width">24dp</item>
+ <item name="android:layout_marginRight">16dp</item>
+ </style>
+
+ <style name="BottomSheet.ListItemTitle">
+ <item name="android:layout_marginLeft">16dp</item>
+ <item name="android:layout_marginRight">16dp</item>
+ <item name="android:textAppearance">?bs_listItemTitleTextAppearance</item>
+ </style>
+
+ <style name="BottomSheet.ListDivider">
+ <item name="android:layout_height">wrap_content</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:minHeight">1dp</item>
+ <item name="android:background">?bs_dividerColor</item>
+ <item name="android:layout_marginTop">7dp</item>
+ <item name="android:layout_marginBottom">8dp</item>
+ </style>
+
+ <style name="BottomSheet.GridItemImage">
+ <item name="android:layout_height">48dp</item>
+ <item name="android:layout_width">48dp</item>
+ <item name="android:layout_margin">8dp</item>
+ <item name="android:padding">0dp</item>
+ </style>
+
+ <style name="BottomSheet.GridItemTitle">
+ <item name="android:singleLine">true</item>
+ <item name="android:textAppearance">?bs_gridItemTitleTextAppearance</item>
+ <item name="android:padding">0dp</item>
+ </style>
+
+ <style name="BottomSheet.Grid"/>
+
+ <style name="BottomSheet.GridItem">
+ <item name="android:gravity">center_horizontal</item>
+ <item name="android:paddingTop">8dp</item>
+ <item name="android:paddingBottom">8dp</item>
+ </style>
+
+ <style name="BottomSheet.Animation">
+ <item name="android:windowEnterAnimation">@anim/dock_bottom_enter</item>
+ <item name="android:windowExitAnimation">@anim/dock_bottom_exit</item>
+ </style>
+
+ <style name="BottomSheet.TopDivider">
+ <item name="android:background">?bs_dividerColor</item>
+ <item name="android:layout_width">fill_parent</item>
+ <item name="android:layout_height">1dp</item>
+ <item name="android:layout_marginBottom">8dp</item>
+ </style>
+
+</resources> \ No newline at end of file