├── .github
└── workflows
│ └── android.yml
├── .gitignore
├── README.md
├── app
├── .gitignore
├── README.txt
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── io
│ │ └── anycopy
│ │ └── googleplusdemo
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── io
│ │ │ └── anycopy
│ │ │ └── googleplusdemo
│ │ │ ├── App.java
│ │ │ ├── AppFragmentPageAdapter.java
│ │ │ ├── BottomNavItemSelectedListener.java
│ │ │ ├── BottomNavigationBehavior.java
│ │ │ ├── BottomNavigationFABBehavior.java
│ │ │ ├── CustomTabManager.java
│ │ │ ├── CustomViewPager.java
│ │ │ ├── DashboardChildFragment.java
│ │ │ ├── DashboardFragment.java
│ │ │ ├── HomeFragment.java
│ │ │ ├── MainActivity.java
│ │ │ ├── NotificationFragment.java
│ │ │ ├── SideNavItemSelectedListener.java
│ │ │ └── TimberLogger.java
│ └── res
│ │ ├── drawable-v21
│ │ ├── ic_add_white_24dp.xml
│ │ ├── ic_menu_gallery.xml
│ │ ├── ic_menu_manage.xml
│ │ ├── ic_menu_send.xml
│ │ └── ic_menu_share.xml
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ ├── ic_baseline_delete_24.xml
│ │ ├── ic_baseline_message_24.xml
│ │ ├── ic_baseline_search_24.xml
│ │ ├── ic_dashboard_black_24dp.xml
│ │ ├── ic_home_black_24dp.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_notifications_black_24dp.xml
│ │ └── side_nav_bar.xml
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── custom_toolbar.xml
│ │ ├── fragment_dashboard.xml
│ │ ├── fragment_dashboard_child.xml
│ │ ├── fragment_home.xml
│ │ ├── fragment_notification.xml
│ │ └── nav_header_main.xml
│ │ ├── menu
│ │ ├── activity_main_drawer.xml
│ │ ├── delete.xml
│ │ ├── main.xml
│ │ ├── message.xml
│ │ ├── navigation.xml
│ │ ├── search.xml
│ │ ├── send.xml
│ │ └── snack_bar.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── long_string.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── io
│ └── anycopy
│ └── googleplusdemo
│ └── ExampleUnitTest.java
├── build.gradle
├── config
└── hooks
│ ├── pre-commit
│ └── pre-commit-stub
├── google_plus_demo.gif
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 | tags:
11 | - '*'
12 |
13 | env:
14 | CI: true
15 | GRADLE_OPTS: -Dorg.gradle.daemon=false
16 | TERM: dumb
17 |
18 | jobs:
19 | assemble:
20 | name: Assemble
21 | runs-on: ubuntu-latest
22 | env:
23 | JAVA_TOOL_OPTIONS: -Xmx4g
24 |
25 | steps:
26 | - uses: actions/checkout@v2
27 | with:
28 | fetch-depth: 0
29 |
30 | - uses: gradle/wrapper-validation-action@v1
31 |
32 | - uses: actions/setup-java@v1
33 | with:
34 | java-version: 14
35 |
36 | - uses: actions/cache@v1
37 | with:
38 | path: ~/.gradle/caches
39 | key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.java') }}
40 |
41 | - name: Assemble debug App apk
42 | run: |
43 | ./gradlew app:assembleDebug
44 |
45 | unit-tests:
46 | name: Unit tests
47 | runs-on: ubuntu-latest
48 | env:
49 | JAVA_TOOL_OPTIONS: -Xmx4g
50 |
51 | steps:
52 | - uses: actions/checkout@v2
53 |
54 | - uses: gradle/wrapper-validation-action@v1
55 |
56 | - uses: actions/setup-java@v1
57 | with:
58 | java-version: 14
59 |
60 | - uses: actions/cache@v1
61 | with:
62 | path: ~/.gradle/caches
63 | key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.java') }}
64 |
65 | - name: Run unit tests
66 | run: |
67 | ./gradlew test -PslimTests
68 | - name: Copy test results
69 | if: always()
70 | run: |
71 | mkdir -p junit
72 | find . -type f -regex ".*/build/test-results/.*xml" -exec cp {} junit/ \;
73 | - name: Upload test results
74 | if: always()
75 | uses: actions/upload-artifact@v1
76 | with:
77 | name: junit-results
78 | path: junit
79 |
80 | static-analysis:
81 | name: Static analysis
82 | runs-on: ubuntu-latest
83 | env:
84 | JAVA_TOOL_OPTIONS: -Xmx4g
85 | steps:
86 | - uses: actions/checkout@v2
87 |
88 | - uses: gradle/wrapper-validation-action@v1
89 |
90 | - uses: actions/setup-java@v1
91 | with:
92 | java-version: 14
93 |
94 | - uses: actions/cache@v1
95 | with:
96 | path: ~/.gradle/caches
97 | key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.java') }}
98 | - name: Cleanup secrets
99 | if: always()
100 | run: |
101 | rm -f app/src/prod/google-services.json
102 | instrumented-tests:
103 | name: Instrumented tests
104 | runs-on: macos-10.15
105 | timeout-minutes: 25
106 | env:
107 | JAVA_TOOL_OPTIONS: -Xmx4g
108 |
109 | steps:
110 | - uses: actions/checkout@v2
111 |
112 | - uses: gradle/wrapper-validation-action@v1
113 |
114 | - uses: actions/setup-java@v1
115 | with:
116 | java-version: 14
117 |
118 | - uses: actions/cache@v1
119 | with:
120 | path: ~/.gradle/caches
121 | key: ${{ runner.os }}-${{ github.job }}-${{ hashFiles('**/*.gradle*') }}-${{ hashFiles('**/gradle/wrapper/gradle-wrapper.properties') }}-${{ hashFiles('**/buildSrc/**/*.java') }}
122 |
123 | - name: Run Android instrumented tests
124 | uses: reactivecircus/android-emulator-runner@v2.20.0
125 | with:
126 | api-level: 28
127 | arch: x86_64
128 | profile: Nexus 5X
129 | script: ./gradlew connectedCheck
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | local.properties
4 | .DS_Store
5 | /captures
6 | .externalNativeBuild
7 | build
8 | .idea
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Google+ Android Sample App demo
2 | =========================
3 | This is a sample app to demonstrate how to create a Google Plus Android sample app that integrates the following UI elements:
4 |
5 | [demo gif preview](google_plus_demo.gif?raw=true)
6 |
7 | BottomNavigationBar
8 | ViewPager
9 | Fragment
10 | ChildFragment
11 | TabLayout
12 | DrawerLayout
13 | SnackBar
14 | FloatingActionBar
15 | NestedScrollView
16 |
17 |
18 | The whole repository contains several branches, which gradually adds a new feature based on the previous branch. For more details, please refer to this blog.
19 |
20 | [Integrate CoordinatorLayout + BottomNavigationView + Toolbar + TabLayout + ViewPager + Fragment + DrawerLayout](https://medium.com/@tonythompsoncmu/integrate-coordinatorlayout-bottomnavigationview-toolbar-tablayout-viewpager-fragment-e4268e83b475)
21 |
22 |
23 | ## Sample Apk download link
24 | [click to download the apk](https://github.com/TonyTangAndroid/GooglePlusDemo/releases/download/0.0.5/app-debug-v4.apk)
25 |
26 |
27 |
28 | License
29 | -------
30 |
31 | Copyright 2018 TonyTangAndroid.
32 |
33 | Licensed to the Apache Software Foundation (ASF) under one or more contributor
34 | license agreements. See the NOTICE file distributed with this work for
35 | additional information regarding copyright ownership. The ASF licenses this
36 | file to you under the Apache License, Version 2.0 (the "License"); you may not
37 | use this file except in compliance with the License. You may obtain a copy of
38 | the License at
39 |
40 | http://www.apache.org/licenses/LICENSE-2.0
41 |
42 | Unless required by applicable law or agreed to in writing, software
43 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
44 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
45 | License for the specific language governing permissions and limitations under
46 | the License.
47 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/README.txt:
--------------------------------------------------------------------------------
1 | Search is everywhere and it is always placed at the right edge.
2 | Message is only on notification
3 | Send is in Dashboard tab 1 and 2
4 | Delete is in Dashboard tab 2 and is always placed at the left edge
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 31
5 | defaultConfig {
6 | applicationId "io.anycopy.googleplusdemo"
7 | minSdkVersion 23
8 | targetSdkVersion 31
9 | versionCode 1
10 | versionName "1.0"
11 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
12 | vectorDrawables.useSupportLibrary = true
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | compileOptions {
21 | sourceCompatibility = '1.8'
22 | targetCompatibility = '1.8'
23 | }
24 | }
25 |
26 | dependencies {
27 | implementation "androidx.fragment:fragment:1.3.6"
28 | implementation "androidx.viewpager2:viewpager2:1.0.0"
29 | implementation "androidx.recyclerview:recyclerview:1.2.1"
30 | implementation 'androidx.appcompat:appcompat:1.3.1'
31 | implementation 'androidx.annotation:annotation:1.2.0'
32 | implementation 'com.google.android.material:material:1.4.0'
33 | implementation 'androidx.vectordrawable:vectordrawable:1.1.0'
34 |
35 | implementation "androidx.lifecycle:lifecycle-runtime:2.3.1"
36 |
37 | implementation 'com.jakewharton.timber:timber:5.0.1'
38 | testImplementation 'junit:junit:4.13.2'
39 | testImplementation 'com.google.truth:truth:1.1.3'
40 | androidTestImplementation 'androidx.test:core:1.4.0'
41 | androidTestImplementation 'androidx.test.ext:junit:1.1.3'
42 | androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.4.0'
43 | androidTestImplementation('androidx.test.espresso:espresso-core:3.4.0') {
44 | exclude group: 'org.checkerframework', module: 'checker'
45 | }
46 | androidTestImplementation('androidx.test.espresso:espresso-contrib:3.4.0') {
47 | exclude group: 'org.checkerframework', module: 'checker'
48 | }
49 | androidTestImplementation 'androidx.test:rules:1.4.0'
50 | androidTestImplementation 'androidx.test:runner:1.4.0'
51 | androidTestImplementation 'com.google.truth:truth:1.1.3'
52 | }
53 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/io/anycopy/googleplusdemo/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.ext.junit.runners.AndroidJUnit4;
6 | import androidx.test.platform.app.InstrumentationRegistry;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.assertEquals;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 |
21 | @Test
22 | public void useAppContext() throws Exception {
23 | // Context of the app under test.
24 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
25 | assertEquals("io.anycopy.googleplusdemo", appContext.getPackageName());
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/App.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.app.Application;
4 | import timber.log.Timber;
5 | import timber.log.Timber.DebugTree;
6 |
7 | public class App extends Application {
8 |
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | Timber.plant(new DebugTree());
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/AppFragmentPageAdapter.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import androidx.annotation.NonNull;
4 | import androidx.appcompat.app.AppCompatActivity;
5 | import androidx.fragment.app.Fragment;
6 | import androidx.viewpager2.adapter.FragmentStateAdapter;
7 |
8 | class AppFragmentPageAdapter extends FragmentStateAdapter {
9 |
10 | public AppFragmentPageAdapter(AppCompatActivity appCompatActivity) {
11 | super(appCompatActivity);
12 | }
13 |
14 | @NonNull
15 | @Override
16 | public Fragment createFragment(int position) {
17 | switch (position) {
18 | case 0:
19 | return HomeFragment.newInstance(1);
20 | case 1:
21 | return DashboardFragment.newInstance("Tony");
22 | case 2:
23 | return NotificationFragment.newInstance();
24 | default:
25 | throw new RuntimeException("Not supported");
26 | }
27 | }
28 |
29 | @Override
30 | public int getItemCount() {
31 | return 3;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/BottomNavItemSelectedListener.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.view.MenuItem;
4 | import androidx.annotation.NonNull;
5 | import androidx.appcompat.widget.Toolbar;
6 | import androidx.viewpager2.widget.ViewPager2;
7 | import com.google.android.material.bottomnavigation.BottomNavigationView;
8 |
9 | public class BottomNavItemSelectedListener implements BottomNavigationView.OnItemSelectedListener {
10 |
11 | private final Toolbar toolbar;
12 | private final ViewPager2 viewPager;
13 |
14 | public BottomNavItemSelectedListener(ViewPager2 viewPager, Toolbar toolbar) {
15 | this.toolbar = toolbar;
16 | this.viewPager = viewPager;
17 | }
18 |
19 | @Override
20 | public boolean onNavigationItemSelected(@NonNull MenuItem item) {
21 | toolbar.setTitle(item.getTitle());
22 | int itemId = item.getItemId();
23 | if (itemId == R.id.navigation_home) {
24 | viewPager.setCurrentItem(0);
25 | return true;
26 | } else if (itemId == R.id.navigation_dashboard) {
27 | viewPager.setCurrentItem(1);
28 | return true;
29 | } else if (itemId == R.id.navigation_notifications) {
30 | viewPager.setCurrentItem(2);
31 | return true;
32 | }
33 | return false;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/BottomNavigationBehavior.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.Gravity;
6 | import android.view.View;
7 |
8 | import androidx.annotation.NonNull;
9 | import androidx.annotation.Nullable;
10 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
11 | import androidx.core.view.ViewCompat;
12 |
13 | import com.google.android.material.bottomnavigation.BottomNavigationView;
14 | import com.google.android.material.snackbar.Snackbar;
15 |
16 | public final class BottomNavigationBehavior
17 | extends CoordinatorLayout.Behavior {
18 |
19 | public BottomNavigationBehavior(@NonNull Context context, @NonNull AttributeSet attrs) {
20 | super(context, attrs);
21 | }
22 |
23 | public boolean layoutDependsOn(
24 | @Nullable CoordinatorLayout parent,
25 | @NonNull BottomNavigationView child,
26 | @Nullable View dependency) {
27 | if (dependency instanceof Snackbar.SnackbarLayout) {
28 | this.updateSnackbar(child, (Snackbar.SnackbarLayout) dependency);
29 | }
30 |
31 | assert parent != null;
32 | assert dependency != null;
33 | return super.layoutDependsOn(parent, child, dependency);
34 | }
35 |
36 | public boolean onStartNestedScroll(
37 | @NonNull CoordinatorLayout coordinatorLayout,
38 | @NonNull BottomNavigationView child,
39 | @NonNull View directTargetChild,
40 | @NonNull View target,
41 | int axes,
42 | int type) {
43 | return axes == ViewCompat.SCROLL_AXIS_VERTICAL;
44 | }
45 |
46 | public void onNestedPreScroll(
47 | @NonNull CoordinatorLayout coordinatorLayout,
48 | @NonNull BottomNavigationView child,
49 | @NonNull View target,
50 | int dx,
51 | int dy,
52 | @NonNull int[] consumed,
53 | int type) {
54 | super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);
55 | child.setTranslationY(
56 | Math.max(0.0f, Math.min(child.getHeight(), child.getTranslationY() + dy)));
57 | }
58 |
59 | private void updateSnackbar(BottomNavigationView child, Snackbar.SnackbarLayout snackbarLayout) {
60 | if (snackbarLayout.getLayoutParams() instanceof CoordinatorLayout.LayoutParams) {
61 | android.view.ViewGroup.LayoutParams layoutParams = snackbarLayout.getLayoutParams();
62 | if (layoutParams == null) {
63 | throw new RuntimeException(
64 | "null cannot be cast to non-null type android.support.design.widget.CoordinatorLayout.LayoutParams");
65 | }
66 |
67 | CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) layoutParams;
68 | params.setAnchorId(child.getId());
69 | params.anchorGravity = Gravity.TOP;
70 | params.gravity = Gravity.TOP;
71 | snackbarLayout.setLayoutParams(params);
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/BottomNavigationFABBehavior.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.View;
6 |
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import androidx.coordinatorlayout.widget.CoordinatorLayout;
10 |
11 | import com.google.android.material.floatingactionbutton.FloatingActionButton;
12 | import com.google.android.material.snackbar.Snackbar;
13 |
14 | public final class BottomNavigationFABBehavior
15 | extends CoordinatorLayout.Behavior {
16 |
17 | public BottomNavigationFABBehavior(@Nullable Context context, @Nullable AttributeSet attrs) {
18 | super(context, attrs);
19 | }
20 |
21 | public boolean layoutDependsOn(
22 | @Nullable CoordinatorLayout parent,
23 | @NonNull FloatingActionButton child,
24 | @NonNull View dependency) {
25 | return dependency instanceof Snackbar.SnackbarLayout;
26 | }
27 |
28 | public void onDependentViewRemoved(
29 | @NonNull CoordinatorLayout parent,
30 | @NonNull FloatingActionButton child,
31 | @NonNull View dependency) {
32 | child.setTranslationY(0.0f);
33 | }
34 |
35 | public boolean onDependentViewChanged(
36 | @NonNull CoordinatorLayout parent,
37 | @NonNull FloatingActionButton child,
38 | @NonNull View dependency) {
39 | return this.updateButton(child, dependency);
40 | }
41 |
42 | private boolean updateButton(View child, View dependency) {
43 | if (dependency instanceof Snackbar.SnackbarLayout) {
44 | float oldTranslation = child.getTranslationY();
45 | float height = (float) dependency.getHeight();
46 | float newTranslation = dependency.getTranslationY() - height;
47 | child.setTranslationY(newTranslation);
48 | return oldTranslation != newTranslation;
49 | } else {
50 | return false;
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/CustomTabManager.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import androidx.appcompat.app.ActionBar;
4 | import androidx.viewpager2.widget.ViewPager2;
5 | import com.google.android.material.tabs.TabLayout;
6 | import com.google.android.material.tabs.TabLayout.Tab;
7 | import com.google.android.material.tabs.TabLayoutMediator;
8 |
9 | public class CustomTabManager {
10 |
11 | private final ActionBar actionBar;
12 |
13 | public CustomTabManager(ActionBar actionBar) {
14 | this.actionBar = actionBar;
15 | }
16 |
17 | public void bind(ViewPager2 viewPager2) {
18 | actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM);
19 | actionBar.setCustomView(R.layout.custom_toolbar);
20 | TabLayout tabLayout = actionBar.getCustomView().findViewById(R.id.tabs);
21 | new TabLayoutMediator(tabLayout, viewPager2, this::setTabItem).attach();
22 | }
23 |
24 | private void setTabItem(Tab tab, int position) {
25 | tab.setText(getPageTitle(position));
26 | }
27 |
28 | private CharSequence getPageTitle(int position) {
29 | return "Dashboard " + position;
30 | }
31 |
32 | public void unbind() {
33 | actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_TITLE);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/CustomViewPager.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.MotionEvent;
6 |
7 | import androidx.viewpager.widget.ViewPager;
8 |
9 | public class CustomViewPager extends ViewPager {
10 |
11 | private boolean enabled = false;
12 |
13 | public CustomViewPager(Context context, AttributeSet attrs) {
14 | super(context, attrs);
15 | }
16 |
17 | @Override
18 | public boolean onTouchEvent(MotionEvent event) {
19 | return this.enabled && super.onTouchEvent(event) && performClick();
20 | }
21 |
22 | @Override
23 | public boolean onInterceptTouchEvent(MotionEvent event) {
24 | return this.enabled && super.onInterceptTouchEvent(event);
25 | }
26 |
27 | @Override
28 | public boolean performClick() {
29 | return this.enabled && super.performClick();
30 | }
31 |
32 | @Override
33 | public void setEnabled(boolean enabled) {
34 | this.enabled = enabled;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/DashboardChildFragment.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.Menu;
7 | import android.view.MenuInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 | import androidx.annotation.NonNull;
12 | import androidx.annotation.Nullable;
13 | import androidx.fragment.app.Fragment;
14 |
15 | public class DashboardChildFragment extends Fragment {
16 |
17 | private static final String ARGUMENT_POSITION = "argument_position";
18 | private static final String ARGUMENT_NAME = "argument_name";
19 |
20 | public static DashboardChildFragment newInstance(int position, String name) {
21 |
22 | Bundle args = new Bundle();
23 | args.putInt(ARGUMENT_POSITION, position);
24 | args.putString(ARGUMENT_NAME, name);
25 | DashboardChildFragment fragment = new DashboardChildFragment();
26 | fragment.setArguments(args);
27 | return fragment;
28 | }
29 |
30 | @Override
31 | public void onCreate(@Nullable Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setHasOptionsMenu(true);
34 | getLifecycle().addObserver(new TimberLogger(this));
35 | }
36 |
37 | @Override
38 | public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
39 | int position = requireArguments().getInt(ARGUMENT_POSITION, -1);
40 | if (position == 1) {
41 | inflater.inflate(R.menu.delete, menu);
42 | }
43 | }
44 |
45 | @Nullable
46 | @Override
47 | public View onCreateView(
48 | @NonNull LayoutInflater inflater,
49 | @Nullable ViewGroup container,
50 | @Nullable Bundle savedInstanceState) {
51 | return inflater.inflate(R.layout.fragment_dashboard_child, container, false);
52 | }
53 |
54 | @SuppressLint("SetTextI18n")
55 | @Override
56 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
57 | super.onViewCreated(view, savedInstanceState);
58 | TextView tvDashBoard = view.findViewById(R.id.tv_dashboard);
59 | int position = requireArguments().getInt(ARGUMENT_POSITION, -1);
60 | String name = requireArguments().getString(ARGUMENT_NAME);
61 | tvDashBoard.setText(
62 | position == 0
63 | ? R.string.do_not_stop_believing
64 | : R.string.life_is_a_very_funny_proposition_after_all);
65 | tvDashBoard.append("\n");
66 | tvDashBoard.append("\n");
67 | tvDashBoard.append("\n");
68 | tvDashBoard.append(name);
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/DashboardFragment.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.Menu;
6 | import android.view.MenuInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.appcompat.app.AppCompatActivity;
12 | import androidx.fragment.app.Fragment;
13 | import androidx.viewpager2.adapter.FragmentStateAdapter;
14 | import androidx.viewpager2.widget.ViewPager2;
15 |
16 | public class DashboardFragment extends Fragment {
17 |
18 | private static final String ARG_NAME = "arg_name";
19 | private ViewPager2 viewPager;
20 | private CustomTabManager customTabManager;
21 |
22 | public static DashboardFragment newInstance(String name) {
23 | Bundle bundle = new Bundle();
24 | bundle.putString(ARG_NAME, name);
25 | DashboardFragment dashboardFragment = new DashboardFragment();
26 | dashboardFragment.setArguments(bundle);
27 | return dashboardFragment;
28 | }
29 |
30 | @Nullable
31 | @Override
32 | public View onCreateView(
33 | @NonNull LayoutInflater inflater,
34 | @Nullable ViewGroup container,
35 | @Nullable Bundle savedInstanceState) {
36 | return inflater.inflate(R.layout.fragment_dashboard, container, false);
37 | }
38 |
39 | @Override
40 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
41 | super.onViewCreated(view, savedInstanceState);
42 | viewPager = view.findViewById(R.id.view_pager2);
43 | GooglePlusFragmentPageAdapter adapter =
44 | new GooglePlusFragmentPageAdapter(this, requireArguments().getString(ARG_NAME));
45 | viewPager.setAdapter(adapter);
46 | viewPager.setOffscreenPageLimit(adapter.getItemCount() - 1);
47 | initCustomTabManager();
48 | }
49 |
50 | @Override
51 | public void onResume() {
52 | super.onResume();
53 | bindTab();
54 | }
55 |
56 | @Override
57 | public void onPause() {
58 | super.onPause();
59 | unbindTab();
60 | }
61 |
62 | private void unbindTab() {
63 | customTabManager.unbind();
64 | }
65 |
66 | private void bindTab() {
67 | customTabManager.bind(viewPager);
68 | }
69 |
70 | private void initCustomTabManager() {
71 | customTabManager =
72 | new CustomTabManager(((AppCompatActivity) requireActivity()).getSupportActionBar());
73 | }
74 |
75 | @Override
76 | public void onCreate(@Nullable Bundle savedInstanceState) {
77 | super.onCreate(savedInstanceState);
78 | setHasOptionsMenu(true);
79 | getLifecycle().addObserver(new TimberLogger(this));
80 | }
81 |
82 | @Override
83 | public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
84 | inflater.inflate(R.menu.send, menu);
85 | }
86 |
87 | private static class GooglePlusFragmentPageAdapter extends FragmentStateAdapter {
88 |
89 | private final String name;
90 |
91 | public GooglePlusFragmentPageAdapter(Fragment fragment, String name) {
92 | super(fragment);
93 | this.name = name;
94 | }
95 |
96 | @NonNull
97 | @Override
98 | public Fragment createFragment(int position) {
99 | return DashboardChildFragment.newInstance(position, name);
100 | }
101 |
102 | @Override
103 | public int getItemCount() {
104 | return 2;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/HomeFragment.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import androidx.annotation.NonNull;
8 | import androidx.annotation.Nullable;
9 | import androidx.fragment.app.Fragment;
10 | import timber.log.Timber;
11 |
12 | public class HomeFragment extends Fragment {
13 |
14 | private static final String ARG_ID = "arg_id";
15 |
16 | public static HomeFragment newInstance(int id) {
17 | Bundle bundle = new Bundle();
18 | bundle.putInt(ARG_ID, id);
19 | HomeFragment homeFragment = new HomeFragment();
20 | homeFragment.setArguments(bundle);
21 | return homeFragment;
22 | }
23 |
24 | @Override
25 | public void onCreate(@Nullable Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | getLifecycle().addObserver(new TimberLogger(this));
28 | }
29 |
30 | @Nullable
31 | @Override
32 | public View onCreateView(
33 | @NonNull LayoutInflater inflater,
34 | @Nullable ViewGroup container,
35 | @Nullable Bundle savedInstanceState) {
36 | return inflater.inflate(R.layout.fragment_home, container, false);
37 | }
38 |
39 | @Override
40 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
41 | super.onViewCreated(view, savedInstanceState);
42 | int id = requireArguments().getInt(ARG_ID);
43 | Timber.d("param as id:%s", id);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/MainActivity.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.os.Bundle;
4 | import android.view.Menu;
5 | import android.view.MenuItem;
6 | import android.view.View;
7 | import androidx.appcompat.app.ActionBarDrawerToggle;
8 | import androidx.appcompat.app.AppCompatActivity;
9 | import androidx.appcompat.widget.Toolbar;
10 | import androidx.drawerlayout.widget.DrawerLayout;
11 | import androidx.viewpager2.widget.ViewPager2;
12 | import com.google.android.material.bottomnavigation.BottomNavigationView;
13 | import com.google.android.material.navigation.NavigationView;
14 | import com.google.android.material.snackbar.Snackbar;
15 |
16 | public class MainActivity extends AppCompatActivity {
17 |
18 | private BottomNavigationView navigation;
19 | private Toolbar toolbar;
20 |
21 | @Override
22 | public boolean onCreateOptionsMenu(Menu menu) {
23 | getMenuInflater().inflate(R.menu.search, menu);
24 | return super.onCreateOptionsMenu(menu);
25 | }
26 |
27 | @Override
28 | public boolean onOptionsItemSelected(MenuItem item) {
29 | if (item.getItemId() == R.id.menu_search) {
30 | showSearch();
31 | return true;
32 | }
33 | return super.onOptionsItemSelected(item);
34 | }
35 |
36 | private void showSearch() {
37 | Snackbar.make(navigation, "Go to Search", Snackbar.LENGTH_LONG).show();
38 | }
39 |
40 | @Override
41 | protected void onCreate(Bundle savedInstanceState) {
42 | super.onCreate(savedInstanceState);
43 | setContentView(R.layout.activity_main);
44 | toolbar = findViewById(R.id.toolbar);
45 | setSupportActionBar(toolbar);
46 | ViewPager2 viewPager = findViewById(R.id.view_pager);
47 | // https://stackoverflow.com/a/55193815/4068957
48 | viewPager.setUserInputEnabled(false);
49 | AppFragmentPageAdapter adapter = new AppFragmentPageAdapter(this);
50 | viewPager.setAdapter(adapter);
51 | viewPager.setOffscreenPageLimit(adapter.getItemCount() - 1);
52 | navigation = findViewById(R.id.navigation);
53 | BottomNavItemSelectedListener listener = new BottomNavItemSelectedListener(viewPager, toolbar);
54 | navigation.setOnItemSelectedListener(listener);
55 | bindNavigationDrawer();
56 | initTitle();
57 | }
58 |
59 | private void initTitle() {
60 | toolbar.post(() -> toolbar.setTitle(navigation.getMenu().getItem(0).getTitle()));
61 | }
62 |
63 | private void bindNavigationDrawer() {
64 | DrawerLayout drawer = findViewById(R.id.drawer_layout);
65 | ActionBarDrawerToggle toggle =
66 | new ActionBarDrawerToggle(
67 | this,
68 | drawer,
69 | toolbar,
70 | R.string.navigation_drawer_open,
71 | R.string.navigation_drawer_close);
72 | drawer.addDrawerListener(toggle);
73 | toggle.syncState();
74 | NavigationView navigationView = findViewById(R.id.nav_view);
75 | SideNavItemSelectedListener listener = new SideNavItemSelectedListener(drawer, navigation);
76 | navigationView.setNavigationItemSelectedListener(listener);
77 | }
78 |
79 | public void onFabClicked(View view) {
80 | Snackbar.make(navigation, "Fab Share", Snackbar.LENGTH_SHORT).show();
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/NotificationFragment.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.os.Bundle;
4 | import android.view.LayoutInflater;
5 | import android.view.Menu;
6 | import android.view.MenuInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.fragment.app.Fragment;
12 |
13 | public class NotificationFragment extends Fragment {
14 |
15 | public static NotificationFragment newInstance() {
16 | return new NotificationFragment();
17 | }
18 |
19 | @Nullable
20 | @Override
21 | public View onCreateView(
22 | @NonNull LayoutInflater inflater,
23 | @Nullable ViewGroup container,
24 | @Nullable Bundle savedInstanceState) {
25 | return inflater.inflate(R.layout.fragment_notification, container, false);
26 | }
27 |
28 | @Override
29 | public void onCreate(@Nullable Bundle savedInstanceState) {
30 | super.onCreate(savedInstanceState);
31 | setHasOptionsMenu(true);
32 | getLifecycle().addObserver(new TimberLogger(this));
33 | }
34 |
35 | @Override
36 | public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
37 | inflater.inflate(R.menu.message, menu);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/SideNavItemSelectedListener.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import android.view.MenuItem;
4 | import androidx.annotation.NonNull;
5 | import androidx.core.view.GravityCompat;
6 | import androidx.drawerlayout.widget.DrawerLayout;
7 | import com.google.android.material.bottomnavigation.BottomNavigationView;
8 | import com.google.android.material.navigation.NavigationView;
9 | import com.google.android.material.snackbar.Snackbar;
10 |
11 | public class SideNavItemSelectedListener
12 | implements NavigationView.OnNavigationItemSelectedListener {
13 |
14 | private final DrawerLayout drawer;
15 | private final BottomNavigationView navigation;
16 |
17 | public SideNavItemSelectedListener(DrawerLayout drawer, BottomNavigationView navigation) {
18 | this.drawer = drawer;
19 | this.navigation = navigation;
20 | }
21 |
22 | @Override
23 | public boolean onNavigationItemSelected(@NonNull MenuItem item) {
24 | // Handle navigation view item clicks here.
25 | int id = item.getItemId();
26 | if (id == R.id.nav_tool) {
27 | showToolSnackBar();
28 | } else if (id == R.id.nav_share) {
29 | showShareSnackBar();
30 | } else if (id == R.id.nav_gallery) {
31 | showGallerySnackBar();
32 | } else if (id == R.id.nav_send) {
33 | showSendSnackBar();
34 | }
35 | drawer.closeDrawer(GravityCompat.START);
36 | return true;
37 | }
38 |
39 | private void showSendSnackBar() {
40 | Snackbar.make(navigation, "Send", Snackbar.LENGTH_SHORT).show();
41 | }
42 |
43 | private void showGallerySnackBar() {
44 | Snackbar.make(navigation, "Gallery", Snackbar.LENGTH_SHORT).show();
45 | }
46 |
47 | private void showToolSnackBar() {
48 | Snackbar.make(navigation, "Tool", Snackbar.LENGTH_SHORT).show();
49 | }
50 |
51 | private void showShareSnackBar() {
52 | Snackbar.make(navigation, "Share", Snackbar.LENGTH_SHORT).show();
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/io/anycopy/googleplusdemo/TimberLogger.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import androidx.lifecycle.Lifecycle.Event;
4 | import androidx.lifecycle.LifecycleObserver;
5 | import androidx.lifecycle.LifecycleOwner;
6 | import androidx.lifecycle.OnLifecycleEvent;
7 | import timber.log.Timber;
8 |
9 | public class TimberLogger implements LifecycleObserver {
10 |
11 | private final LifecycleOwner lifecycleOwner;
12 |
13 | public TimberLogger(LifecycleOwner lifecycleOwner) {
14 | this.lifecycleOwner = lifecycleOwner;
15 | }
16 |
17 | @OnLifecycleEvent(Event.ON_RESUME)
18 | public void onResume() {
19 | Timber.i("onResume:%s", lifecycleOwner.getClass().getSimpleName());
20 | }
21 |
22 | @OnLifecycleEvent(Event.ON_PAUSE)
23 | public void onPause() {
24 | Timber.i("onPause:%s", lifecycleOwner.getClass().getSimpleName());
25 | }
26 |
27 | @OnLifecycleEvent(Event.ON_START)
28 | public void onStart() {
29 | Timber.i("onStart:%s", lifecycleOwner.getClass().getSimpleName());
30 | }
31 |
32 | @OnLifecycleEvent(Event.ON_STOP)
33 | public void onStop() {
34 | Timber.i("onStop:%s", lifecycleOwner.getClass().getSimpleName());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_add_white_24dp.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_gallery.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_manage.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_send.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v21/ic_menu_share.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_delete_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_message_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_baseline_search_24.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/side_nav_bar.xml:
--------------------------------------------------------------------------------
1 |
3 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
15 |
16 |
22 |
23 |
30 |
31 |
32 |
37 |
38 |
46 |
47 |
59 |
60 |
61 |
62 |
63 |
71 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/custom_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_dashboard.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_dashboard_child.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_home.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_notification.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/nav_header_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
15 |
21 |
22 |
28 |
29 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/activity_main_drawer.xml:
--------------------------------------------------------------------------------
1 |
2 |
31 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/delete.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/message.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
13 |
14 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/search.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/send.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/snack_bar.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 | 8dp
6 | 176dp
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/values/long_string.xml:
--------------------------------------------------------------------------------
1 |
2 | BE HONEST AND TRUE\n\n\n\n
3 | BY GEORGE BIRDSEYE\n\n\n\n
4 | Be honest and true, boys!\n\n
5 | Whatever you do, boys,\n\n
6 | Let this be your motto through life.\n\n
7 | Both now and forever,\n\n
8 | Be this your endeavor,\n\n
9 | When wrong with the right is at strife.\n\n
10 | The best and the truest,\n\n
11 | Alas! are the fewest;\n\n
12 | But be one of these if you can.\n\n
13 | In duty ne’er fail; you\n\n
14 | Will find ’twill avail you,\n\n
15 | And bring its reward when a man.\n\n
16 | Don’t think life plain sailing;\n\n
17 | There’s danger of failing,\n\n
18 | Though bright seem the future to be;\n\n
19 | But honor and labor,\n\n
20 | And truth to your neighbor,\n\n
21 | Will bear you safe over life’s sea.\n\n
22 | Then up and be doing,\n\n
23 | Right only pursuing,\n\n
24 | And take your fair part in the strife.\n\n
25 | Be honest and true, boys,\n\n
26 | Whatever you do, boys,\n\n
27 | Let this be your motto through life!\n\n
28 |
29 | Old and Wise\n\n\n\n
30 | by The Alan Parsons Project\n\n\n\n
31 | As far as my eyes can see\n\n
32 | There are Shadows approaching me\n\n
33 | And to those I left behind\n\n
34 | I wanted you to Know\n\n
35 | You\'ve always shared my deepest thoughts\n\n
36 | You follow where I go\n\n
37 | And oh when I\'m old and wise\n\n
38 | Bitter words mean little to me\n\n
39 | Autumn Winds will blow right through me\n\n
40 | And someday in the mist of time\n\n
41 | When they asked me if I knew you\n\n
42 | I\'d smile and say you were a friend of mine\n\n
43 | And the sadness would be Lifted from my eyes\n\n
44 | Oh when I\'m old and wise\n\n
45 | As far as my Eyes can see\n\n
46 | There are shadows surrounding me\n\n
47 | And to those I leave behind\n\n
48 | I want you all to know\n\n
49 | You\'ve always Shared my darkest hours\n\n
50 | I\'ll miss you when I go\n\n
51 | And oh, when I\'m old and wise\n\n
52 | Heavy words that tossed and blew me\n\n
53 | Like Autumn winds that will blow right through me\n\n
54 | And someday in the mist of time\n\n
55 | When they ask you if you knew me\n\n
56 | Remember that You were a friend of mine\n\n
57 | As the final curtain falls before my eyes\n\n
58 | Oh when I\'m Old and wise\n\n
59 | As far as my eyes can see\n\n
60 |
61 |
62 | Life\'s a very funny proposition after all\n\n
63 | by George M. Cohen\n\n\n\n
64 | Did you ever sit and ponder\n\n
65 | Sit and wonder, sit and think\n\n
66 | Why we\'re here and what this life is all about?\n\n
67 | It\'s a problem that has driven\n\n
68 | Many brainy men to drink\n\n
69 | It\'s the weirdest thing they\'ve tried to figure out\n\n
70 | About a thousand different theories\n\n
71 | All the scientists can show\n\n
72 | But never yet have proved a reason why\n\n
73 | With all we\'ve thought\n\n
74 | And all we\'re taught\n\n
75 | Why all we seem to know\n\n
76 | Is we\'re born and live a while and then we die\n\n\n\n
77 |
78 | Life\'s a very funny proposition after all\n\n
79 | Imagination, jealousy, hypocrisy and all\n\n
80 | Three meals a day, a whole lot to say\n\n
81 | When you haven\'t got the coin you\'re always in the way\n\n
82 | Everybody\'s fighting as we wend our way along\n\n
83 | Every fellow claims the other fellow\'s in the wrong\n\n
84 | Hurried and worried until we\'re buried and there\'s no curtain call\n\n
85 | Life\'s a very funny proposition after all\n\n\n\n
86 |
87 | When all things are coming easy, and when luck is with a man\n\n
88 | Why then life to him is sunshine everywhere\n\n
89 | Then the fates blow rather breezy and they quite upset a plan\n\n
90 | Then he\'ll cry that life\'s a burden hard to bear\n\n
91 | Though today may be a day of smiles, tomorrow\'s still in doubt\n\n
92 | And what brings me joy, may bring you care and woe\n\n
93 | We\'re born to die, but don\'t know why, or what it\'s all about\n\n
94 | And the more we try to learn the less we know\n\n\n\n
95 |
96 | Life\'s a very funny proposition, you can bet\n\n
97 | And no one\'s ever solved the problem properly as yet\n\n
98 | Young for a day, then old and gray\n\n
99 | Like the rose that buds and blooms and fades and falls away\n\n
100 | Losing health to gain our wealth as through this dream we tour\n\n
101 | Everything\'s a guess and nothing\'s absolutely sure\n\n
102 | Battles exciting and fates we\'re fighting until the curtain falls\n\n
103 | Life\'s a very funny proposition after all\n\n
104 |
105 | Don\'t Stop Believing\n\n
106 | by Journey\n\n\n\n
107 | Just a small town girl\n\n\n\n
108 | Livin\' in a lonely world\n\n
109 | She took the midnight train\n\n
110 | Goin\' anywhere\n\n
111 | Just a city boy\n\n
112 | Born and raised in South Detroit\n\n
113 | He took the midnight train\n\n
114 | Goin\' anywhere\n\n\n\n
115 |
116 | A singer in a smokey room\n\n
117 | The smell of wine and cheap perfume\n\n
118 | For a smile they can share the night\n\n
119 | It goes on and on and on and on\n\n\n\n
120 |
121 | Strangers waiting\n\n
122 | Up and down the boulevard\n\n
123 | Their shadows searching\n\n
124 | In the night\n\n
125 | Streetlight people\n\n
126 | Livin\' just to find emotion\n\n
127 | Hidin\' somewhere in the night\n\n\n\n
128 |
129 | Workin\' hard to get my fill\n\n
130 | Everybody wants a thrill\n\n
131 | Payin\' anything to roll the dice\n\n
132 | Just one more time\n\n
133 | Some will win\n\n
134 | Some will lose\n\n
135 | Some were born to sing the blues\n\n
136 | Oh, the movie never ends\n\n
137 | It goes on and on and on and on\n\n\n\n
138 |
139 | Strangers waiting\n\n
140 | Up and down the boulevard\n\n
141 | Their shadows searching\n\n
142 | In the night\n\n
143 | Streetlight people\n\n
144 | Livin\' just to find emotion\n\n
145 | Hidin\' somewhere in the night\n\n\n\n
146 |
147 | [Instrumental interlude]
148 |
149 | Don\'t stop believin\'\n\n
150 | Hold on to that feelin\'\n\n
151 | Streetlight people\n\n
152 | Don\'t stop believin\'\n\n
153 | Hold on\n\n
154 | Streetlight people\n\n
155 | Don\'t stop believin\'\n\n
156 | Hold on to that feelin\'\n\n
157 | Streetlight people\n\n
158 | Don\'t stop believin\'\n\n
159 | Hold on to that feelin\'\n\n
160 | Streetlight people\n\n
161 | Don\'t stop believin\'\n\n
162 | Streetlight people\n\n
163 | Don\'t stop
164 |
165 |
166 |
167 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | GooglePlusDemo
3 | Home
4 | Dashboard
5 | Notifications
6 | Show
7 | Settings
8 | Open navigation drawer
9 | Close navigation drawer
10 | Search
11 | Message
12 | Send
13 | Delete
14 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/src/test/java/io/anycopy/googleplusdemo/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package io.anycopy.googleplusdemo;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.assertEquals;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 |
14 | @Test
15 | public void addition_isCorrect() throws Exception {
16 | assertEquals(4, 2 + 2);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | buildscript {
2 | repositories {
3 | google()
4 | mavenCentral()
5 | //noinspection JcenterRepositoryObsolete
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:4.2.2'
10 | }
11 |
12 | }
13 |
14 | plugins {
15 | id "com.github.sherter.google-java-format" version "0.8"
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | mavenCentral()
22 | //noinspection JcenterRepositoryObsolete
23 | jcenter()
24 | }
25 | }
26 |
27 | subprojects { project ->
28 | project.tasks.withType(JavaCompile) {
29 | dependsOn(installGitHooks)
30 | }
31 |
32 | repositories {
33 | google()
34 | mavenCentral()
35 | //noinspection JcenterRepositoryObsolete
36 | jcenter() }
37 |
38 | }
39 |
40 | googleJavaFormat {
41 | toolVersion = "1.7"
42 | }
43 |
44 | ////////////////////////////////////////////////////////////////////////
45 | //
46 | // Google Java Format pre-commit hook installation
47 | ////////////////////////////////////////////////////////////////////////
48 |
49 |
50 | tasks.register('installGitHooks', Copy) {
51 | from(file('config/hooks/pre-commit-stub')) {
52 | rename 'pre-commit-stub', 'pre-commit'
53 | }
54 | into file('.git/hooks')
55 | fileMode 0777
56 | }
57 |
--------------------------------------------------------------------------------
/config/hooks/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | set -e
4 |
5 | REPO_ROOT_DIR="$(git rev-parse --show-toplevel)"
6 |
7 | files=$((git diff --cached --name-only --diff-filter=ACMR | grep -Ei "\.java$") || true)
8 | if [ ! -z "${files}" ]; then
9 | comma_files=$(echo "$files" | paste -s -d "," -)
10 | "${REPO_ROOT_DIR}/gradlew" goJF -DgoogleJavaFormat.include="$comma_files" &>/dev/null
11 | git add $(echo "$files" | paste -s -d " " -)
12 | fi
13 |
--------------------------------------------------------------------------------
/config/hooks/pre-commit-stub:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # stub pre-commit hook
4 | # just a runner for the real pre-commit script
5 | # if script cannot be found, exit without error
6 | # (to not block local commits)
7 |
8 | set -e
9 |
10 | REPO_ROOT_DIR="$(git rev-parse --show-toplevel)"
11 | PRE_COMMIT_SCRIPT="${REPO_ROOT_DIR}/config/hooks/pre-commit"
12 |
13 | if [ -f $PRE_COMMIT_SCRIPT ]; then
14 | source $PRE_COMMIT_SCRIPT
15 | fi
16 |
--------------------------------------------------------------------------------
/google_plus_demo.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/google_plus_demo.gif
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 | android.useAndroidX=true
14 | android.enableJetifier=true
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
19 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TonyTangAndroid/GooglePlusDemo/7db626b977c59ea233e4aaee9256e159e9134db4/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------