├── .circleci
└── config.yml
├── .github
└── workflows
│ └── android.yml
├── .gitignore
├── .idea
├── assetWizardSettings.xml
├── codeStyles
│ ├── Project.xml
│ └── codeStyleConfig.xml
├── copyright
│ ├── apache_license.xml
│ └── profiles_settings.xml
├── encodings.xml
├── jarRepositories.xml
├── misc.xml
├── modules.xml
└── vcs.xml
├── CONTRIBUTING.md
├── LICENSE
├── PRIVACY.md
├── README.md
├── app
├── .gitignore
├── build.gradle
├── google-services.json
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── hossainkhan
│ │ └── android
│ │ └── demo
│ │ └── ExampleInstrumentedTest.kt
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── hossainkhan
│ │ │ └── android
│ │ │ └── demo
│ │ │ ├── base
│ │ │ ├── AppConfig.kt
│ │ │ └── DemoApplication.kt
│ │ │ ├── data
│ │ │ ├── AppDataStore.kt
│ │ │ ├── FirestoreDateFormatter.kt
│ │ │ ├── LayoutDataStore.kt
│ │ │ ├── LayoutInformation.kt
│ │ │ ├── ResourceInfo.kt
│ │ │ └── ResourceResult.kt
│ │ │ ├── di
│ │ │ ├── ActivityBindingModule.kt
│ │ │ ├── ActivityScope.kt
│ │ │ ├── ApplicationModule.kt
│ │ │ ├── DataStoreModule.kt
│ │ │ ├── DemoApplicationComponent.kt
│ │ │ ├── LayoutBrowseActivityModule.kt
│ │ │ ├── LayoutBrowseSubcomponent.kt
│ │ │ ├── ViewModelKey.kt
│ │ │ └── ViewModelModule.kt
│ │ │ ├── ui
│ │ │ ├── browse
│ │ │ │ ├── BrowseResult.kt
│ │ │ │ ├── LayoutBrowseActivity.kt
│ │ │ │ ├── LayoutBrowseAdapter.kt
│ │ │ │ └── LayoutBrowseViewModel.kt
│ │ │ ├── common
│ │ │ │ ├── DataBoundListAdapter.kt
│ │ │ │ ├── DataBoundViewHolder.kt
│ │ │ │ └── LiveEvent.kt
│ │ │ ├── dialog
│ │ │ │ └── LayoutInfoDialog.kt
│ │ │ ├── functionaldemo
│ │ │ │ ├── MovieDetailsPreviewActivity.kt
│ │ │ │ ├── MoviePosterAdapter.kt
│ │ │ │ ├── PinCodeEntryActivity.kt
│ │ │ │ └── TedTalkPlaybackActivity.kt
│ │ │ ├── layoutpreview
│ │ │ │ ├── LayoutChainStyleActivity.kt
│ │ │ │ ├── LayoutDimensionMinMaxActivity.kt
│ │ │ │ ├── LayoutGuidelineBarrierActivity.kt
│ │ │ │ ├── LayoutGuidelineGroupActivity.kt
│ │ │ │ ├── LayoutInfoViewModel.kt
│ │ │ │ ├── LayoutPreviewBaseActivity.kt
│ │ │ │ └── LayoutVisibilityGoneActivity.kt
│ │ │ └── resource
│ │ │ │ ├── LearningResourceActivity.kt
│ │ │ │ ├── LearningResourceViewModel.kt
│ │ │ │ └── ResourceListAdapter.kt
│ │ │ └── viewmodel
│ │ │ └── ViewModelProviderFactory.kt
│ └── res
│ │ ├── drawable-xxxhdpi
│ │ ├── poster_angry_birds.webp
│ │ ├── poster_dragon3.webp
│ │ ├── poster_finding_nemo.webp
│ │ ├── poster_i1.webp
│ │ ├── poster_i2.webp
│ │ ├── poster_lego_batman.webp
│ │ ├── poster_lego_movie.webp
│ │ ├── poster_spider_verse_detail.webp
│ │ ├── poster_wreckit_ralph.webp
│ │ ├── spider_verse_background.webp
│ │ ├── spider_verse_poster.webp
│ │ ├── thumb_roger_hanlon.png
│ │ └── thumb_ted_talk.webp
│ │ ├── drawable
│ │ ├── circle.xml
│ │ ├── ic_baseline_4k_18dp.xml
│ │ ├── ic_book_128dp.xml
│ │ ├── ic_circle_overlay.xml
│ │ ├── ic_dotted_line_overlay.xml
│ │ ├── ic_forward_30_black_42dp.xml
│ │ ├── ic_github_logo.xml
│ │ ├── ic_grid_overlay.xml
│ │ ├── ic_image_black_140dp.xml
│ │ ├── ic_info_outline_black_24dp.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── ic_launcher_foreground.xml
│ │ ├── ic_library_books_black_42dp.xml
│ │ ├── ic_ondemand_video_black_24dp.xml
│ │ ├── ic_outline_backspace_24.xml
│ │ ├── ic_outline_check_circle_outline_24.xml
│ │ ├── ic_people_black_18dp.xml
│ │ ├── ic_pin_entry_preview.xml
│ │ ├── ic_pin_filled.xml
│ │ ├── ic_pin_outline.xml
│ │ ├── ic_play_arrow_black_42dp.xml
│ │ ├── ic_play_circle_filled_black_42dp.xml
│ │ ├── ic_play_circle_outline_black_24dp.xml
│ │ ├── ic_playlist_add_black_24dp.xml
│ │ ├── ic_replay_30_black_42dp.xml
│ │ ├── ic_skip_next_black_42dp.xml
│ │ ├── ic_skip_previous_black_42dp.xml
│ │ ├── ic_star_black_18dp.xml
│ │ ├── ic_ted_talks_logo.xml
│ │ ├── ic_thumb_down_black_24dp.xml
│ │ ├── ic_thumb_up_black_24dp.xml
│ │ ├── thumb_chain_style.xml
│ │ ├── thumb_dimension_min_max.xml
│ │ ├── thumb_dimension_percentage.xml
│ │ ├── thumb_dimension_ratio.xml
│ │ ├── thumb_positioning_bias.xml
│ │ ├── thumb_positioning_center.xml
│ │ ├── thumb_positioning_circular.xml
│ │ ├── thumb_positioning_top_left.xml
│ │ ├── thumb_virtual_helper_barrier.xml
│ │ ├── thumb_virtual_helper_group.xml
│ │ ├── thumb_virtual_helper_guideline.xml
│ │ └── thumb_visibility_behaviour.xml
│ │ ├── layout
│ │ ├── .README.md
│ │ ├── activity_learning_resource.xml
│ │ ├── activity_main.xml
│ │ ├── demo_movie_details.xml
│ │ ├── demo_pin_code_entry.xml
│ │ ├── demo_ted_talk_playback.xml
│ │ ├── dialog_layout_info_sheet.xml
│ │ ├── include_layout_chain_style.xml
│ │ ├── include_layout_positioning_bias.xml
│ │ ├── include_layout_positioning_circle_overlay.xml
│ │ ├── list_item_layout_preview.xml
│ │ ├── list_item_poster.xml
│ │ ├── list_item_resource_tech_talk.xml
│ │ ├── preview_chain_style_main.xml
│ │ ├── preview_chain_weighted.xml
│ │ ├── preview_dimension_min_max.xml
│ │ ├── preview_dimension_percent.xml
│ │ ├── preview_dimension_ratio.xml
│ │ ├── preview_positioning_bias.xml
│ │ ├── preview_positioning_centered.xml
│ │ ├── preview_positioning_circular.xml
│ │ ├── preview_positioning_top_left.xml
│ │ ├── preview_virtual_helper_barrier.xml
│ │ ├── preview_virtual_helper_group.xml
│ │ ├── preview_virtual_helper_guideline.xml
│ │ └── preview_visibility_gone.xml
│ │ ├── menu
│ │ ├── menu_layout_browse.xml
│ │ └── menu_layout_positioning.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-land
│ │ └── dimens.xml
│ │ ├── values-sw760dp-land
│ │ └── dimens.xml
│ │ ├── values-sw760dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── colors.xml
│ │ ├── colors_material_design.xml
│ │ ├── dimens.xml
│ │ ├── ic_launcher_background.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── hossainkhan
│ └── android
│ └── demo
│ ├── data
│ ├── LayoutDataStoreTest.kt
│ └── ResourceInfoTest.kt
│ └── ui
│ ├── browse
│ ├── LayoutBrowseViewModelTest.kt
│ └── TestLifecycleOwner.kt
│ └── layoutpreview
│ └── LayoutInfoViewModelTest.kt
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── resources
├── documents
│ └── ConstraintLayout_Documentation_Snapshot.pdf
├── google-play
│ ├── Constraint Layout - Google Play Banner.svg
│ ├── ConstraintLayout-banner.png
│ ├── ic_launcher-web.png
│ └── screenshots
│ │ ├── phone-6inch
│ │ └── phone_04_ted.png
│ │ └── tablet-10inch
│ │ ├── tablet_01-2.png
│ │ ├── tablet_01.png
│ │ ├── tablet_02.png
│ │ └── tablet_03.png
├── raw-screenshots
│ ├── device-2019-06-01-234353.png
│ ├── device-2019-06-01-234602-small.png
│ ├── device-2019-06-01-234602.png
│ ├── device-2019-06-06-190330.png
│ ├── device-2020-07-15-205904.png
│ ├── device-2020-07-15-205931.png
│ ├── device-2020-07-15-205948.png
│ ├── device-2020-07-15-210018.png
│ ├── device-2020-07-15-210033.png
│ ├── device-2020-07-15-210105.png
│ ├── device-2020-07-15-210133.png
│ ├── device-2020-07-15-210211.png
│ └── device-nexus-9-resources.png
└── vector
│ ├── README.md
│ ├── grid_overlay.svg
│ ├── ic_chain_style.svg
│ ├── ic_dimension_min_max.svg
│ ├── ic_dimension_percentage.svg
│ ├── ic_dimension_ratio.svg
│ ├── ic_positioning_bias.svg
│ ├── ic_positioning_center.svg
│ ├── ic_positioning_circular.svg
│ ├── ic_positioning_top_left.svg
│ ├── ic_virtual_helper_barrier.svg
│ ├── ic_virtual_helper_group.svg
│ ├── ic_virtual_helper_guideline.svg
│ └── ic_visibility_behaviour.svg
└── settings.gradle
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2.1
2 |
3 | # https://circleci.com/docs/2.0/language-android/
4 | orbs:
5 | android: circleci/android@0.2.0
6 |
7 | jobs:
8 | build:
9 | executor: android/android
10 |
11 | steps:
12 | - checkout
13 | - run:
14 | command: ./gradlew build
15 | - run:
16 | name: Run Tests
17 | command: ./gradlew lint test
18 | - store_artifacts:
19 | # Stores mobile apk for local testing
20 | path: app/build/outputs/apk
21 | destination: mobile-apk
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on: [push]
4 |
5 | jobs:
6 | build:
7 |
8 | runs-on: ubuntu-latest
9 |
10 | steps:
11 | - uses: actions/checkout@v1
12 | - name: set up JDK 1.8
13 | uses: actions/setup-java@v1
14 | with:
15 | java-version: 1.8
16 | - name: Build with Gradle
17 | run: ./gradlew assembleDebug
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | # Files for the ART/Dalvik VM
6 | *.dex
7 |
8 | # Java class files
9 | *.class
10 |
11 | # Generated files
12 | bin/
13 | gen/
14 | out/
15 |
16 | # Gradle files
17 | .gradle/
18 | build/
19 |
20 | # Local configuration file (sdk path, etc)
21 | local.properties
22 |
23 | # Proguard folder generated by Eclipse
24 | proguard/
25 |
26 | # Log Files
27 | *.log
28 |
29 | # Android Studio Navigation editor temp files
30 | .navigation/
31 |
32 | # Android Studio captures folder
33 | captures/
34 |
35 | # Intellij
36 | *.iml
37 | .idea/workspace.xml
38 | .idea/tasks.xml
39 | .idea/gradle.xml
40 | .idea/dictionaries
41 | .idea/libraries
42 |
43 | # Keystore files
44 | *.jks
45 |
46 | # External native build folder generated in Android Studio 2.2 and later
47 | .externalNativeBuild
48 |
49 | # Google Services (e.g. APIs or Firebase)
50 | google-services.json
51 |
52 | # Freeline
53 | freeline.py
54 | freeline/
55 | freeline_project_description.json
56 | output.json
57 | build_file_checksums.ser
58 | .DS_Store
59 |
--------------------------------------------------------------------------------
/.idea/assetWizardSettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
51 |
52 |
--------------------------------------------------------------------------------
/.idea/codeStyles/codeStyleConfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/copyright/apache_license.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | Contribution Guideline
2 | =====================
3 |
4 | You are more than welcome to enhance, fix any demo you see in the app. A good way to start is look into existing [issues](https://github.com/amardeshbd/android-constraint-layout-cheatsheet/issues) and see
5 | if any of them interests you.
6 |
7 | Development Guide
8 | ----------------------
9 | It is important to keep consistency in the project. Here are some of the key things you need to keep in mind:
10 |
11 | * Follow existing app architecture for previewing demo
12 | * Use `LayoutPreviewBaseActivity` if the demo does not need special user interaction
13 | * or, Create subclass of `LayoutPreviewBaseActivity` with user interaction specific binding. See `LayoutVisibilityGoneActivity` as an example.
14 | * Follow existing resource naming convention. See [README](https://github.com/amardeshbd/android-constraint-layout-cheatsheet/blob/master/app/src/main/res/layout/.README.md)
15 | * Create vector assets and save it to [raw resources](https://github.com/amardeshbd/android-constraint-layout-cheatsheet/tree/master/resources/vector) for later use. See [README](https://github.com/amardeshbd/android-constraint-layout-cheatsheet/blob/master/resources/vector/README.md) for example resource and how to create new resource.
16 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/google-services.json:
--------------------------------------------------------------------------------
1 | {
2 | "project_info": {
3 | "project_number": "98405830882",
4 | "firebase_url": "https://constraintlayout-demo.firebaseio.com",
5 | "project_id": "constraintlayout-demo",
6 | "storage_bucket": "constraintlayout-demo.appspot.com"
7 | },
8 | "client": [
9 | {
10 | "client_info": {
11 | "mobilesdk_app_id": "1:98405830882:android:8d24bba2add2a5f0",
12 | "android_client_info": {
13 | "package_name": "com.hossainkhan.android.constraintlayout"
14 | }
15 | },
16 | "oauth_client": [
17 | {
18 | "client_id": "98405830882-mm815s1f4l9cpjh59rk02hchs4cp60kg.apps.googleusercontent.com",
19 | "client_type": 3
20 | }
21 | ],
22 | "api_key": [
23 | {
24 | "current_key": "AIzaSyDdPaT1FWfc8jxPg0uUsxlvq798YYy1FQU"
25 | }
26 | ],
27 | "services": {
28 | "analytics_service": {
29 | "status": 1
30 | },
31 | "appinvite_service": {
32 | "status": 1,
33 | "other_platform_oauth_client": []
34 | },
35 | "ads_service": {
36 | "status": 2
37 | }
38 | }
39 | }
40 | ],
41 | "configuration_version": "1"
42 | }
--------------------------------------------------------------------------------
/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/com/hossainkhan/android/demo/ExampleInstrumentedTest.kt:
--------------------------------------------------------------------------------
1 | package com.hossainkhan.android.demo
2 |
3 | import androidx.test.InstrumentationRegistry
4 | import androidx.test.runner.AndroidJUnit4
5 |
6 | import org.junit.Test
7 | import org.junit.runner.RunWith
8 |
9 | import org.junit.Assert.*
10 |
11 | /**
12 | * Instrumented test, which will execute on an Android device.
13 | *
14 | * See [testing documentation](http://d.android.com/tools/testing).
15 | */
16 | @RunWith(AndroidJUnit4::class)
17 | class ExampleInstrumentedTest {
18 | @Test
19 | fun useAppContext() {
20 | // Context of the app under test.
21 | val appContext = InstrumentationRegistry.getTargetContext()
22 | assertEquals("com.hossainkhan.android.demo", appContext.packageName)
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
25 |
28 |
31 |
34 |
37 |
40 |
43 |
46 |
49 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/base/AppConfig.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.base
18 |
19 | /**
20 | * Application configurations.
21 | */
22 | object AppConfig {
23 | const val GITHUB_BASE_URL = "https://github.com/amardeshbd/android-constraint-layout-cheatsheet"
24 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/base/DemoApplication.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.base
18 |
19 | import android.app.Activity
20 | import android.app.Application
21 | import com.hossainkhan.android.demo.BuildConfig
22 | import com.hossainkhan.android.demo.di.DaggerDemoApplicationComponent
23 | import dagger.android.AndroidInjector
24 | import dagger.android.DispatchingAndroidInjector
25 | import dagger.android.HasActivityInjector
26 | import timber.log.Timber
27 | import javax.inject.Inject
28 |
29 |
30 | class DemoApplication : Application(), HasActivityInjector {
31 | @Inject
32 | lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector
33 |
34 | override fun onCreate() {
35 | super.onCreate()
36 |
37 | // Prepares dagger
38 | DaggerDemoApplicationComponent.builder()
39 | .application(this)
40 | .build()
41 | .inject(this)
42 |
43 | if (BuildConfig.DEBUG) {
44 | Timber.plant(Timber.DebugTree())
45 | }
46 | }
47 |
48 | override fun activityInjector(): AndroidInjector {
49 | return dispatchingAndroidInjector
50 | }
51 |
52 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/data/AppDataStore.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.data
18 |
19 | import android.content.SharedPreferences
20 | import javax.inject.Inject
21 |
22 | /**
23 | * Application wide data storage and preferences backed by [SharedPreferences].
24 | */
25 | class AppDataStore @Inject constructor(
26 | private val preferences: SharedPreferences,
27 | val layoutStore: LayoutDataStore) {
28 |
29 | private companion object {
30 | private const val PREF_KEY_IS_FIRST_TIME_USER = "KEY_IS_FIRST_TIME_USER"
31 | }
32 |
33 | fun isFirstTime(): Boolean {
34 | return preferences.getBoolean(PREF_KEY_IS_FIRST_TIME_USER, true)
35 | }
36 |
37 | fun updateFirstTimeUser(isFirstTime: Boolean) {
38 | preferences.edit().putBoolean(PREF_KEY_IS_FIRST_TIME_USER, isFirstTime).apply()
39 | }
40 |
41 | /**
42 | * Checks if layout information should be shown to user, and updates the flag if it should be shown.
43 | *
44 | * @return `true`, if it's first time being checked, else `false`
45 | */
46 | fun shouldshowLayoutInformation(layoutId: Int): Boolean {
47 | val layoutPreferenceKey = layoutStore.getLayoutUrl(layoutId)
48 | val shouldShow = preferences.getBoolean(layoutPreferenceKey, true)
49 | if (shouldShow) {
50 | preferences.edit().putBoolean(layoutPreferenceKey, false).apply()
51 | }
52 | return shouldShow
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/data/FirestoreDateFormatter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.data
18 |
19 | import com.google.firebase.Timestamp
20 | import java.text.SimpleDateFormat
21 | import java.util.Date
22 | import java.util.Locale
23 |
24 |
25 | object FirestoreDateFormatter {
26 | fun date(timestamp: Timestamp): String {
27 | val sfd = SimpleDateFormat("EEEE, MMMM d", Locale.CANADA)
28 | return sfd.format(timestamp.toDate())
29 | }
30 |
31 | fun date(date: Date): String {
32 | val sfd = SimpleDateFormat("MMMM d, yyyy", Locale.CANADA)
33 | return sfd.format(date)
34 | }
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/data/LayoutInformation.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.data
18 |
19 | import androidx.annotation.DrawableRes
20 | import androidx.annotation.LayoutRes
21 |
22 | /**
23 | * A simple data class containing layout resource ID and it's respective description.
24 | */
25 | data class LayoutInformation(
26 | @LayoutRes
27 | val layoutResourceId: Int,
28 | @DrawableRes
29 | val thumbnailResourceId: Int,
30 | val title: CharSequence,
31 | val description: CharSequence
32 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/data/ResourceInfo.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.data
18 |
19 | import android.net.Uri
20 | import com.google.firebase.Timestamp
21 | import java.util.Date
22 |
23 |
24 | /**
25 | * External resource info like Youtube video or technical articles online.
26 | *
27 | * Example:
28 | * - author: Nicolas Roard & John Hoford
29 | * - event: Google I/O'19
30 | * - publish_date: 9 May 2019
31 | * - summary: Learn the capabilities of ConstraintLayout
32 | * - title: What's New in ConstraintLayout
33 | * - type: techtalk
34 | * - url: https://www.youtube.com/watch?v=29gLA90m6Gk
35 | */
36 | data class ResourceInfo(
37 | var author: String = "",
38 | var summary: String = "",
39 | var title: String = "",
40 | var event: String = "",
41 | var url: String = "",
42 | var publish_date: Timestamp? = null,
43 | /**
44 | * Possible values:
45 | * "techarticle", "techtalk"
46 | */
47 | var type: String = "techtalk"
48 | ) {
49 | val formattedDate: String
50 | get() {
51 | val date = publish_date?.toDate() ?: Date()
52 | return FirestoreDateFormatter.date(date)
53 | }
54 |
55 | val isYouTubeUrl: Boolean
56 | get() = url.contains("youtube.com/watch?v=", ignoreCase = true)
57 |
58 | /**
59 | * Provides [Uri] for directly invoking youtube app via Android Intent.
60 | * @throws IllegalStateException if the URL is not for youtube. Check [isYouTubeUrl] first.
61 | */
62 | val youtubeIntentUri: String
63 | get() = if (isYouTubeUrl) ("vnd.youtube:" + url.split("=")[1]) else throw IllegalStateException("Not a YouTube URL.")
64 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/data/ResourceResult.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.data
18 |
19 |
20 | /**
21 | * A class to represent external resource request with data or error on fail.
22 | */
23 | class ResourceResult(
24 | val resources: List = emptyList(),
25 | val error: Exception? = null
26 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/ActivityScope.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import javax.inject.Scope
20 |
21 | @Scope
22 | @Retention(AnnotationRetention.RUNTIME)
23 | annotation class ActivityScope
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/ApplicationModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import android.app.Application
20 | import android.content.Context
21 | import dagger.Binds
22 | import dagger.Module
23 |
24 | /**
25 | * This is a Dagger module. We use this to bind our Application class as a Context in
26 | * the [DemoApplicationComponent] By using Dagger Android we do not need to pass
27 | * our Application instance to any module, we simply need to expose our Application as Context.
28 | * One of the advantages of Dagger.Android is that your
29 | * Application & Activities are provided into your graph for you.
30 | *
31 | * @see DemoApplicationComponent
32 | */
33 | @Module(includes = [ViewModelModule::class])
34 | abstract class ApplicationModule {
35 | //expose Application as an injectable context
36 | @Binds
37 | internal abstract fun bindContext(application: Application): Context
38 |
39 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/DataStoreModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import android.content.Context
20 | import android.content.SharedPreferences
21 | import android.content.res.Resources
22 | import com.google.firebase.firestore.FirebaseFirestore
23 | import dagger.Module
24 | import dagger.Provides
25 |
26 | @Module
27 | class DataStoreModule {
28 | @Provides
29 | internal fun provideSharedPreferences(context: Context): SharedPreferences {
30 | return context.getSharedPreferences("app_preferences", Context.MODE_PRIVATE)
31 | }
32 |
33 | @Provides
34 | internal fun provideAndroidResoures(context: Context): Resources {
35 | return context.resources
36 | }
37 |
38 | @Provides
39 | internal fun provideFirestore(context: Context): FirebaseFirestore {
40 | return FirebaseFirestore.getInstance()
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/DemoApplicationComponent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import android.app.Application
20 | import com.hossainkhan.android.demo.base.DemoApplication
21 | import dagger.BindsInstance
22 | import dagger.Component
23 | import javax.inject.Singleton
24 |
25 | @Singleton
26 | @Component(modules = arrayOf(
27 | ApplicationModule::class,
28 | ActivityBindingModule::class,
29 | DataStoreModule::class,
30 | LayoutBrowseActivityModule::class))
31 | interface DemoApplicationComponent {
32 | fun inject(app: DemoApplication)
33 |
34 | // Gives us syntactic sugar. we can then do DaggerAppComponent.builder().application(this).build().inject(this);
35 | // never having to instantiate any modules or say which module we are passing the application to.
36 | // Application will just be provided into our app graph now.
37 | @Component.Builder
38 | interface Builder {
39 | @BindsInstance
40 | fun application(application: Application): DemoApplicationComponent.Builder
41 |
42 | fun build(): DemoApplicationComponent
43 | }
44 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/LayoutBrowseActivityModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import android.app.Activity
20 | import com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity
21 | import dagger.Binds
22 | import dagger.Module
23 | import dagger.android.ActivityKey
24 | import dagger.android.AndroidInjector
25 | import dagger.multibindings.IntoMap
26 |
27 | @Module(subcomponents = [LayoutBrowseSubcomponent::class])
28 | abstract class LayoutBrowseActivityModule {
29 |
30 | @Binds
31 | @IntoMap
32 | @ActivityKey(LayoutBrowseActivity::class)
33 | abstract fun bindMainActivityInjectorFactory(
34 | builder: LayoutBrowseSubcomponent.Builder): AndroidInjector.Factory
35 |
36 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/LayoutBrowseSubcomponent.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2018 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import com.hossainkhan.android.demo.ui.browse.LayoutBrowseActivity
20 | import dagger.Subcomponent
21 | import dagger.android.AndroidInjector
22 |
23 | @Subcomponent
24 | interface LayoutBrowseSubcomponent : AndroidInjector {
25 | @Subcomponent.Builder
26 | abstract class Builder : AndroidInjector.Builder()
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/ViewModelKey.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import androidx.lifecycle.ViewModel
20 | import dagger.MapKey
21 | import kotlin.reflect.KClass
22 |
23 | /**
24 | * See https://dagger.dev/multibindings.html
25 | */
26 | @MustBeDocumented
27 | @Target(
28 | AnnotationTarget.FUNCTION,
29 | AnnotationTarget.PROPERTY_GETTER,
30 | AnnotationTarget.PROPERTY_SETTER
31 | )
32 | @Retention(AnnotationRetention.RUNTIME)
33 | @MapKey
34 | annotation class ViewModelKey(val value: KClass)
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/di/ViewModelModule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.di
18 |
19 | import androidx.lifecycle.ViewModel
20 | import androidx.lifecycle.ViewModelProvider
21 | import com.hossainkhan.android.demo.ui.browse.LayoutBrowseViewModel
22 | import com.hossainkhan.android.demo.ui.layoutpreview.LayoutInfoViewModel
23 | import com.hossainkhan.android.demo.ui.resource.LearningResourceViewModel
24 | import com.hossainkhan.android.demo.viewmodel.ViewModelProviderFactory
25 | import dagger.Binds
26 | import dagger.Module
27 | import dagger.multibindings.IntoMap
28 |
29 | /**
30 | * Uses dagger multi-binding to provide [ViewModel] instances used in the app.
31 | *
32 | * @see Multibindings
33 | */
34 | @Suppress("unused")
35 | @Module
36 | abstract class ViewModelModule {
37 | @Binds
38 | @IntoMap
39 | @ViewModelKey(LayoutBrowseViewModel::class)
40 | abstract fun bindLayoutBrowserViewModel(viewModel: LayoutBrowseViewModel): ViewModel
41 |
42 | @Binds
43 | @IntoMap
44 | @ViewModelKey(LayoutInfoViewModel::class)
45 | abstract fun bindLayoutInfoViewModel(viewModel: LayoutInfoViewModel): ViewModel
46 |
47 | @Binds
48 | @IntoMap
49 | @ViewModelKey(LearningResourceViewModel::class)
50 | abstract fun bindResourceViewModel(viewModel: LearningResourceViewModel): ViewModel
51 |
52 | @Binds
53 | abstract fun bindViewModelFactory(factory: ViewModelProviderFactory): ViewModelProvider.Factory
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/browse/BrowseResult.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.browse
18 |
19 | class BrowseResult(
20 | val clazz: Class? = null,
21 | val layoutResId: Int? = null
22 | )
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/common/DataBoundViewHolder.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.common
18 |
19 | import androidx.databinding.ViewDataBinding
20 | import androidx.recyclerview.widget.RecyclerView
21 |
22 | /**
23 | * A generic ViewHolder that works with a [ViewDataBinding].
24 | * @param The type of the ViewDataBinding.
25 | */
26 | class DataBoundViewHolder constructor(
27 | val binding: T
28 | ) : RecyclerView.ViewHolder(binding.root)
29 |
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/functionaldemo/MoviePosterAdapter.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.functionaldemo
18 |
19 | import android.view.LayoutInflater
20 | import android.view.ViewGroup
21 | import android.widget.ImageView
22 | import androidx.recyclerview.widget.RecyclerView
23 | import com.hossainkhan.android.demo.R
24 |
25 | /**
26 | * A simple adapter container movie poster images.
27 | */
28 | class MoviePosterAdapter : RecyclerView.Adapter() {
29 | private val posterImageResourceIds = listOf(
30 | R.drawable.poster_lego_batman,
31 | R.drawable.poster_i2,
32 | R.drawable.poster_angry_birds,
33 | R.drawable.poster_lego_movie,
34 | R.drawable.poster_wreckit_ralph,
35 | R.drawable.poster_dragon3,
36 | R.drawable.poster_i1,
37 | R.drawable.poster_finding_nemo
38 | )
39 |
40 | override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PosterViewHolder {
41 | // create a new view
42 | val posterView = LayoutInflater.from(parent.context)
43 | .inflate(R.layout.list_item_poster, parent, false) as ImageView
44 |
45 | return PosterViewHolder(posterView)
46 | }
47 |
48 | override fun getItemCount(): Int {
49 | return posterImageResourceIds.size
50 | }
51 |
52 | override fun onBindViewHolder(holder: PosterViewHolder, position: Int) {
53 | holder.posterView.setImageResource(posterImageResourceIds[position])
54 | }
55 |
56 | // Provide a reference to the views for each data item
57 | class PosterViewHolder(val posterView: ImageView) : RecyclerView.ViewHolder(posterView)
58 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/functionaldemo/PinCodeEntryActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2020 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.functionaldemo
18 |
19 | import com.hossainkhan.android.demo.ui.layoutpreview.LayoutPreviewBaseActivity
20 |
21 | class PinCodeEntryActivity : LayoutPreviewBaseActivity() {
22 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/functionaldemo/TedTalkPlaybackActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.functionaldemo
18 |
19 | import android.os.Bundle
20 | import android.view.View
21 | import android.widget.ImageButton
22 | import android.widget.Toast
23 | import com.hossainkhan.android.demo.R
24 | import com.hossainkhan.android.demo.ui.layoutpreview.LayoutPreviewBaseActivity
25 |
26 | class TedTalkPlaybackActivity : LayoutPreviewBaseActivity() {
27 | private val generalClickListener = View.OnClickListener { view ->
28 | Toast.makeText(view.context, "You tapped on ${view}", Toast.LENGTH_SHORT).show()
29 | }
30 |
31 | override fun onCreate(savedInstanceState: Bundle?) {
32 | super.onCreate(savedInstanceState)
33 |
34 | // Apply generic toast listener to touchable views so that user gets feedback when they tap it
35 | applyToastListener(
36 | findViewById(R.id.action_prev_track),
37 | findViewById(R.id.action_rewind15),
38 | findViewById(R.id.action_play_pause),
39 | findViewById(R.id.action_forward15),
40 | findViewById(R.id.action_next_track)
41 | )
42 | }
43 |
44 | private fun applyToastListener(vararg views: View) {
45 | views.forEach {
46 | it.setOnClickListener(generalClickListener)
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/hossainkhan/android/demo/ui/layoutpreview/LayoutDimensionMinMaxActivity.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2019 Hossain Khan
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.hossainkhan.android.demo.ui.layoutpreview
18 |
19 | import android.os.Bundle
20 | import android.widget.Button
21 | import android.widget.TextView
22 | import com.hossainkhan.android.demo.R
23 |
24 | /**
25 | * Activity showcasing how virtual guideline group containing multiple views and how it can be changed.
26 | *
27 | * See https://developer.android.com/reference/android/support/constraint/Barrier
28 | */
29 | class LayoutDimensionMinMaxActivity : LayoutPreviewBaseActivity() {
30 |
31 | override fun onCreate(savedInstanceState: Bundle?) {
32 | super.onCreate(savedInstanceState)
33 |
34 | // Setup additional view that is only available in this screen.
35 | val toggleButton = findViewById