├── .gitignore ├── LICENSE ├── LICENSE-MergeRecyclerAdapter ├── README.md ├── build.gradle ├── example ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ ├── assets │ │ └── http_testdata │ │ │ └── GET_users_cattaka_repos │ └── java │ │ └── net │ │ └── cattaka │ │ └── android │ │ └── snippets │ │ └── example │ │ ├── GitHubReposActivityTest.java │ │ └── test │ │ ├── AssetsDispatcher.java │ │ ├── IsolateEnvRule.java │ │ └── TestMyModule.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── net │ │ │ └── cattaka │ │ │ └── android │ │ │ └── snippets │ │ │ └── example │ │ │ ├── AnimateConstraintLayoutActivity.java │ │ │ ├── AppBarLayoutExample1Activity.java │ │ │ ├── AppBarLayoutExample2Activity.java │ │ │ ├── BottomSheetBehaviorExampleActivity.java │ │ │ ├── BottomSheetBehaviorOpenBySwipeUpActivity.java │ │ │ ├── CameraApi2ExampleActivity.java │ │ │ ├── CheckCameraOrientationActivity.java │ │ │ ├── ChoosableTreeItemAdapterExampleActivity.java │ │ │ ├── CodeLabelExampleActivity.java │ │ │ ├── ComplexStringExampleActivity.java │ │ │ ├── Constants.java │ │ │ ├── ControlStatusBarColorActivity.java │ │ │ ├── GitHubReposActivity.java │ │ │ ├── GradientOvalDrawableActivity.java │ │ │ ├── Issue212316ParrierExampleActvity.java │ │ │ ├── MainActivity.java │ │ │ ├── MotionLayoutMorphActivity.java │ │ │ ├── MotionLayoutProgressActivity.java │ │ │ ├── MotionLayoutStretchableSurfacesActivity.java │ │ │ ├── MotionLayoutSwitchSceneActivity.java │ │ │ ├── MultiAdapterExampleActivity.java │ │ │ ├── MySQLiteOpenHelper.java │ │ │ ├── NestedScrambleAdapterExampleActivity.java │ │ │ ├── OperatableListExampleActivity.java │ │ │ ├── PickFromGooglePhotosActivity.java │ │ │ ├── RecyclerViewHeaderExampleActivity.java │ │ │ ├── ScrambleAdapterExampleActivity.java │ │ │ ├── SimpleStringExampleActivity.java │ │ │ ├── TreeItemAdapterExampleActivity.java │ │ │ ├── ViewPagerInBottomSheetExampleActivity.java │ │ │ ├── ViewSnapperExampleActivity.java │ │ │ ├── adapter │ │ │ ├── ActivityEntryAdapter.java │ │ │ ├── ChoosableMyTreeItemAdapter.java │ │ │ ├── ComplexStringAdapter.java │ │ │ ├── MyTreeItemAdapter.java │ │ │ ├── SimpleNumberAdapter.java │ │ │ ├── SimpleStringAdapter.java │ │ │ ├── SimpleViewsPagerAdapter.java │ │ │ └── factory │ │ │ │ ├── CodeLableViewHolderFactory.java │ │ │ │ ├── ComplexStringViewHolderFactory.java │ │ │ │ ├── MyInfoViewHolderFactory.java │ │ │ │ ├── NestedScrambleInfoViewHolderFactory.java │ │ │ │ ├── RepoViewHolderFactory.java │ │ │ │ ├── SimpleNumberViewHolderFactory.java │ │ │ │ ├── SimpleStringViewHolderFactory.java │ │ │ │ └── TextInfoViewHolderFactory.java │ │ │ ├── core │ │ │ ├── AppComponent.java │ │ │ ├── MyApplication.java │ │ │ └── MyModule.java │ │ │ ├── data │ │ │ ├── ActivityEntry.java │ │ │ ├── ColorItem.java │ │ │ ├── MyInfo.java │ │ │ ├── MyTreeItem.java │ │ │ ├── NestedScrambleInfo.java │ │ │ ├── OrdinalLabel.java │ │ │ ├── Owner.java │ │ │ ├── Repo.java │ │ │ └── TextInfo.java │ │ │ ├── drawable │ │ │ └── GradientOvalDrawable.java │ │ │ ├── fragment │ │ │ ├── SimpleAppBarLayoutFragment.java │ │ │ ├── SimpleRecyclerViewFragment.java │ │ │ └── SimpleSwipeRefreshLayoutFragment.java │ │ │ ├── retrofit │ │ │ └── GitHubService.java │ │ │ ├── tracker │ │ │ ├── IScreen.java │ │ │ ├── TrackActivityLifecycleCallbacks.java │ │ │ ├── TrackEvent.java │ │ │ ├── TrackParam.java │ │ │ ├── TrackParamBundle.java │ │ │ └── Tracker.java │ │ │ ├── utils │ │ │ ├── ExampleDataGenerator.java │ │ │ └── RelayForEnterAlwaysCollapsed.java │ │ │ └── view │ │ │ ├── NestedScrollLinearLayout.java │ │ │ ├── ProgressTextView.java │ │ │ └── RoundView.java │ └── res │ │ ├── drawable-hdpi │ │ └── cover_image.jpg │ │ ├── drawable-v21 │ │ └── item_background.xml │ │ ├── drawable │ │ ├── bg_grad.xml │ │ ├── btn_open_close.xml │ │ ├── circle_gray250.xml │ │ ├── ic_android_black_24dp.xml │ │ ├── ic_arrow_downward_black_24dp.xml │ │ ├── ic_arrow_upward_black_24dp.xml │ │ ├── ic_volume_down_black_24dp.xml │ │ ├── ic_volume_down_white_24dp.xml │ │ ├── ic_volume_up_black_24dp.xml │ │ ├── ic_volume_up_white_24dp.xml │ │ └── item_background.xml │ │ ├── layout │ │ ├── activity_animate_constraint_layout.xml │ │ ├── activity_app_bar_layout_example_1.xml │ │ ├── activity_app_bar_layout_example_2.xml │ │ ├── activity_bottom_sheet_behavior_example.xml │ │ ├── activity_bottom_sheet_behavior_open_by_swipe_up.xml │ │ ├── activity_camera_api_2_example.xml │ │ ├── activity_choosable_tree_item_adapter.xml │ │ ├── activity_code_label_example.xml │ │ ├── activity_control_status_bar_color.xml │ │ ├── activity_git_hub_repos.xml │ │ ├── activity_gradient_oval_example.xml │ │ ├── activity_main.xml │ │ ├── activity_motion_layout_morph.xml │ │ ├── activity_motion_layout_progress.xml │ │ ├── activity_motion_layout_stretchable_surface.xml │ │ ├── activity_motion_layout_stretchable_surface_fail.xml │ │ ├── activity_motion_layout_switch_scene.xml │ │ ├── activity_multi_adapter_example.xml │ │ ├── activity_nested_scramble_adapter_example.xml │ │ ├── activity_operatable_list_example.xml │ │ ├── activity_pick_from_google_photos.xml │ │ ├── activity_recycler_view_header_example.xml │ │ ├── activity_scramble_adapter_example.xml │ │ ├── activity_simple_string_example.xml │ │ ├── activity_tree_item_adapter.xml │ │ ├── activity_view_pager_in_bottom_sheet_example.xml │ │ ├── activity_view_snapper.xml │ │ ├── actvity_issue_212316_parrier_example.xml │ │ ├── android_check_camera_orientation.xml │ │ ├── fragment_simple_app_bar_layout.xml │ │ ├── fragment_simple_recycler_view.xml │ │ ├── fragment_simple_swipe_refresh_layout.xml │ │ ├── item_activity_entry.xml │ │ ├── item_choosable_my_tree_item.xml │ │ ├── item_code_label.xml │ │ ├── item_complex_string.xml │ │ ├── item_my_info.xml │ │ ├── item_my_tree_item.xml │ │ ├── item_nested_scramble.xml │ │ ├── item_repo.xml │ │ ├── item_simple_number.xml │ │ ├── item_simple_string.xml │ │ ├── item_text_info.xml │ │ ├── view_footer.xml │ │ ├── view_header.xml │ │ ├── view_header_number.xml │ │ └── view_header_string.xml │ │ ├── mipmap-hdpi │ │ └── ic_launcher.png │ │ ├── mipmap-mdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxhdpi │ │ └── ic_launcher.png │ │ ├── mipmap-xxxhdpi │ │ └── ic_launcher.png │ │ ├── values-ja │ │ └── strings.xml │ │ ├── values-w820dp │ │ └── dimens.xml │ │ ├── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml │ │ └── xml │ │ ├── activity_motion_layout_morph.xml │ │ ├── activity_motion_layout_progress.xml │ │ ├── activity_motion_layout_stretchable_surface.xml │ │ └── activity_motion_layout_switch_scene.xml │ └── test │ └── java │ └── net │ └── cattaka │ └── android │ └── snippets │ └── example │ └── ExampleUnitTest.java ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── misc └── web_hi_res_512.png ├── privacy-policy.md ├── settings.gradle └── snippets ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src ├── androidTest └── java │ └── net │ └── cattaka │ └── android │ └── snippets │ └── test │ ├── CustomMatchers.java │ ├── RetryTestRule.java │ ├── ScrollToExAction.java │ └── TestUtils.java ├── main ├── AndroidManifest.xml └── java │ └── net │ └── cattaka │ └── android │ └── snippets │ ├── CoordinatorLayoutUtils.java │ ├── animator │ └── LayoutAnimatorHelper.java │ ├── camera │ ├── Camera2Engine.java │ ├── CaptureRequestDescriptions.java │ ├── ICameraEngine.java │ ├── ICaptureRequestDescription.java │ ├── ISurfaceHolder.java │ ├── ImageReaderDescription.java │ ├── ImageReaderSurfaceHolder.java │ └── TextureViewSurfaceHolder.java │ ├── issue │ └── Issue212316Parrier.java │ ├── util │ ├── ImageUtils.java │ └── StatusBarUtils.java │ └── view │ ├── NestedScrollingCoordinatorLayout.java │ ├── ViewSnapper.java │ └── WrapContentListView.java └── test └── java └── net └── cattaka └── android └── snippets └── ExampleUnitTest.java /.gitignore: -------------------------------------------------------------------------------- 1 | #built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Windows thumbnail db 19 | Thumbs.db 20 | 21 | # OSX files 22 | .DS_Store 23 | 24 | # Eclipse project files 25 | .classpath 26 | .project 27 | 28 | # Android Studio 29 | *.iml 30 | .idea 31 | #.idea/workspace.xml - remove # and delete .idea if it better suit your needs. 32 | .gradle 33 | build/ 34 | captures/ 35 | workspace/ 36 | 37 | google-services.json 38 | -------------------------------------------------------------------------------- /LICENSE-MergeRecyclerAdapter: -------------------------------------------------------------------------------- 1 | Copyright 2016 Takao Sumitomo 2 | Copyright 2014 Josh Burton 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. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## AndroidSnippets 2 | 3 | These are snippets written by @cattaka. 4 | 5 | 6 | ### To enable Google Play Services and Firebase on example application 7 | Put google-services.json under example directory, 8 | then example/build.gradle detects it and enable them. 9 | 10 | 11 | ### License 12 | 13 | #### MergeRecyclerAdapeter.java 14 | forked from https://gist.github.com/athornz/008edacd1d3b2f1e1836 15 | 16 | ``` 17 | Copyright 2016 Takao Sumitomo 18 | Copyright 2014 Josh Burton 19 | 20 | Licensed under the Apache License, Version 2.0 (the "License"); 21 | you may not use this file except in compliance with the License. 22 | You may obtain a copy of the License at 23 | 24 | http://www.apache.org/licenses/LICENSE-2.0 25 | 26 | Unless required by applicable law or agreed to in writing, software 27 | distributed under the License is distributed on an "AS IS" BASIS, 28 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | See the License for the specific language governing permissions and 30 | limitations under the License. 31 | ``` 32 | 33 | ### ScrollToExAction.java 34 | forked from https://android.googlesource.com/platform/frameworks/testing/+/android-support-test/espresso/core/src/main/java/android/support/test/espresso/action/ScrollToAction.java 35 | 36 | ``` 37 | Copyright (C) 2016 Takao Sumitomo 38 | Copyright (C) 2014 The Android Open Source Project 39 | 40 | Licensed under the Apache License, Version 2.0 (the "License"); 41 | you may not use this file except in compliance with the License. 42 | You may obtain a copy of the License at 43 | 44 | http://www.apache.org/licenses/LICENSE-2.0 45 | 46 | Unless required by applicable law or agreed to in writing, software 47 | distributed under the License is distributed on an "AS IS" BASIS, 48 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 49 | See the License for the specific language governing permissions and 50 | limitations under the License. 51 | ``` 52 | 53 | ### Others 54 | Other codes written by Takao Sumitomo are licensed under CC0. 55 | 56 | [![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png "CC0")](http://creativecommons.org/publicdomain/zero/1.0/deed.ja) 57 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | maven { url 'https://maven.google.com' } 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.4.1' 11 | classpath 'com.google.gms:google-services:4.1.0' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url 'https://maven.google.com' } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /example/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /home/cattaka/opt/android-sdk-linux/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /example/src/androidTest/java/net/cattaka/android/snippets/example/GitHubReposActivityTest.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.support.test.rule.ActivityTestRule; 4 | import android.support.test.runner.AndroidJUnit4; 5 | 6 | import net.cattaka.android.snippets.example.retrofit.GitHubService; 7 | import net.cattaka.android.snippets.example.test.IsolateEnvRule; 8 | 9 | import org.junit.Rule; 10 | import org.junit.Test; 11 | import org.junit.runner.RunWith; 12 | import org.mockito.internal.stubbing.defaultanswers.ForwardsInvocations; 13 | 14 | import java.util.concurrent.TimeUnit; 15 | 16 | import okhttp3.mockwebserver.RecordedRequest; 17 | 18 | import static org.hamcrest.Matchers.is; 19 | import static org.hamcrest.Matchers.notNullValue; 20 | import static org.junit.Assert.assertThat; 21 | import static org.mockito.Mockito.eq; 22 | import static org.mockito.Mockito.mock; 23 | import static org.mockito.Mockito.verify; 24 | 25 | /** 26 | * Created by cattaka on 16/07/10. 27 | */ 28 | @RunWith(AndroidJUnit4.class) 29 | public class GitHubReposActivityTest { 30 | @Rule 31 | public IsolateEnvRule mIsolateEnvRule = new IsolateEnvRule(); 32 | 33 | @Rule 34 | public ActivityTestRule mActivityTestRule = new ActivityTestRule<>(GitHubReposActivity.class, false, false); 35 | 36 | @Test 37 | public void testCheckRequest_mMockWebServer() throws Exception { 38 | mActivityTestRule.launchActivity(null); 39 | do { 40 | RecordedRequest recordedRequest = mIsolateEnvRule.mTestMyModule.mMockWebServer.takeRequest(3, TimeUnit.SECONDS); 41 | assertThat(recordedRequest, is(notNullValue())); 42 | if ("GET".equals(recordedRequest.getMethod()) && "/users/cattaka/repos".equals(recordedRequest.getPath())) { 43 | break; 44 | } 45 | } while (true); 46 | } 47 | 48 | @Test 49 | public void testCheckRequest_mGitHubService() throws Exception { 50 | GitHubService service; 51 | { 52 | service = mIsolateEnvRule.mTestMyModule.mGitHubService; 53 | service = mock(GitHubService.class, new ForwardsInvocations(service)); 54 | mIsolateEnvRule.mTestMyModule.mGitHubService = service; 55 | } 56 | 57 | mActivityTestRule.launchActivity(null); 58 | verify(service).listRepos(eq("cattaka")); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /example/src/androidTest/java/net/cattaka/android/snippets/example/test/AssetsDispatcher.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.test; 2 | 3 | import android.content.res.AssetManager; 4 | import android.support.test.InstrumentationRegistry; 5 | 6 | import java.io.ByteArrayOutputStream; 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | import okhttp3.mockwebserver.Dispatcher; 11 | import okhttp3.mockwebserver.MockResponse; 12 | import okhttp3.mockwebserver.RecordedRequest; 13 | 14 | /** 15 | * Created by cattaka on 16/07/10. 16 | */ 17 | public class AssetsDispatcher extends Dispatcher { 18 | AssetManager mAssetManager; // テスト側のContextのAssetManagerが想定 19 | 20 | public AssetsDispatcher() { 21 | mAssetManager = InstrumentationRegistry.getContext().getAssets(); 22 | } 23 | 24 | @Override 25 | public MockResponse dispatch(final RecordedRequest request) throws InterruptedException { 26 | String assetFilename = "http_testdata/" + request.getMethod() + request.getPath().replace('/', '_'); 27 | try { 28 | String body = readAssetAsString(assetFilename); 29 | return new MockResponse().setBody(body).setResponseCode(200); 30 | } catch (IOException e) { 31 | // assets/http_testdata/に見つからないので404を返す 32 | return new MockResponse().setResponseCode(404); 33 | } 34 | } 35 | 36 | private String readAssetAsString(String assetFilename) throws IOException { 37 | InputStream in = mAssetManager.open(assetFilename); 38 | ByteArrayOutputStream bout = new ByteArrayOutputStream(); 39 | byte[] buf = new byte[1 << 12]; 40 | int r; 41 | while ((r = in.read(buf)) > 0) { 42 | bout.write(buf, 0, r); 43 | } 44 | return new String(bout.toByteArray()); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /example/src/androidTest/java/net/cattaka/android/snippets/example/test/IsolateEnvRule.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.test; 2 | 3 | import android.support.test.InstrumentationRegistry; 4 | 5 | import net.cattaka.android.snippets.example.core.AppComponent; 6 | import net.cattaka.android.snippets.example.core.DaggerAppComponent; 7 | import net.cattaka.android.snippets.example.core.MyApplication; 8 | 9 | import org.junit.rules.TestRule; 10 | import org.junit.runner.Description; 11 | import org.junit.runners.model.Statement; 12 | 13 | import java.io.IOException; 14 | 15 | /** 16 | * Created by cattaka on 16/07/10. 17 | */ 18 | public class IsolateEnvRule implements TestRule { 19 | public TestMyModule mTestMyModule; 20 | 21 | public Statement apply(Statement base, Description description) { 22 | return statement(base, description); 23 | } 24 | 25 | private Statement statement(final Statement base, final Description description) { 26 | return new Statement() { 27 | @Override 28 | public void evaluate() throws Throwable { 29 | before(); 30 | try { 31 | base.evaluate(); 32 | } finally { 33 | after(); 34 | } 35 | } 36 | }; 37 | } 38 | 39 | private void before() { 40 | MyApplication application = (MyApplication) InstrumentationRegistry 41 | .getTargetContext().getApplicationContext(); 42 | mTestMyModule = new TestMyModule(application); 43 | mTestMyModule.reset(); 44 | AppComponent testComponent = DaggerAppComponent.builder() 45 | .myModule(mTestMyModule).build(); 46 | application.setAppComponent(testComponent); 47 | } 48 | 49 | private void after() { 50 | try { 51 | mTestMyModule.shutdown(); 52 | } catch (IOException e) { 53 | // ignore 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/src/androidTest/java/net/cattaka/android/snippets/example/test/TestMyModule.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.test; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.google.gson.FieldNamingPolicy; 8 | import com.google.gson.Gson; 9 | import com.google.gson.GsonBuilder; 10 | 11 | import net.cattaka.android.snippets.example.Constants; 12 | import net.cattaka.android.snippets.example.MySQLiteOpenHelper; 13 | import net.cattaka.android.snippets.example.core.MyModule; 14 | import net.cattaka.android.snippets.example.retrofit.GitHubService; 15 | 16 | import java.io.IOException; 17 | 18 | import dagger.Module; 19 | import dagger.Provides; 20 | import okhttp3.mockwebserver.MockWebServer; 21 | import retrofit2.Retrofit; 22 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 23 | import retrofit2.converter.gson.GsonConverterFactory; 24 | 25 | /** 26 | * Created by cattaka on 16/07/10. 27 | */ 28 | @Module 29 | public class TestMyModule extends MyModule { 30 | public static final String TEST_PREF_NAME = "test_" + Constants.PREF_NAME; 31 | public static final String TEST_DB_NAME = "test_" + Constants.DB_NAME; 32 | 33 | private Context mContext; 34 | // テスト時にアクセスできるようにpublicにしておく 35 | public MockWebServer mMockWebServer; 36 | 37 | public SharedPreferences mSharedPreferences; 38 | public MySQLiteOpenHelper mMySQLiteOpenHelper; 39 | public Retrofit mRetrofit; 40 | public GitHubService mGitHubService; 41 | 42 | public TestMyModule(@NonNull Context context) { 43 | super(context); 44 | mContext = context; 45 | mMockWebServer = new MockWebServer(); 46 | mMockWebServer.setDispatcher(new AssetsDispatcher()); 47 | 48 | mSharedPreferences = mContext.getSharedPreferences(TEST_PREF_NAME, Context.MODE_PRIVATE); 49 | mMySQLiteOpenHelper = new MySQLiteOpenHelper(mContext, TEST_DB_NAME, null, Constants.DB_VERSION); 50 | Gson gson = new GsonBuilder() 51 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 52 | .create(); 53 | mRetrofit = new Retrofit.Builder() 54 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 55 | .addConverterFactory(GsonConverterFactory.create(gson)) 56 | .baseUrl(mMockWebServer.url("/").toString()).build(); 57 | mGitHubService = mRetrofit.create(GitHubService.class); 58 | } 59 | 60 | public void reset() { 61 | // 手段を問わず、保存されているデータを消す 62 | createSharedPreferences().edit().clear().apply(); 63 | mContext.deleteDatabase(TEST_DB_NAME); 64 | } 65 | 66 | public void shutdown() throws IOException { 67 | mMockWebServer.shutdown(); 68 | } 69 | 70 | @Provides 71 | public SharedPreferences createSharedPreferences() { 72 | return mSharedPreferences; 73 | } 74 | 75 | @Provides 76 | public MySQLiteOpenHelper createMySQLiteOpenHelper() { 77 | return mMySQLiteOpenHelper; 78 | } 79 | 80 | @Provides 81 | public Retrofit createRetrofit() { 82 | return mRetrofit; 83 | } 84 | 85 | @Provides 86 | 87 | @Override 88 | public GitHubService createGitHubService() { 89 | return mGitHubService; 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /example/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/CheckCameraOrientationActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.content.Context; 4 | import android.content.res.Configuration; 5 | import android.databinding.DataBindingUtil; 6 | import android.hardware.Camera; 7 | import android.hardware.camera2.CameraMetadata; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.support.annotation.Nullable; 11 | import android.support.v7.app.AppCompatActivity; 12 | import android.view.Surface; 13 | import android.view.WindowManager; 14 | 15 | import net.cattaka.android.snippets.example.databinding.AndroidCheckCameraOrientationBinding; 16 | 17 | /** 18 | * Created by cattaka on 17/01/02. 19 | */ 20 | 21 | public class CheckCameraOrientationActivity extends AppCompatActivity { 22 | AndroidCheckCameraOrientationBinding mBinding; 23 | 24 | @Override 25 | protected void onCreate(@Nullable Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | 28 | mBinding = DataBindingUtil.setContentView(this, R.layout.android_check_camera_orientation); 29 | } 30 | 31 | @Override 32 | protected void onStart() { 33 | super.onStart(); 34 | 35 | mBinding.setActivityOrientation(getActivityOrientation()); 36 | mBinding.setDisplayOrientation(getDisplayOrientation()); 37 | mBinding.setCameraOrientation(getCameraOrientation()); 38 | } 39 | 40 | private String getActivityOrientation() { 41 | switch (getResources().getConfiguration().orientation) { 42 | case Configuration.ORIENTATION_LANDSCAPE: 43 | return "ORIENTATION_LANDSCAPE"; 44 | case Configuration.ORIENTATION_PORTRAIT: 45 | return "ORIENTATION_PORTRAIT"; 46 | case Configuration.ORIENTATION_SQUARE: 47 | return "ORIENTATION_SQUARE"; 48 | case Configuration.ORIENTATION_UNDEFINED: 49 | default: { 50 | return "ORIENTATION_UNDEFINED"; 51 | } 52 | } 53 | } 54 | 55 | private String getDisplayOrientation() { 56 | WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); 57 | int rotation = windowManager.getDefaultDisplay().getRotation(); 58 | switch (rotation) { 59 | case Surface.ROTATION_0: 60 | return "ROTATION_0"; 61 | case Surface.ROTATION_90: 62 | return "ROTATION_90"; 63 | case Surface.ROTATION_180: 64 | return "ROTATION_180"; 65 | case Surface.ROTATION_270: 66 | return "ROTATION_270"; 67 | default: 68 | return "ROTATION_UNDEFINED"; 69 | } 70 | } 71 | 72 | private String getCameraOrientation() { 73 | Camera.CameraInfo info = new Camera.CameraInfo(); 74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 75 | Camera.getCameraInfo(CameraMetadata.LENS_FACING_BACK, info); 76 | } else { 77 | Camera.getCameraInfo(1, info); 78 | } 79 | return String.valueOf(info.orientation); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/ChoosableTreeItemAdapterExampleActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | 9 | import net.cattaka.android.snippets.example.adapter.ChoosableMyTreeItemAdapter; 10 | import net.cattaka.android.snippets.example.data.MyTreeItem; 11 | import net.cattaka.android.snippets.example.tracker.IScreen; 12 | import net.cattaka.android.snippets.example.tracker.TrackEvent; 13 | import net.cattaka.android.snippets.example.tracker.TrackParam; 14 | import net.cattaka.android.snippets.example.tracker.Tracker; 15 | import net.cattaka.android.snippets.example.utils.ExampleDataGenerator; 16 | 17 | import java.util.Arrays; 18 | import java.util.List; 19 | 20 | import static net.cattaka.android.snippets.example.tracker.TrackParamBundle.toParamsMap; 21 | 22 | /** 23 | * Created by cattaka on 16/05/21. 24 | */ 25 | public class ChoosableTreeItemAdapterExampleActivity extends AppCompatActivity implements IScreen { 26 | ChoosableMyTreeItemAdapter.IChoosableMyTreeItemAdapterListener mChoosableMyTreeItemAdapterListener = new ChoosableMyTreeItemAdapter.IChoosableMyTreeItemAdapterListener() { 27 | @Override 28 | public void onItemOpenChanged(@NonNull MyTreeItem item, boolean open) { 29 | Tracker.getInstance().recordAction(me, TrackEvent.ACTION_CLICK, toParamsMap(TrackParam.ITEM_NAME, item.getText(), TrackParam.VIEW_NAME, "open", TrackParam.VALUE, String.valueOf(open))); 30 | } 31 | 32 | @Override 33 | public void onItemCheckChanged(@NonNull MyTreeItem item, boolean checked) { 34 | Tracker.getInstance().recordAction(me, TrackEvent.ACTION_CLICK, toParamsMap(TrackParam.ITEM_NAME, item.getText(), TrackParam.VIEW_NAME, "check", TrackParam.VALUE, String.valueOf(checked))); 35 | } 36 | }; 37 | 38 | ChoosableTreeItemAdapterExampleActivity me = this; 39 | RecyclerView mRecyclerView; 40 | 41 | @Override 42 | protected void onCreate(Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | setContentView(R.layout.activity_choosable_tree_item_adapter); 45 | 46 | // find views 47 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler); 48 | 49 | { // set adapter 50 | List items = ExampleDataGenerator.generateMyTreeItem(Arrays.asList(5, 3, 2), 0); 51 | ChoosableMyTreeItemAdapter adapter = new ChoosableMyTreeItemAdapter(this, items); 52 | adapter.setListener(mChoosableMyTreeItemAdapterListener); 53 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 54 | mRecyclerView.setAdapter(adapter); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/CodeLabelExampleActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | import android.widget.AdapterView; 7 | import android.widget.Spinner; 8 | import android.widget.Toast; 9 | 10 | import net.cattaka.android.adaptertoolbox.adapter.CodeLabelAdapter; 11 | import net.cattaka.android.snippets.example.data.OrdinalLabel; 12 | import net.cattaka.android.snippets.example.tracker.IScreen; 13 | import net.cattaka.android.snippets.example.tracker.TrackEvent; 14 | import net.cattaka.android.snippets.example.tracker.TrackParam; 15 | import net.cattaka.android.snippets.example.tracker.Tracker; 16 | 17 | import static net.cattaka.android.snippets.example.tracker.TrackParamBundle.toParamsMap; 18 | 19 | /** 20 | * Created by cattaka on 16/05/02. 21 | */ 22 | public class CodeLabelExampleActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener, IScreen { 23 | CodeLabelExampleActivity me = this; 24 | Spinner mSpinner; 25 | 26 | @Override 27 | protected void onCreate(Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | setContentView(R.layout.activity_code_label_example); 30 | 31 | // find views 32 | mSpinner = (Spinner) findViewById(R.id.spinner); 33 | 34 | // bind event handlers 35 | mSpinner.setOnItemSelectedListener(this); 36 | 37 | // set adapter 38 | mSpinner.setAdapter(CodeLabelAdapter.newInstance(this, OrdinalLabel.values(), true)); 39 | } 40 | 41 | @Override 42 | public void onItemSelected(AdapterView parent, View view, int position, long id) { 43 | if (parent.getId() == R.id.spinner) { 44 | OrdinalLabel item = (OrdinalLabel) parent.getItemAtPosition(position); 45 | Tracker.getInstance().recordAction(me, TrackEvent.SELECTED, toParamsMap(TrackParam.ITEM_NAME, (item != null) ? item.getCode() : null)); 46 | String text = (item != null) ? item.getLabel(getResources()) : "null"; 47 | Toast.makeText(this, text + " is selected.", Toast.LENGTH_SHORT).show(); 48 | } 49 | } 50 | 51 | @Override 52 | public void onNothingSelected(AdapterView parent) { 53 | // no-op 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/Constants.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | /** 4 | * Created by cattaka on 16/07/10. 5 | */ 6 | public class Constants { 7 | public static final String DB_NAME = "database"; 8 | public static final int DB_VERSION = 1; 9 | public static final String PREF_NAME = "pref"; 10 | } 11 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/GradientOvalDrawableActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | import android.widget.SeekBar; 8 | 9 | import net.cattaka.android.snippets.example.drawable.GradientOvalDrawable; 10 | import net.cattaka.android.snippets.example.tracker.IScreen; 11 | 12 | public class GradientOvalDrawableActivity extends AppCompatActivity implements IScreen { 13 | SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() { 14 | @Override 15 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 16 | switch (seekBar.getId()) { 17 | case R.id.seek_alpha: { 18 | mGradientOvalDrawable.setAlpha(progress); 19 | break; 20 | } 21 | case R.id.seek_degree: { 22 | mGradientOvalDrawable.setDegree(progress); 23 | break; 24 | } 25 | case R.id.seek_stroke_width: { 26 | float f = (float) progress / (float) seekBar.getMax(); 27 | int w = (int) (f * mImageView.getWidth() / 2); 28 | mGradientOvalDrawable.setStrokeWidth(w); 29 | break; 30 | } 31 | } 32 | } 33 | 34 | @Override 35 | public void onStartTrackingTouch(SeekBar seekBar) { 36 | // no-op 37 | } 38 | 39 | @Override 40 | public void onStopTrackingTouch(SeekBar seekBar) { 41 | // no-op 42 | } 43 | }; 44 | 45 | View mImageView; 46 | SeekBar mAlphaSeek; 47 | SeekBar mStrokeWidthSeek; 48 | SeekBar mSeekDegree; 49 | 50 | GradientOvalDrawable mGradientOvalDrawable; 51 | 52 | @Override 53 | protected void onCreate(@Nullable Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_gradient_oval_example); 56 | 57 | mGradientOvalDrawable = new GradientOvalDrawable(); 58 | mImageView = findViewById(R.id.image); 59 | mAlphaSeek = findViewById(R.id.seek_alpha); 60 | mStrokeWidthSeek = findViewById(R.id.seek_stroke_width); 61 | mSeekDegree = findViewById(R.id.seek_degree); 62 | 63 | mImageView.setBackgroundDrawable(mGradientOvalDrawable); 64 | mAlphaSeek.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 65 | mStrokeWidthSeek.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 66 | mSeekDegree.setOnSeekBarChangeListener(mOnSeekBarChangeListener); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/Issue212316ParrierExampleActvity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.widget.TextView; 7 | 8 | import net.cattaka.android.snippets.example.core.MyApplication; 9 | 10 | /** 11 | * https://code.google.com/p/android/issues/detail?id=212316 12 | *

13 | * Created by takao on 2017/01/12. 14 | */ 15 | public class Issue212316ParrierExampleActvity extends AppCompatActivity { 16 | private TextView mTextView; 17 | private int mOnStartCount = 0; 18 | private byte[] mBlob; 19 | 20 | @Override 21 | protected void onCreate(@Nullable Bundle savedInstanceState) { 22 | ((MyApplication) getApplication()).getIssue212316Parrier().restoreSaveInstanceState(savedInstanceState, true); 23 | super.onCreate(savedInstanceState); 24 | setContentView(R.layout.actvity_issue_212316_parrier_example); 25 | if (savedInstanceState != null) { 26 | mOnStartCount = savedInstanceState.getInt("onStartCount"); 27 | mBlob = savedInstanceState.getByteArray("blob"); 28 | } else { 29 | mBlob = new byte[1 << 23]; // 8MiB 30 | } 31 | 32 | // find view 33 | mTextView = (TextView) findViewById(R.id.text); 34 | } 35 | 36 | @Override 37 | protected void onStart() { 38 | super.onStart(); 39 | mOnStartCount++; 40 | mTextView.setText("onStart count : " + mOnStartCount); 41 | } 42 | 43 | @Override 44 | protected void onSaveInstanceState(Bundle outState) { 45 | super.onSaveInstanceState(outState); 46 | outState.putInt("onStartCount", mOnStartCount); 47 | outState.putByteArray("blob", mBlob); 48 | 49 | ((MyApplication) getApplication()).getIssue212316Parrier().saveInstanceState(outState); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/MotionLayoutMorphActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import net.cattaka.android.snippets.example.tracker.IScreen; 8 | 9 | public class MotionLayoutMorphActivity extends AppCompatActivity implements IScreen { 10 | @Override 11 | protected void onCreate(@Nullable Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_motion_layout_morph); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/MotionLayoutProgressActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import net.cattaka.android.snippets.example.tracker.IScreen; 8 | 9 | public class MotionLayoutProgressActivity extends AppCompatActivity implements IScreen { 10 | @Override 11 | protected void onCreate(@Nullable Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_motion_layout_progress); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/MotionLayoutStretchableSurfacesActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | 7 | import net.cattaka.android.snippets.example.tracker.IScreen; 8 | 9 | public class MotionLayoutStretchableSurfacesActivity extends AppCompatActivity implements IScreen { 10 | @Override 11 | protected void onCreate(@Nullable Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_motion_layout_stretchable_surface); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/MotionLayoutSwitchSceneActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.constraint.motion.MotionLayout; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.util.Log; 7 | import android.view.View; 8 | 9 | import net.cattaka.android.snippets.example.tracker.IScreen; 10 | 11 | import java.util.Locale; 12 | 13 | /** 14 | * Created by takao on 2016/10/28. 15 | */ 16 | 17 | public class MotionLayoutSwitchSceneActivity extends AppCompatActivity implements View.OnClickListener, IScreen { 18 | private MotionLayoutSwitchSceneActivity me = this; 19 | private MotionLayout mMotionLayout; 20 | private int mDirtyHackForSceneId = -1; 21 | 22 | @Override 23 | protected void onCreate(Bundle savedInstanceState) { 24 | super.onCreate(savedInstanceState); 25 | setContentView(R.layout.activity_motion_layout_switch_scene); 26 | 27 | // Find views 28 | mMotionLayout = findViewById(R.id.motionLayout); 29 | findViewById(R.id.button_center).setOnClickListener(this); 30 | findViewById(R.id.button_top).setOnClickListener(this); 31 | findViewById(R.id.button_start_bottom).setOnClickListener(this); 32 | findViewById(R.id.button_end_bottom).setOnClickListener(this); 33 | 34 | mMotionLayout.setShowPaths(true); 35 | } 36 | 37 | @Override 38 | public void onClick(View view) { 39 | 40 | Log.d("cattaka", String.format(Locale.ROOT, "%d:%f", mMotionLayout.getCurrentState(), mMotionLayout.getProgress())); 41 | if (view.getId() == R.id.button_center) { 42 | switchToState(R.id.scene_c); 43 | } else if (view.getId() == R.id.button_top) { 44 | switchToState(R.id.scene_t); 45 | } else if (view.getId() == R.id.button_start_bottom) { 46 | switchToState(R.id.scene_sb); 47 | } else if (view.getId() == R.id.button_end_bottom) { 48 | switchToState(R.id.scene_eb); 49 | } 50 | } 51 | 52 | private void switchToState(int nextSceneId) { 53 | // FIXME: In some case, getCurrentState() returns -1 54 | int lastSceneId = mMotionLayout.getCurrentState(); 55 | if (lastSceneId == -1) { 56 | lastSceneId = mDirtyHackForSceneId; 57 | } else { 58 | mDirtyHackForSceneId = lastSceneId; 59 | } 60 | mMotionLayout.setTransition(lastSceneId, nextSceneId); 61 | mMotionLayout.setProgress(0); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/MySQLiteOpenHelper.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.content.Context; 4 | import android.database.DatabaseErrorHandler; 5 | import android.database.sqlite.SQLiteDatabase; 6 | import android.database.sqlite.SQLiteOpenHelper; 7 | 8 | /** 9 | * Created by cattaka on 16/07/10. 10 | */ 11 | public class MySQLiteOpenHelper extends SQLiteOpenHelper { 12 | public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) { 13 | super(context, name, factory, version); 14 | } 15 | 16 | public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version, DatabaseErrorHandler errorHandler) { 17 | super(context, name, factory, version, errorHandler); 18 | } 19 | 20 | @Override 21 | public void onCreate(SQLiteDatabase db) { 22 | 23 | } 24 | 25 | @Override 26 | public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 27 | // no-op yet 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/PickFromGooglePhotosActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.content.Intent; 4 | import android.databinding.DataBindingUtil; 5 | import android.net.Uri; 6 | import android.os.Build; 7 | import android.os.Bundle; 8 | import android.support.annotation.Nullable; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.view.View; 11 | 12 | import net.cattaka.android.snippets.example.databinding.ActivityPickFromGooglePhotosBinding; 13 | import net.cattaka.android.snippets.example.tracker.IScreen; 14 | import net.cattaka.android.snippets.example.tracker.TrackEvent; 15 | import net.cattaka.android.snippets.example.tracker.Tracker; 16 | 17 | import static net.cattaka.android.snippets.example.tracker.TrackParam.VIEW_NAME; 18 | import static net.cattaka.android.snippets.example.tracker.TrackParamBundle.toParamsMap; 19 | 20 | /** 21 | * Created by cattaka on 17/12/15. 22 | */ 23 | 24 | public class PickFromGooglePhotosActivity extends AppCompatActivity implements IScreen { 25 | static final int REQUEST_CODE_PICK = 1; 26 | 27 | ActivityPickFromGooglePhotosBinding mBinding; 28 | 29 | String GOOGLE_PHOTOS_PACKAGE_NAME = "com.google.android.apps.photos"; 30 | 31 | @Override 32 | protected void onCreate(@Nullable Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | mBinding = DataBindingUtil.setContentView(this, R.layout.activity_pick_from_google_photos); 35 | mBinding.setActivity(this); 36 | } 37 | 38 | @Override 39 | protected void onActivityResult(int requestCode, int resultCode, Intent data) { 40 | super.onActivityResult(requestCode, resultCode, data); 41 | if (requestCode == REQUEST_CODE_PICK) { 42 | if (resultCode == RESULT_OK) { 43 | Uri resultUri = (data != null ? data.getData() : null); 44 | if (resultUri != null) { 45 | mBinding.image.setImageURI(resultUri); 46 | } 47 | } 48 | } 49 | } 50 | 51 | public void onClickPickNormal(View view) { 52 | Tracker.getInstance().recordAction(this, TrackEvent.ACTION_CLICK, toParamsMap(VIEW_NAME, "pick_normal")); 53 | Intent intent = new Intent(); 54 | intent.setAction(Intent.ACTION_GET_CONTENT); 55 | if (Build.VERSION.SDK_INT >= 19) { 56 | intent.addCategory(Intent.CATEGORY_OPENABLE); 57 | } 58 | intent.setType("image/*"); 59 | startActivityForResult(intent, REQUEST_CODE_PICK); 60 | } 61 | 62 | public void onClickPickFromPhotos(View view) { 63 | Tracker.getInstance().recordAction(this, TrackEvent.ACTION_CLICK, toParamsMap(VIEW_NAME, "pick_from_photos")); 64 | Intent intent = new Intent(); 65 | intent.setAction(Intent.ACTION_GET_CONTENT); 66 | if (Build.VERSION.SDK_INT >= 19) { 67 | intent.addCategory(Intent.CATEGORY_OPENABLE); 68 | } 69 | intent.setType("image/*"); 70 | intent.setPackage(GOOGLE_PHOTOS_PACKAGE_NAME); 71 | startActivityForResult(intent, REQUEST_CODE_PICK); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/SimpleStringExampleActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.design.widget.Snackbar; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.View; 9 | 10 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 11 | import net.cattaka.android.adaptertoolbox.adapter.listener.ListenerRelay; 12 | import net.cattaka.android.snippets.example.adapter.SimpleStringAdapter; 13 | import net.cattaka.android.snippets.example.tracker.IScreen; 14 | import net.cattaka.android.snippets.example.tracker.TrackEvent; 15 | import net.cattaka.android.snippets.example.tracker.TrackParam; 16 | import net.cattaka.android.snippets.example.tracker.Tracker; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | import static net.cattaka.android.snippets.example.tracker.TrackParamBundle.toParamsMap; 22 | 23 | /** 24 | * Created by cattaka on 16/05/02. 25 | */ 26 | public class SimpleStringExampleActivity extends AppCompatActivity implements IScreen { 27 | ListenerRelay, RecyclerView.ViewHolder> mListenerRelay = new ListenerRelay, RecyclerView.ViewHolder>() { 28 | @Override 29 | public void onClick(RecyclerView recyclerView, ScrambleAdapter adapter, RecyclerView.ViewHolder viewHolder, View view) { 30 | if (recyclerView.getId() == R.id.recycler) { 31 | String item = (String) adapter.getItemAt(viewHolder.getAdapterPosition()); 32 | Tracker.getInstance().recordAction(me, TrackEvent.ACTION_CLICK, toParamsMap(TrackParam.ITEM_NAME, item)); 33 | Snackbar.make(view, item + " is clicked.", Snackbar.LENGTH_SHORT).show(); 34 | } 35 | } 36 | 37 | @Override 38 | public boolean onLongClick(RecyclerView recyclerView, ScrambleAdapter adapter, RecyclerView.ViewHolder viewHolder, View view) { 39 | if (recyclerView.getId() == R.id.recycler) { 40 | String item = (String) adapter.getItemAt(viewHolder.getAdapterPosition()); 41 | Tracker.getInstance().recordAction(me, TrackEvent.ACTION_LONG_CLICK, toParamsMap(TrackParam.ITEM_NAME, item)); 42 | Snackbar.make(view, item + " is long clicked.", Snackbar.LENGTH_SHORT).show(); 43 | return true; 44 | } 45 | return false; 46 | } 47 | }; 48 | 49 | SimpleStringExampleActivity me = this; 50 | RecyclerView mRecyclerView; 51 | 52 | @Override 53 | protected void onCreate(Bundle savedInstanceState) { 54 | super.onCreate(savedInstanceState); 55 | setContentView(R.layout.activity_simple_string_example); 56 | 57 | // find views 58 | mRecyclerView = (RecyclerView) findViewById(R.id.recycler); 59 | 60 | { // set adapter 61 | List items = new ArrayList<>(); 62 | for (int i = 0; i < 100; i++) { 63 | items.add("item " + i); 64 | } 65 | SimpleStringAdapter adapter = new SimpleStringAdapter(this, items, mListenerRelay); 66 | mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); 67 | mRecyclerView.setAdapter(adapter); 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/ViewPagerInBottomSheetExampleActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.view.ViewPager; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | 9 | import net.cattaka.android.snippets.example.adapter.SimpleViewsPagerAdapter; 10 | import net.cattaka.android.snippets.example.tracker.IScreen; 11 | 12 | import biz.laenger.android.vpbs.BottomSheetUtils; 13 | import biz.laenger.android.vpbs.ViewPagerBottomSheetBehavior; 14 | 15 | /** 16 | * Created by cattaka on 2018/12/03 17 | */ 18 | 19 | public class ViewPagerInBottomSheetExampleActivity extends AppCompatActivity implements IScreen, View.OnClickListener { 20 | 21 | ViewPager mViewPager; 22 | SimpleViewsPagerAdapter mAdapter; 23 | ViewPagerBottomSheetBehavior mBottomSheetBehavior; 24 | 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_view_pager_in_bottom_sheet_example); 29 | 30 | // Find views 31 | mViewPager = findViewById(R.id.view_pager); 32 | 33 | findViewById(R.id.button_show_bottom_sheet).setOnClickListener(this); 34 | 35 | mBottomSheetBehavior = ViewPagerBottomSheetBehavior.from(mViewPager); 36 | mBottomSheetBehavior.setHideable(true); 37 | 38 | mAdapter = new SimpleViewsPagerAdapter(getSupportFragmentManager(), 3); 39 | mViewPager.setAdapter(mAdapter); 40 | 41 | BottomSheetUtils.setupViewPager(mViewPager); 42 | } 43 | 44 | @Override 45 | public void onClick(View v) { 46 | if (v.getId() == R.id.button_show_bottom_sheet) { 47 | mBottomSheetBehavior.setState(ViewPagerBottomSheetBehavior.STATE_EXPANDED); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/ViewSnapperExampleActivity.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example; 2 | 3 | import android.graphics.Point; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.widget.Button; 7 | import android.widget.HorizontalScrollView; 8 | import android.widget.LinearLayout; 9 | import android.widget.ScrollView; 10 | 11 | import net.cattaka.android.snippets.view.ViewSnapper; 12 | 13 | import java.util.Locale; 14 | 15 | /** 16 | * Created by takao on 2016/10/26. 17 | */ 18 | public class ViewSnapperExampleActivity extends AppCompatActivity { 19 | ScrollView mVerticalScroll; 20 | HorizontalScrollView mHorizontalScroll; 21 | LinearLayout mLayout; 22 | 23 | @Override 24 | protected void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_view_snapper); 27 | 28 | mVerticalScroll = (ScrollView) findViewById(R.id.scroll_vertical); 29 | mHorizontalScroll = (HorizontalScrollView) findViewById(R.id.scroll_horizontal); 30 | mLayout = (LinearLayout) findViewById(R.id.layout); 31 | makeLayout(); 32 | 33 | ViewSnapper viewSnapper = new ViewSnapper(); 34 | viewSnapper.apply(mVerticalScroll, true, true, ViewSnapper.withClass(Button.class), ViewSnapper.anchorVertical(true, true)); 35 | viewSnapper.apply(mHorizontalScroll, true, true, ViewSnapper.withClass(Button.class), ViewSnapper.anchorHorizontal(true, true)); 36 | } 37 | 38 | private void makeLayout() { 39 | Point size = new Point(); 40 | getWindowManager().getDefaultDisplay().getSize(size); 41 | 42 | for (int c = 0; c < 32; c++) { 43 | LinearLayout linearLayout = new LinearLayout(this); 44 | linearLayout.setOrientation(LinearLayout.HORIZONTAL); 45 | for (int r = 0; r < 32; r++) { 46 | Button b = new Button(this); 47 | b.setText(String.format(Locale.ROOT, "%d, %d", c, r)); 48 | LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(size.x * 2 / 5, size.y * 2 / 5); 49 | b.setLayoutParams(params); 50 | b.setBackgroundColor(0xFF000000 + (int) (Math.random() * 0xFFFFFF)); 51 | linearLayout.addView(b); 52 | } 53 | mLayout.addView(linearLayout); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/ComplexStringAdapter.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 7 | import net.cattaka.android.adaptertoolbox.adapter.listener.ListenerRelay; 8 | import net.cattaka.android.snippets.example.adapter.factory.ComplexStringViewHolderFactory; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by cattaka on 16/05/02. 14 | */ 15 | public class ComplexStringAdapter extends ScrambleAdapter { 16 | public ComplexStringAdapter(Context context, List items, ListenerRelay, RecyclerView.ViewHolder> listenerRelay) { 17 | super(context, items, listenerRelay, new ComplexStringViewHolderFactory()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/SimpleNumberAdapter.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 7 | import net.cattaka.android.adaptertoolbox.adapter.listener.ListenerRelay; 8 | import net.cattaka.android.snippets.example.adapter.factory.SimpleNumberViewHolderFactory; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by cattaka on 16/05/02. 14 | */ 15 | public class SimpleNumberAdapter extends ScrambleAdapter { 16 | public SimpleNumberAdapter(Context context, List items, ListenerRelay, RecyclerView.ViewHolder> listenerRelay) { 17 | super(context, items, listenerRelay, new SimpleNumberViewHolderFactory()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/SimpleStringAdapter.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 7 | import net.cattaka.android.adaptertoolbox.adapter.listener.ListenerRelay; 8 | import net.cattaka.android.snippets.example.adapter.factory.SimpleStringViewHolderFactory; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Created by cattaka on 16/05/02. 14 | */ 15 | public class SimpleStringAdapter extends ScrambleAdapter { 16 | public SimpleStringAdapter(Context context, List items, ListenerRelay, RecyclerView.ViewHolder> listenerRelay) { 17 | super(context, items, listenerRelay, new SimpleStringViewHolderFactory()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/SimpleViewsPagerAdapter.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import net.cattaka.android.snippets.example.fragment.SimpleAppBarLayoutFragment; 8 | import net.cattaka.android.snippets.example.fragment.SimpleRecyclerViewFragment; 9 | import net.cattaka.android.snippets.example.fragment.SimpleSwipeRefreshLayoutFragment; 10 | 11 | public class SimpleViewsPagerAdapter extends FragmentPagerAdapter { 12 | int mNum; 13 | 14 | public SimpleViewsPagerAdapter(FragmentManager fm, int num) { 15 | super(fm); 16 | mNum = num; 17 | } 18 | 19 | @Override 20 | public Fragment getItem(int i) { 21 | switch (i % 3) { 22 | case 0: { 23 | return new SimpleRecyclerViewFragment(); 24 | } 25 | case 1: { 26 | return new SimpleSwipeRefreshLayoutFragment(); 27 | } 28 | case 2: 29 | default: { 30 | return new SimpleAppBarLayoutFragment(); 31 | } 32 | 33 | } 34 | } 35 | 36 | @Override 37 | public int getCount() { 38 | return mNum; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/CodeLableViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.content.res.Resources; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.TextView; 9 | 10 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 11 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 12 | import net.cattaka.android.adaptertoolbox.data.ICodeLabel; 13 | import net.cattaka.android.snippets.example.R; 14 | 15 | /** 16 | * Created by cattaka on 16/05/02. 17 | */ 18 | public class CodeLableViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 19 | Resources mResources; 20 | 21 | public CodeLableViewHolderFactory(Resources resources) { 22 | mResources = resources; 23 | } 24 | 25 | @Override 26 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 27 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_code_label, parent, false); 28 | ViewHolder vh = new ViewHolder(view); 29 | vh.codeText.setOnClickListener(forwardingListener); 30 | vh.codeText.setOnLongClickListener(forwardingListener); 31 | vh.labelText.setOnClickListener(forwardingListener); 32 | vh.labelText.setOnLongClickListener(forwardingListener); 33 | return vh; 34 | } 35 | 36 | @Override 37 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, 38 | int position, Object object) { 39 | ICodeLabel item = (ICodeLabel) object; 40 | 41 | holder.codeText.setText(item.getCode()); 42 | holder.labelText.setText(item.getLabel(mResources)); 43 | } 44 | 45 | @Override 46 | public boolean isAssignable(Object object) { 47 | return object instanceof ICodeLabel; 48 | } 49 | 50 | public static class ViewHolder extends RecyclerView.ViewHolder { 51 | TextView codeText; 52 | TextView labelText; 53 | 54 | public ViewHolder(View itemView) { 55 | super(itemView); 56 | codeText = (TextView) itemView.findViewById(R.id.text_code); 57 | labelText = (TextView) itemView.findViewById(R.id.text_label); 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/ComplexStringViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 10 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 11 | import net.cattaka.android.snippets.example.R; 12 | 13 | /** 14 | * Created by cattaka on 16/05/02. 15 | */ 16 | public class ComplexStringViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 17 | @Override 18 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 19 | View view = LayoutInflater.from(adapter.getContext()).inflate(R.layout.item_complex_string, parent, false); 20 | ViewHolder vh = new ViewHolder(view); 21 | vh.text.setOnClickListener(forwardingListener); 22 | vh.text.setOnLongClickListener(forwardingListener); 23 | vh.aButton.setOnClickListener(forwardingListener); 24 | vh.aButton.setOnLongClickListener(forwardingListener); 25 | vh.bButton.setOnClickListener(forwardingListener); 26 | vh.bButton.setOnLongClickListener(forwardingListener); 27 | return vh; 28 | } 29 | 30 | @Override 31 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, int position, Object object) { 32 | String item = (String) object; 33 | 34 | holder.text.setText(item); 35 | } 36 | 37 | @Override 38 | public boolean isAssignable(Object object) { 39 | return object instanceof String; 40 | } 41 | 42 | public static class ViewHolder extends RecyclerView.ViewHolder { 43 | TextView text; 44 | View aButton; 45 | View bButton; 46 | 47 | public ViewHolder(View itemView) { 48 | super(itemView); 49 | text = (TextView) itemView.findViewById(R.id.text); 50 | aButton = itemView.findViewById(R.id.button_a); 51 | bButton = itemView.findViewById(R.id.button_b); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/MyInfoViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.SeekBar; 8 | import android.widget.Spinner; 9 | import android.widget.Switch; 10 | 11 | import net.cattaka.android.adaptertoolbox.adapter.CodeLabelAdapter; 12 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 13 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 14 | import net.cattaka.android.adaptertoolbox.utils.SpinnerUtils; 15 | import net.cattaka.android.snippets.example.R; 16 | import net.cattaka.android.snippets.example.data.MyInfo; 17 | import net.cattaka.android.snippets.example.data.OrdinalLabel; 18 | 19 | /** 20 | * Created by cattaka on 16/05/15. 21 | */ 22 | public class MyInfoViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 23 | @Override 24 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 25 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_my_info, parent, false); 26 | ViewHolder vh = new ViewHolder(view); 27 | 28 | vh.intValueSeek.setOnSeekBarChangeListener(forwardingListener); 29 | vh.ordinalLabelSpinner.setOnItemSelectedListener(forwardingListener); 30 | vh.checkedSwitch.setOnCheckedChangeListener(forwardingListener); 31 | 32 | vh.ordinalLabelSpinner.setAdapter(CodeLabelAdapter.newInstance(view.getContext(), OrdinalLabel.values(), true)); 33 | 34 | return vh; 35 | } 36 | 37 | @Override 38 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, int position, Object object) { 39 | MyInfo item = (MyInfo) object; 40 | 41 | holder.intValueSeek.setProgress(item.getIntValue()); 42 | SpinnerUtils.selectSpinnerValue(holder.ordinalLabelSpinner, item.getOrdinalLabel()); 43 | holder.checkedSwitch.setChecked(item.isChecked()); 44 | } 45 | 46 | @Override 47 | public boolean isAssignable(Object object) { 48 | return object instanceof MyInfo; 49 | } 50 | 51 | public class ViewHolder extends RecyclerView.ViewHolder { 52 | SeekBar intValueSeek; 53 | Spinner ordinalLabelSpinner; 54 | Switch checkedSwitch; 55 | 56 | public ViewHolder(View itemView) { 57 | super(itemView); 58 | intValueSeek = (SeekBar) itemView.findViewById(R.id.seek_int_value); 59 | ordinalLabelSpinner = (Spinner) itemView.findViewById(R.id.spinner_ordinal_label); 60 | checkedSwitch = (Switch) itemView.findViewById(R.id.switch_checked); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/NestedScrambleInfoViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 10 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 11 | import net.cattaka.android.snippets.example.R; 12 | import net.cattaka.android.snippets.example.data.NestedScrambleInfo; 13 | 14 | /** 15 | * Created by cattaka on 16/05/16. 16 | */ 17 | public class NestedScrambleInfoViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 18 | @Override 19 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 20 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_nested_scramble, parent, false); 21 | 22 | { // Hack height 23 | int h = parent.getHeight(); 24 | if (h > 0) { 25 | ViewGroup.LayoutParams params = view.getLayoutParams(); 26 | params.height = h / 3; 27 | view.setLayoutParams(params); 28 | } 29 | } 30 | 31 | ViewHolder vh = new ViewHolder(view); 32 | return vh; 33 | } 34 | 35 | @Override 36 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, int position, Object object) { 37 | NestedScrambleInfo item = (NestedScrambleInfo) object; 38 | 39 | ScrambleAdapter nextedAdapter = new ScrambleAdapter(holder.itemView.getContext(), item.getItems(), item.getListenerRelay(), item.getViewHolderFactories()); 40 | holder.recyclerView.setLayoutManager(new LinearLayoutManager(holder.itemView.getContext(), LinearLayoutManager.HORIZONTAL, false)); 41 | holder.recyclerView.setAdapter(nextedAdapter); 42 | } 43 | 44 | public static class ViewHolder extends RecyclerView.ViewHolder { 45 | RecyclerView recyclerView; 46 | 47 | public ViewHolder(View itemView) { 48 | super(itemView); 49 | recyclerView = (RecyclerView) itemView.findViewById(R.id.recycler); 50 | } 51 | } 52 | 53 | @Override 54 | public boolean isAssignable(Object object) { 55 | return object instanceof NestedScrambleInfo; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/RepoViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.annotation.NonNull; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.widget.RecyclerView; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.TextView; 10 | 11 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 12 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 13 | import net.cattaka.android.snippets.example.R; 14 | import net.cattaka.android.snippets.example.data.Repo; 15 | 16 | /** 17 | * Created by cattaka on 16/07/10. 18 | */ 19 | public class RepoViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 20 | 21 | @NonNull 22 | @Override 23 | public ViewHolder onCreateViewHolder(@NonNull ScrambleAdapter adapter, @NonNull ViewGroup parent, @NonNull ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 24 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_repo, parent, false); 25 | ViewHolder holder = new ViewHolder(view); 26 | holder.openButton.setOnClickListener(forwardingListener); 27 | holder.ownerButton.setOnClickListener(forwardingListener); 28 | return holder; 29 | } 30 | 31 | @Override 32 | public void onBindViewHolder(@NonNull ScrambleAdapter adapter, @NonNull ViewHolder holder, int position, @Nullable Object object) { 33 | Repo item = (Repo) object; 34 | 35 | holder.nameText.setText(item.getName()); 36 | holder.urlText.setText(item.getUrl()); 37 | } 38 | 39 | @Override 40 | public boolean isAssignable(Object object) { 41 | return object instanceof Repo; 42 | } 43 | 44 | public static class ViewHolder extends RecyclerView.ViewHolder { 45 | public final TextView nameText; 46 | public final TextView urlText; 47 | public final View openButton; 48 | public final View ownerButton; 49 | 50 | public ViewHolder(View itemView) { 51 | super(itemView); 52 | nameText = (TextView) itemView.findViewById(R.id.text_name); 53 | urlText = (TextView) itemView.findViewById(R.id.text_url); 54 | openButton = itemView.findViewById(R.id.button_open); 55 | ownerButton = itemView.findViewById(R.id.button_owner); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/SimpleNumberViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 10 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 11 | import net.cattaka.android.snippets.example.R; 12 | 13 | /** 14 | * Created by cattaka on 16/05/02. 15 | */ 16 | public class SimpleNumberViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 17 | @Override 18 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 19 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_simple_number, parent, false); 20 | ViewHolder vh = new ViewHolder(view); 21 | view.setOnClickListener(forwardingListener); 22 | view.setOnLongClickListener(forwardingListener); 23 | return vh; 24 | } 25 | 26 | @Override 27 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, int position, Object object) { 28 | Number item = (Number) object; 29 | 30 | String str = "Number = " + item; 31 | holder.text.setText(str); 32 | } 33 | 34 | @Override 35 | public boolean isAssignable(Object object) { 36 | return object instanceof Number; 37 | } 38 | 39 | public static class ViewHolder extends RecyclerView.ViewHolder { 40 | TextView text; 41 | 42 | public ViewHolder(View itemView) { 43 | super(itemView); 44 | text = (TextView) itemView.findViewById(R.id.text); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/SimpleStringViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.TextView; 8 | 9 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 10 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 11 | import net.cattaka.android.snippets.example.R; 12 | 13 | /** 14 | * Created by cattaka on 16/05/02. 15 | */ 16 | public class SimpleStringViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 17 | 18 | @Override 19 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 20 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_simple_string, parent, false); 21 | ViewHolder vh = new ViewHolder(view); 22 | view.setOnClickListener(forwardingListener); 23 | view.setOnLongClickListener(forwardingListener); 24 | return vh; 25 | } 26 | 27 | @Override 28 | public void onBindViewHolder(ScrambleAdapter adapter, ViewHolder holder, int position, Object object) { 29 | String item = (String) object; 30 | 31 | String str = "String = " + item; 32 | holder.text.setText(str); 33 | } 34 | 35 | @Override 36 | public boolean isAssignable(Object object) { 37 | return object instanceof String; 38 | } 39 | 40 | public static class ViewHolder extends RecyclerView.ViewHolder { 41 | TextView text; 42 | 43 | public ViewHolder(View itemView) { 44 | super(itemView); 45 | text = (TextView) itemView.findViewById(R.id.text); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/adapter/factory/TextInfoViewHolderFactory.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.adapter.factory; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.EditText; 8 | 9 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 10 | import net.cattaka.android.adaptertoolbox.adapter.listener.ForwardingListener; 11 | import net.cattaka.android.snippets.example.R; 12 | import net.cattaka.android.snippets.example.data.TextInfo; 13 | 14 | /** 15 | * Created by cattaka on 16/05/15. 16 | */ 17 | public class TextInfoViewHolderFactory extends ScrambleAdapter.AbsViewHolderFactory { 18 | @Override 19 | public ViewHolder onCreateViewHolder(ScrambleAdapter adapter, ViewGroup parent, ForwardingListener, RecyclerView.ViewHolder> forwardingListener) { 20 | View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_text_info, parent, false); 21 | ViewHolder vh = new ViewHolder(view); 22 | 23 | vh.editText.setOnEditorActionListener(forwardingListener); 24 | forwardingListener.addTextChangedListener(vh.editText); 25 | vh.goButton.setOnClickListener(forwardingListener); 26 | 27 | return vh; 28 | } 29 | 30 | @Override 31 | public void onBindViewHolder(ScrambleAdapter adapter, TextInfoViewHolderFactory.ViewHolder holder, int position, Object object) { 32 | TextInfo item = (TextInfo) object; 33 | 34 | holder.editText.setText(item.getText()); 35 | } 36 | 37 | @Override 38 | public boolean isAssignable(Object object) { 39 | return object instanceof TextInfo; 40 | } 41 | 42 | public class ViewHolder extends RecyclerView.ViewHolder { 43 | public final EditText editText; 44 | public final View goButton; 45 | 46 | public ViewHolder(View itemView) { 47 | super(itemView); 48 | editText = (EditText) itemView.findViewById(R.id.edit_text); 49 | goButton = itemView.findViewById(R.id.button_go); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/core/AppComponent.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.core; 2 | 3 | import android.content.SharedPreferences; 4 | 5 | import net.cattaka.android.snippets.example.GitHubReposActivity; 6 | import net.cattaka.android.snippets.example.MySQLiteOpenHelper; 7 | import net.cattaka.android.snippets.example.retrofit.GitHubService; 8 | 9 | import dagger.Component; 10 | import retrofit2.Retrofit; 11 | 12 | /** 13 | * Created by cattaka on 16/07/10. 14 | */ 15 | @Component(modules = MyModule.class) 16 | public interface AppComponent { 17 | void inject(GitHubReposActivity activity); 18 | 19 | SharedPreferences getSharedPreferences(); 20 | 21 | MySQLiteOpenHelper getMySQLiteOpenHelper(); 22 | 23 | Retrofit getRetrofit(); 24 | 25 | GitHubService getGitHubService(); 26 | } 27 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/core/MyApplication.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.core; 2 | 3 | import android.app.Application; 4 | import android.support.annotation.VisibleForTesting; 5 | 6 | import net.cattaka.android.snippets.example.BuildConfig; 7 | import net.cattaka.android.snippets.example.tracker.Tracker; 8 | import net.cattaka.android.snippets.issue.Issue212316Parrier; 9 | 10 | /** 11 | * Created by cattaka on 16/07/10. 12 | */ 13 | public class MyApplication extends Application { 14 | AppComponent mAppComponent; 15 | Issue212316Parrier mIssue212316Parrier; 16 | 17 | @Override 18 | public void onCreate() { 19 | super.onCreate(); 20 | mAppComponent = DaggerAppComponent 21 | .builder() 22 | .myModule(new MyModule(this)) 23 | .build(); 24 | 25 | mIssue212316Parrier = new Issue212316Parrier(this, BuildConfig.VERSION_NAME, BuildConfig.VERSION_CODE); 26 | mIssue212316Parrier.initialize(); 27 | 28 | Tracker.getInstance().initialize(this); 29 | } 30 | 31 | public AppComponent getAppComponent() { 32 | return mAppComponent; 33 | } 34 | 35 | public Issue212316Parrier getIssue212316Parrier() { 36 | return mIssue212316Parrier; 37 | } 38 | 39 | @VisibleForTesting 40 | public void setAppComponent(AppComponent appComponent) { 41 | mAppComponent = appComponent; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/core/MyModule.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.core; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | import android.support.annotation.NonNull; 6 | 7 | import com.google.gson.FieldNamingPolicy; 8 | import com.google.gson.Gson; 9 | import com.google.gson.GsonBuilder; 10 | 11 | import net.cattaka.android.snippets.example.Constants; 12 | import net.cattaka.android.snippets.example.MySQLiteOpenHelper; 13 | import net.cattaka.android.snippets.example.retrofit.GitHubService; 14 | 15 | import dagger.Module; 16 | import dagger.Provides; 17 | import retrofit2.Retrofit; 18 | import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory; 19 | import retrofit2.converter.gson.GsonConverterFactory; 20 | 21 | /** 22 | * Created by cattaka on 16/07/10. 23 | */ 24 | @Module 25 | public class MyModule { 26 | private Context mContext; 27 | 28 | public MyModule(@NonNull Context context) { 29 | mContext = context; 30 | } 31 | 32 | @Provides 33 | public SharedPreferences createSharedPreferences() { 34 | return mContext.getSharedPreferences(Constants.PREF_NAME, Context.MODE_PRIVATE); 35 | } 36 | 37 | @Provides 38 | public MySQLiteOpenHelper createMySQLiteOpenHelper() { 39 | return new MySQLiteOpenHelper(mContext, Constants.DB_NAME, null, Constants.DB_VERSION); 40 | } 41 | 42 | @Provides 43 | public Retrofit createRetrofit() { 44 | Gson gson = new GsonBuilder() 45 | .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES) 46 | .create(); 47 | return new Retrofit.Builder() 48 | .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 49 | .addConverterFactory(GsonConverterFactory.create(gson)) 50 | .baseUrl("https://api.github.com/").build(); 51 | } 52 | 53 | @Provides 54 | public GitHubService createGitHubService() { 55 | return createRetrofit().create(GitHubService.class); 56 | } 57 | } -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/ActivityEntry.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | import android.app.Activity; 4 | 5 | import net.cattaka.android.adaptertoolbox.data.ITreeItem; 6 | 7 | import java.util.Arrays; 8 | import java.util.List; 9 | 10 | /** 11 | * Created by cattaka on 16/05/22. 12 | */ 13 | public class ActivityEntry implements ITreeItem { 14 | private String label; 15 | private Class clazz; 16 | private List children; 17 | private int apiLevel; 18 | 19 | public ActivityEntry(String label, Class clazz, ActivityEntry... children) { 20 | this.label = label; 21 | this.clazz = clazz; 22 | this.children = Arrays.asList(children); 23 | this.apiLevel = 1; 24 | } 25 | 26 | public ActivityEntry(String label, Class clazz, int apiLevel, ActivityEntry... children) { 27 | this.label = label; 28 | this.clazz = clazz; 29 | this.children = Arrays.asList(children); 30 | this.apiLevel = apiLevel; 31 | } 32 | 33 | public String getLabel() { 34 | return label; 35 | } 36 | 37 | public void setLabel(String label) { 38 | this.label = label; 39 | } 40 | 41 | public Class getClazz() { 42 | return clazz; 43 | } 44 | 45 | public void setClazz(Class clazz) { 46 | this.clazz = clazz; 47 | } 48 | 49 | @Override 50 | public List getChildren() { 51 | return children; 52 | } 53 | 54 | public void setChildren(List children) { 55 | this.children = children; 56 | } 57 | 58 | public int getApiLevel() { 59 | return apiLevel; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/ColorItem.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | import java.util.Locale; 4 | 5 | /** 6 | * Created by takao on 2016/12/12. 7 | */ 8 | 9 | public class ColorItem { 10 | private int color; 11 | 12 | public ColorItem() { 13 | 14 | } 15 | 16 | public ColorItem(int color) { 17 | this.color = color; 18 | } 19 | 20 | public int getColor() { 21 | return color; 22 | } 23 | 24 | public void setColor(int color) { 25 | this.color = color; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return String.format(Locale.ROOT, "%08X", color); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/MyInfo.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | /** 4 | * Created by cattaka on 16/05/15. 5 | */ 6 | public class MyInfo { 7 | private int intValue; 8 | private OrdinalLabel ordinalLabel; 9 | private boolean checked; 10 | 11 | public int getIntValue() { 12 | return intValue; 13 | } 14 | 15 | public void setIntValue(int intValue) { 16 | this.intValue = intValue; 17 | } 18 | 19 | public OrdinalLabel getOrdinalLabel() { 20 | return ordinalLabel; 21 | } 22 | 23 | public void setOrdinalLabel(OrdinalLabel ordinalLabel) { 24 | this.ordinalLabel = ordinalLabel; 25 | } 26 | 27 | public boolean isChecked() { 28 | return checked; 29 | } 30 | 31 | public void setChecked(boolean checked) { 32 | this.checked = checked; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/MyTreeItem.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | import net.cattaka.android.adaptertoolbox.data.ITreeItem; 4 | 5 | import java.util.List; 6 | 7 | /** 8 | * Created by cattaka on 16/05/21. 9 | */ 10 | public class MyTreeItem implements ITreeItem { 11 | private String text; 12 | private List children; 13 | 14 | public MyTreeItem() { 15 | } 16 | 17 | public MyTreeItem(String text, List children) { 18 | this.text = text; 19 | this.children = children; 20 | } 21 | 22 | public String getText() { 23 | return text; 24 | } 25 | 26 | public void setText(String text) { 27 | this.text = text; 28 | } 29 | 30 | @Override 31 | public List getChildren() { 32 | return children; 33 | } 34 | 35 | public void setChildren(List children) { 36 | this.children = children; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/NestedScrambleInfo.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | 5 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 6 | import net.cattaka.android.adaptertoolbox.adapter.listener.ListenerRelay; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * Created by cattaka on 16/05/16. 12 | */ 13 | public class NestedScrambleInfo { 14 | private List> viewHolderFactories; 15 | private ListenerRelay, RecyclerView.ViewHolder> listenerRelay; 16 | private List items; 17 | 18 | public NestedScrambleInfo() { 19 | } 20 | 21 | public NestedScrambleInfo(List> viewHolderFactories, ListenerRelay, RecyclerView.ViewHolder> listenerRelay, List items) { 22 | this.viewHolderFactories = viewHolderFactories; 23 | this.listenerRelay = listenerRelay; 24 | this.items = items; 25 | } 26 | 27 | public List> getViewHolderFactories() { 28 | return viewHolderFactories; 29 | } 30 | 31 | public void setViewHolderFactories(List> viewHolderFactories) { 32 | this.viewHolderFactories = viewHolderFactories; 33 | } 34 | 35 | public ListenerRelay, RecyclerView.ViewHolder> getListenerRelay() { 36 | return listenerRelay; 37 | } 38 | 39 | public void setListenerRelay(ListenerRelay, RecyclerView.ViewHolder> listenerRelay) { 40 | this.listenerRelay = listenerRelay; 41 | } 42 | 43 | public List getItems() { 44 | return items; 45 | } 46 | 47 | public void setItems(List items) { 48 | this.items = items; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/OrdinalLabel.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | import android.content.res.Resources; 4 | import android.support.annotation.StringRes; 5 | 6 | import net.cattaka.android.adaptertoolbox.data.ICodeLabel; 7 | import net.cattaka.android.snippets.example.R; 8 | 9 | /** 10 | * Created by cattaka on 16/05/02. 11 | */ 12 | public enum OrdinalLabel implements ICodeLabel { 13 | FIRST("first", R.string.ordinal_label_first), 14 | SECOND("second", R.string.ordinal_label_second), 15 | THIRD("third", R.string.ordinal_label_third), 16 | FOURTH("fourth", R.string.ordinal_label_fourth), 17 | // 18 | ; 19 | 20 | final String code; 21 | @StringRes 22 | final int resId; 23 | 24 | OrdinalLabel(String code, @StringRes int resId) { 25 | this.code = code; 26 | this.resId = resId; 27 | } 28 | 29 | @Override 30 | public String getCode() { 31 | return code; 32 | } 33 | 34 | @Override 35 | public String getLabel(Resources res) { 36 | return res.getString(resId); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/data/TextInfo.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.data; 2 | 3 | /** 4 | * Created by cattaka on 16/05/15. 5 | */ 6 | public class TextInfo { 7 | private String text; 8 | 9 | public String getText() { 10 | return text; 11 | } 12 | 13 | public void setText(String text) { 14 | this.text = text; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/fragment/SimpleAppBarLayoutFragment.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 14 | import net.cattaka.android.snippets.example.R; 15 | import net.cattaka.android.snippets.example.adapter.factory.SimpleStringViewHolderFactory; 16 | 17 | import java.util.ArrayList; 18 | 19 | public class SimpleAppBarLayoutFragment extends Fragment { 20 | RecyclerView mRecyclerView; 21 | ScrambleAdapter mAdapter; 22 | 23 | @Nullable 24 | @Override 25 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 | return inflater.inflate(R.layout.fragment_simple_app_bar_layout, container, false); 27 | } 28 | 29 | @Override 30 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 31 | super.onViewCreated(view, savedInstanceState); 32 | mRecyclerView = view.findViewById(R.id.view_recycler); 33 | 34 | { // Setup mRecyclerView 35 | mAdapter = new ScrambleAdapter<>(requireContext(), new ArrayList<>(), null, new SimpleStringViewHolderFactory()); 36 | mRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)); 37 | mRecyclerView.setAdapter(mAdapter); 38 | for (int i = 0; i < 100; i++) { 39 | mAdapter.getItems().add("Item : " + mAdapter.getItems().size()); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/fragment/SimpleRecyclerViewFragment.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 14 | import net.cattaka.android.snippets.example.R; 15 | import net.cattaka.android.snippets.example.adapter.factory.SimpleStringViewHolderFactory; 16 | 17 | import java.util.ArrayList; 18 | 19 | public class SimpleRecyclerViewFragment extends Fragment { 20 | RecyclerView mRecyclerView; 21 | ScrambleAdapter mAdapter; 22 | 23 | @Nullable 24 | @Override 25 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 26 | return inflater.inflate(R.layout.fragment_simple_recycler_view, container, false); 27 | } 28 | 29 | @Override 30 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 31 | super.onViewCreated(view, savedInstanceState); 32 | mRecyclerView = view.findViewById(R.id.view_recycler); 33 | 34 | { // Setup mRecyclerView 35 | mAdapter = new ScrambleAdapter<>(requireContext(), new ArrayList<>(), null, new SimpleStringViewHolderFactory()); 36 | mRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)); 37 | mRecyclerView.setAdapter(mAdapter); 38 | for (int i = 0; i < 100; i++) { 39 | mAdapter.getItems().add("Item : " + mAdapter.getItems().size()); 40 | } 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/fragment/SimpleSwipeRefreshLayoutFragment.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.os.Looper; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.support.v4.widget.SwipeRefreshLayout; 10 | import android.support.v7.widget.LinearLayoutManager; 11 | import android.support.v7.widget.RecyclerView; 12 | import android.view.LayoutInflater; 13 | import android.view.View; 14 | import android.view.ViewGroup; 15 | 16 | import net.cattaka.android.adaptertoolbox.adapter.ScrambleAdapter; 17 | import net.cattaka.android.snippets.example.R; 18 | import net.cattaka.android.snippets.example.adapter.factory.SimpleStringViewHolderFactory; 19 | 20 | import java.util.ArrayList; 21 | 22 | public class SimpleSwipeRefreshLayoutFragment extends Fragment { 23 | Handler sHandler = new Handler(Looper.getMainLooper()); 24 | 25 | SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = new SwipeRefreshLayout.OnRefreshListener() { 26 | @Override 27 | public void onRefresh() { 28 | sHandler.postDelayed(() -> mSwipeRefreshLayout.setRefreshing(false), 1000); 29 | } 30 | }; 31 | 32 | SwipeRefreshLayout mSwipeRefreshLayout; 33 | RecyclerView mRecyclerView; 34 | ScrambleAdapter mAdapter; 35 | 36 | @Nullable 37 | @Override 38 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 39 | return inflater.inflate(R.layout.fragment_simple_swipe_refresh_layout, container, false); 40 | } 41 | 42 | @Override 43 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { 44 | super.onViewCreated(view, savedInstanceState); 45 | mRecyclerView = view.findViewById(R.id.view_recycler); 46 | mSwipeRefreshLayout = view.findViewById(R.id.layout_swipe_refresh); 47 | 48 | mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener); 49 | 50 | { // Setup mRecyclerView 51 | mAdapter = new ScrambleAdapter<>(requireContext(), new ArrayList<>(), null, new SimpleStringViewHolderFactory()); 52 | mRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)); 53 | mRecyclerView.setAdapter(mAdapter); 54 | for (int i = 0; i < 100; i++) { 55 | mAdapter.getItems().add("Item : " + mAdapter.getItems().size()); 56 | } 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/retrofit/GitHubService.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.retrofit; 2 | 3 | import net.cattaka.android.snippets.example.data.Repo; 4 | 5 | import java.util.List; 6 | 7 | import retrofit2.http.GET; 8 | import retrofit2.http.Path; 9 | import rx.Observable; 10 | 11 | /** 12 | * Created by cattaka on 16/07/10. 13 | */ 14 | public interface GitHubService { 15 | @GET("users/{user}/repos") 16 | Observable> listRepos(@Path("user") String user); 17 | } 18 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/tracker/IScreen.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.tracker; 2 | 3 | import android.app.Activity; 4 | import android.support.annotation.NonNull; 5 | 6 | /** 7 | * Created by cattaka on 17/12/01. 8 | */ 9 | 10 | public interface IScreen { 11 | @NonNull 12 | default String getScreenName() { 13 | return this.getClass().getSimpleName(); 14 | } 15 | 16 | default boolean useAutoTrack() { 17 | return true; 18 | } 19 | 20 | static IScreen ofScreen(@NonNull Activity o) { 21 | return new IScreen() { 22 | @NonNull 23 | @Override 24 | public String getScreenName() { 25 | return o.getClass().getSimpleName(); 26 | } 27 | }; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/tracker/TrackActivityLifecycleCallbacks.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.tracker; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.os.Bundle; 6 | import android.os.Handler; 7 | import android.os.Looper; 8 | import android.os.Message; 9 | 10 | /** 11 | * Created by cattaka on 17/12/01. 12 | */ 13 | 14 | public class TrackActivityLifecycleCallbacks implements Application.ActivityLifecycleCallbacks { 15 | private static final int EVENT_CHECK_FOREGROUND = 1; 16 | private static final int INTERVAL_LEAVE_SCREEN_MSEC = 3000; 17 | 18 | private static Handler sHandler = new Handler(Looper.getMainLooper()) { 19 | @Override 20 | public void handleMessage(Message msg) { 21 | super.handleMessage(msg); 22 | TrackActivityLifecycleCallbacks target = (TrackActivityLifecycleCallbacks) msg.obj; 23 | if (msg.what == EVENT_CHECK_FOREGROUND) { 24 | target.checkForeground(); 25 | } 26 | } 27 | }; 28 | 29 | private boolean mForeground = false; 30 | 31 | @Override 32 | public void onActivityCreated(Activity activity, Bundle bundle) { 33 | // no-op 34 | } 35 | 36 | @Override 37 | public void onActivityStarted(Activity activity) { 38 | // no-op 39 | } 40 | 41 | @Override 42 | public void onActivityResumed(Activity activity) { 43 | mForeground = true; 44 | sHandler.removeMessages(EVENT_CHECK_FOREGROUND, this); 45 | IScreen screen = (activity instanceof IScreen) ? ((IScreen) activity) : IScreen.ofScreen(activity); 46 | 47 | if (screen.useAutoTrack()) { 48 | Tracker.getInstance().recordScreen(screen); 49 | } 50 | } 51 | 52 | @Override 53 | public void onActivityPaused(Activity activity) { 54 | mForeground = false; 55 | sHandler.removeMessages(EVENT_CHECK_FOREGROUND, this); 56 | sHandler.sendMessageDelayed( 57 | sHandler.obtainMessage(EVENT_CHECK_FOREGROUND, this), 58 | INTERVAL_LEAVE_SCREEN_MSEC 59 | ); 60 | } 61 | 62 | @Override 63 | public void onActivityStopped(Activity activity) { 64 | // no-op 65 | } 66 | 67 | @Override 68 | public void onActivitySaveInstanceState(Activity activity, Bundle bundle) { 69 | // no-op 70 | } 71 | 72 | @Override 73 | public void onActivityDestroyed(Activity activity) { 74 | // no-op 75 | } 76 | 77 | private void checkForeground() { 78 | if (!mForeground) { 79 | Tracker.getInstance().recordScreen(null); 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/tracker/TrackEvent.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.tracker; 2 | 3 | /** 4 | * NODE: Follow the limitation of Firebase Analytics, such as num of actions, don't use space in action name. 5 | */ 6 | public enum TrackEvent { 7 | ACTION_CLICK("action_click"), 8 | ACTION_LONG_CLICK("action_long_click"), 9 | CHECK_CHANGE("check_change"), 10 | SELECTED("selected"), 11 | // 12 | ; 13 | public final String code; 14 | 15 | TrackEvent(String code) { 16 | this.code = code; 17 | } 18 | 19 | @Override 20 | public String toString() { 21 | return code; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/tracker/Tracker.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.tracker; 2 | 3 | import android.app.Activity; 4 | import android.app.Application; 5 | import android.app.Fragment; 6 | import android.content.Context; 7 | import android.os.Bundle; 8 | import android.support.annotation.NonNull; 9 | import android.support.annotation.Nullable; 10 | import android.util.Log; 11 | 12 | import com.google.firebase.analytics.FirebaseAnalytics; 13 | 14 | import net.cattaka.android.snippets.example.BuildConfig; 15 | 16 | import java.util.Locale; 17 | 18 | /** 19 | * Created by cattaka on 17/12/01. 20 | */ 21 | 22 | public class Tracker { 23 | static final String TAG_SCREEN = "TrackScreen"; 24 | static final String TAG_ACTION = "TrackEvent"; 25 | 26 | 27 | private static Tracker INSTANCE = new Tracker(); 28 | 29 | public static Tracker getInstance() { 30 | return INSTANCE; 31 | } 32 | 33 | private Context mContext; 34 | private FirebaseAnalytics mFirebaseAnalytics; 35 | private TrackActivityLifecycleCallbacks mTrackActivityLifecycleCallbacks; 36 | 37 | public void initialize(@NonNull Application context) { 38 | mContext = context; 39 | if (BuildConfig.ENABLE_GOOGLE_SERVICES) { 40 | mFirebaseAnalytics = FirebaseAnalytics.getInstance(context); 41 | } 42 | 43 | TrackActivityLifecycleCallbacks mTrackActivityLifecycleCallbacks = new TrackActivityLifecycleCallbacks(); 44 | context.registerActivityLifecycleCallbacks(mTrackActivityLifecycleCallbacks); 45 | } 46 | 47 | public void recordScreen(@Nullable IScreen screen) { 48 | if (BuildConfig.ENABLE_GOOGLE_SERVICES) { 49 | if (screen instanceof Activity) { 50 | String screenName = screen.getScreenName(); 51 | mFirebaseAnalytics.setCurrentScreen((Activity) screen, screenName, null); 52 | } else if (screen instanceof Fragment) { 53 | Activity activity = ((Fragment) screen).getActivity(); 54 | mFirebaseAnalytics.setCurrentScreen(activity, screen.getScreenName(), null); 55 | } else { 56 | String screenName = (screen != null) ? screen.getScreenName() : null; 57 | mFirebaseAnalytics.setCurrentScreen(null, screenName, null); 58 | } 59 | } 60 | if (BuildConfig.DEBUG) { 61 | String screenName = (screen != null) ? screen.getScreenName() : null; 62 | Log.d(TAG_SCREEN, String.format(Locale.ROOT, "screen=%s", screenName)); 63 | } 64 | } 65 | 66 | public void recordAction(@Nullable IScreen screen, @NonNull TrackEvent action, @Nullable TrackParamBundle params) { 67 | String screenName = (screen != null) ? screen.getScreenName() : null; 68 | if (BuildConfig.ENABLE_GOOGLE_SERVICES) { 69 | Bundle event = (params != null) ? params.toFirebaseBundle() : new Bundle(); 70 | event.putString("screen", screenName); 71 | event.putString("app_version", BuildConfig.VERSION_NAME); 72 | mFirebaseAnalytics.logEvent(action.code, event); 73 | } 74 | if (BuildConfig.DEBUG) { 75 | StringBuilder sb = new StringBuilder(); 76 | sb.append(screenName != null ? screenName : "?"); 77 | sb.append(" / "); 78 | sb.append(action.code); 79 | sb.append(" / "); 80 | sb.append(params); 81 | Log.d(TAG_ACTION, sb.toString()); 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/utils/ExampleDataGenerator.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.utils; 2 | 3 | import net.cattaka.android.snippets.example.data.MyTreeItem; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Locale; 8 | 9 | /** 10 | * Created by cattaka on 16/05/21. 11 | */ 12 | public class ExampleDataGenerator { 13 | public static List generateMyTreeItem(List numOfLevels, int level) { 14 | if (numOfLevels.size() == 0) { 15 | return null; 16 | } 17 | List items = new ArrayList<>(); 18 | int n = numOfLevels.get(0); 19 | for (int i = 0; i < n; i++) { 20 | String text = String.format(Locale.ROOT, "Item %d of level %d", i, level); 21 | List children = generateMyTreeItem(numOfLevels.subList(1, numOfLevels.size()), level + 1); 22 | items.add(new MyTreeItem(text, children)); 23 | } 24 | return items; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/utils/RelayForEnterAlwaysCollapsed.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.utils; 2 | 3 | import android.os.SystemClock; 4 | import android.support.annotation.NonNull; 5 | import android.support.design.widget.AppBarLayout; 6 | import android.support.design.widget.CoordinatorLayout; 7 | import android.support.v7.widget.RecyclerView; 8 | 9 | /** 10 | * Created by cattaka on 17/02/19. 11 | */ 12 | 13 | public class RelayForEnterAlwaysCollapsed { 14 | public static RecyclerView.OnScrollListener apply(@NonNull RecyclerView target, @NonNull CoordinatorLayout coordinatorLayout, @NonNull AppBarLayout appBarLayout) { 15 | ForRecyclerView listener = new ForRecyclerView(coordinatorLayout, appBarLayout); 16 | target.addOnScrollListener(listener); 17 | return listener; 18 | } 19 | 20 | public static class ForRecyclerView extends RecyclerView.OnScrollListener { 21 | CoordinatorLayout mCoordinatorLayout; 22 | AppBarLayout mAppBarLayout; 23 | long mLastTime; 24 | float mLastVelX; 25 | float mLastVelY; 26 | 27 | public ForRecyclerView(@NonNull CoordinatorLayout coordinatorLayout, @NonNull AppBarLayout appBarLayout) { 28 | mCoordinatorLayout = coordinatorLayout; 29 | mAppBarLayout = appBarLayout; 30 | } 31 | 32 | @Override 33 | public void onScrollStateChanged(RecyclerView recyclerView, int newState) { 34 | super.onScrollStateChanged(recyclerView, newState); 35 | if (newState == RecyclerView.SCROLL_STATE_IDLE) { 36 | CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) mAppBarLayout.getLayoutParams(); 37 | AppBarLayout.Behavior behavior = (AppBarLayout.Behavior) params.getBehavior(); 38 | if (behavior != null) { 39 | behavior.onNestedFling(mCoordinatorLayout, mAppBarLayout, null, mLastVelX, mLastVelY, false); 40 | } 41 | } 42 | } 43 | 44 | @Override 45 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 46 | super.onScrolled(recyclerView, dx, dy); 47 | long t = SystemClock.elapsedRealtime(); 48 | if (t > mLastTime) { 49 | float dt = (float) (t - mLastTime) / 1000f; 50 | mLastVelX = (float) dx / dt; 51 | mLastVelY = (float) dy / dt; 52 | } 53 | mLastTime = t; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/view/NestedScrollLinearLayout.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.view; 2 | 3 | import android.content.Context; 4 | import android.os.Build; 5 | import android.support.annotation.Nullable; 6 | import android.support.annotation.RequiresApi; 7 | import android.support.v4.view.NestedScrollingChild; 8 | import android.support.v4.view.NestedScrollingChildHelper; 9 | import android.util.AttributeSet; 10 | import android.widget.LinearLayout; 11 | 12 | public class NestedScrollLinearLayout extends LinearLayout implements NestedScrollingChild { 13 | NestedScrollingChildHelper mNestedScrollingChildHelper; 14 | 15 | public NestedScrollLinearLayout(Context context) { 16 | super(context); 17 | init(); 18 | } 19 | 20 | public NestedScrollLinearLayout(Context context, @Nullable AttributeSet attrs) { 21 | super(context, attrs); 22 | init(); 23 | } 24 | 25 | public NestedScrollLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 26 | super(context, attrs, defStyleAttr); 27 | init(); 28 | } 29 | 30 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 31 | public NestedScrollLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 32 | super(context, attrs, defStyleAttr, defStyleRes); 33 | init(); 34 | } 35 | 36 | private void init() { 37 | mNestedScrollingChildHelper = new NestedScrollingChildHelper(this); 38 | setNestedScrollingEnabled(true); 39 | } 40 | 41 | public void setNestedScrollingEnabled(boolean enabled) { 42 | mNestedScrollingChildHelper.setNestedScrollingEnabled(enabled); 43 | } 44 | 45 | public boolean isNestedScrollingEnabled() { 46 | return mNestedScrollingChildHelper.isNestedScrollingEnabled(); 47 | } 48 | 49 | public boolean startNestedScroll(int axes) { 50 | return mNestedScrollingChildHelper.startNestedScroll(axes); 51 | } 52 | 53 | public void stopNestedScroll() { 54 | mNestedScrollingChildHelper.stopNestedScroll(); 55 | } 56 | 57 | public boolean hasNestedScrollingParent() { 58 | return mNestedScrollingChildHelper.hasNestedScrollingParent(); 59 | } 60 | 61 | public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @Nullable int[] offsetInWindow) { 62 | return mNestedScrollingChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow); 63 | } 64 | 65 | public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, @Nullable int[] offsetInWindow) { 66 | return mNestedScrollingChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow); 67 | } 68 | 69 | public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) { 70 | return mNestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed); 71 | } 72 | 73 | public boolean dispatchNestedPreFling(float velocityX, float velocityY) { 74 | return mNestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/view/ProgressTextView.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.view; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.AppCompatTextView; 5 | import android.util.AttributeSet; 6 | 7 | import java.util.Locale; 8 | 9 | public class ProgressTextView extends AppCompatTextView { 10 | private float mProgress; 11 | 12 | public ProgressTextView(Context context) { 13 | super(context); 14 | init(); 15 | } 16 | 17 | public ProgressTextView(Context context, AttributeSet attrs) { 18 | super(context, attrs); 19 | init(); 20 | } 21 | 22 | public ProgressTextView(Context context, AttributeSet attrs, int defStyleAttr) { 23 | super(context, attrs, defStyleAttr); 24 | init(); 25 | } 26 | 27 | private void init() { 28 | setProgress(0); 29 | } 30 | 31 | public float getProgress() { 32 | return mProgress; 33 | } 34 | 35 | public void setProgress(float progress) { 36 | if (mProgress != progress) { 37 | mProgress = progress; 38 | setText(String.format(Locale.ROOT, "%1.3f", mProgress)); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /example/src/main/java/net/cattaka/android/snippets/example/view/RoundView.java: -------------------------------------------------------------------------------- 1 | package net.cattaka.android.snippets.example.view; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Path; 6 | import android.graphics.RectF; 7 | import android.os.Build; 8 | import android.support.annotation.RequiresApi; 9 | import android.util.AttributeSet; 10 | import android.view.View; 11 | 12 | public class RoundView extends View { 13 | private float mProgress; 14 | 15 | public RoundView(Context context) { 16 | super(context); 17 | } 18 | 19 | public RoundView(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | 23 | public RoundView(Context context, AttributeSet attrs, int defStyleAttr) { 24 | super(context, attrs, defStyleAttr); 25 | } 26 | 27 | @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) 28 | public RoundView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 29 | super(context, attrs, defStyleAttr, defStyleRes); 30 | } 31 | 32 | @Override 33 | public void draw(Canvas canvas) { 34 | int w = this.getWidth(); 35 | int h = this.getHeight(); 36 | float radius = Math.min(w / 2, h / 2) * (1f - mProgress); 37 | 38 | Path clipPath = new Path(); 39 | canvas.save(); 40 | clipPath.addRoundRect( 41 | new RectF(0, 0, w, h), 42 | radius, 43 | radius, 44 | Path.Direction.CW 45 | ); 46 | canvas.clipPath(clipPath); 47 | super.draw(canvas); 48 | canvas.restore(); 49 | } 50 | 51 | public float getProgress() { 52 | return mProgress; 53 | } 54 | 55 | public void setProgress(float progress) { 56 | if (mProgress != progress) { 57 | mProgress = progress; 58 | invalidate(); 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /example/src/main/res/drawable-hdpi/cover_image.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cattaka/AndroidSnippets/73708ad75239b26feaa24016a86abf083c0fbea5/example/src/main/res/drawable-hdpi/cover_image.jpg -------------------------------------------------------------------------------- /example/src/main/res/drawable-v21/item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/bg_grad.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 11 | 14 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/btn_open_close.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/circle_gray250.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_android_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_arrow_downward_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_arrow_upward_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_volume_down_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_volume_down_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_volume_up_black_24dp.xml: -------------------------------------------------------------------------------- 1 | 6 | 9 | 10 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/ic_volume_up_white_24dp.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /example/src/main/res/drawable/item_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /example/src/main/res/layout/activity_animate_constraint_layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 14 | 15 | 24 | 25 | 34 | 35 | 44 | 45 | 52 | 53 | 54 | 57 | 58 |