├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── drawable │ │ │ │ ├── ic_app.png │ │ │ │ ├── ic_face_01.png │ │ │ │ ├── ic_face_02.png │ │ │ │ ├── ic_face_03.png │ │ │ │ ├── ic_face_04.png │ │ │ │ ├── ic_face_05.png │ │ │ │ ├── ic_face_06.png │ │ │ │ ├── ic_face_07.png │ │ │ │ ├── pic_bird_main.png │ │ │ │ ├── pic_cow_main.png │ │ │ │ ├── pic_owl_main.png │ │ │ │ ├── pic_pig_main.png │ │ │ │ ├── ic_pet_hide_left.png │ │ │ │ ├── ic_intro_first_01.png │ │ │ │ ├── ic_intro_first_02.png │ │ │ │ ├── ic_intro_first_03.png │ │ │ │ ├── ic_intro_first_04.png │ │ │ │ ├── ic_intro_first_05.png │ │ │ │ ├── ic_intro_first_06.png │ │ │ │ ├── ic_intro_first_07.png │ │ │ │ ├── ic_intro_first_08.png │ │ │ │ ├── ic_intro_first_sun.png │ │ │ │ ├── ic_pet_hide_right.png │ │ │ │ └── vpi__tab_indicator.xml │ │ │ ├── mipmap-hdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-mdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-hdpi │ │ │ │ ├── shadow_left.png │ │ │ │ ├── shadow_bottom.png │ │ │ │ ├── shadow_right.png │ │ │ │ ├── ic_arrow_back_white_24dp.png │ │ │ │ ├── ic_settings_white_24dp.png │ │ │ │ ├── vpi__tab_selected_holo.9.png │ │ │ │ ├── vpi__tab_unselected_holo.9.png │ │ │ │ ├── vpi__tab_selected_focused_holo.9.png │ │ │ │ ├── vpi__tab_selected_pressed_holo.9.png │ │ │ │ ├── vpi__tab_unselected_focused_holo.9.png │ │ │ │ ├── vpi__tab_unselected_pressed_holo.9.png │ │ │ │ ├── bg_btn_selector.xml │ │ │ │ └── bg_btn_accent_selector.xml │ │ │ ├── mipmap-xhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ └── ic_launcher.png │ │ │ ├── drawable-mdpi │ │ │ │ ├── ic_arrow_back_white_24dp.png │ │ │ │ ├── ic_settings_white_24dp.png │ │ │ │ ├── vpi__tab_selected_holo.9.png │ │ │ │ ├── vpi__tab_unselected_holo.9.png │ │ │ │ ├── vpi__tab_selected_focused_holo.9.png │ │ │ │ ├── vpi__tab_selected_pressed_holo.9.png │ │ │ │ ├── vpi__tab_unselected_focused_holo.9.png │ │ │ │ └── vpi__tab_unselected_pressed_holo.9.png │ │ │ ├── drawable-xhdpi │ │ │ │ ├── ic_settings_white_24dp.png │ │ │ │ ├── ic_arrow_back_white_24dp.png │ │ │ │ ├── vpi__tab_selected_holo.9.png │ │ │ │ ├── vpi__tab_unselected_holo.9.png │ │ │ │ ├── vpi__tab_selected_focused_holo.9.png │ │ │ │ ├── vpi__tab_selected_pressed_holo.9.png │ │ │ │ ├── vpi__tab_unselected_focused_holo.9.png │ │ │ │ └── vpi__tab_unselected_pressed_holo.9.png │ │ │ ├── drawable-xxhdpi │ │ │ │ ├── ic_settings_white_24dp.png │ │ │ │ └── ic_arrow_back_white_24dp.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ ├── ic_settings_white_24dp.png │ │ │ │ ├── ic_arrow_back_white_24dp.png │ │ │ │ └── bg_btn_light_selector.xml │ │ │ ├── anim │ │ │ │ ├── transition_not_move.xml │ │ │ │ ├── transition_right_in.xml │ │ │ │ ├── transition_right_out.xml │ │ │ │ ├── splash_intro_items.xml │ │ │ │ ├── slide_in.xml │ │ │ │ └── slide_out.xml │ │ │ ├── layout │ │ │ │ ├── layout_swipeback.xml │ │ │ │ ├── layout_toolbar.xml │ │ │ │ ├── layout_widget_pet.xml │ │ │ │ ├── activity_setting.xml │ │ │ │ ├── activity_main.xml │ │ │ │ ├── layout_dialog_login.xml │ │ │ │ ├── layout_rv_item_main.xml │ │ │ │ ├── layout_dialog_register.xml │ │ │ │ ├── activity_intro.xml │ │ │ │ └── fragment_intro_first.xml │ │ │ ├── values-w820dp │ │ │ │ ├── dimens.xml │ │ │ │ └── attrs.xml │ │ │ ├── values │ │ │ │ ├── colors.xml │ │ │ │ ├── styles.xml │ │ │ │ ├── dimens.xml │ │ │ │ ├── vpi__colors.xml │ │ │ │ ├── strings.xml │ │ │ │ ├── vpi__styles.xml │ │ │ │ ├── vpi__defaults.xml │ │ │ │ └── vpi__attrs.xml │ │ │ ├── color │ │ │ │ ├── vpi__dark_theme.xml │ │ │ │ └── vpi__light_theme.xml │ │ │ └── layout-xlarge │ │ │ │ └── layout_rv_item_main.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── rdc │ │ │ │ └── goospet │ │ │ │ ├── view │ │ │ │ ├── vinterface │ │ │ │ │ ├── SettingVInterface.java │ │ │ │ │ ├── MainVInterface.java │ │ │ │ │ └── IntroVInterface.java │ │ │ │ ├── activity │ │ │ │ │ ├── SettingActivity.java │ │ │ │ │ ├── MainActivity.java │ │ │ │ │ └── IntroActivity.java │ │ │ │ ├── viewholder │ │ │ │ │ └── RVMainViewHolder.java │ │ │ │ ├── widget │ │ │ │ │ ├── PageIndicator.java │ │ │ │ │ ├── FloatingPetView.java │ │ │ │ │ └── CirclePageIndicator.java │ │ │ │ └── fragment │ │ │ │ │ ├── IntroFourthFragment.java │ │ │ │ │ ├── IntroThirdFragment.java │ │ │ │ │ ├── IntroSecondFragment.java │ │ │ │ │ └── IntroFirstFragment.java │ │ │ │ ├── model │ │ │ │ ├── minterface │ │ │ │ │ ├── SettingMInterface.java │ │ │ │ │ ├── MainMInterface.java │ │ │ │ │ └── introMInterface.java │ │ │ │ ├── SettingModel.java │ │ │ │ ├── MainModel.java │ │ │ │ └── IntroModel.java │ │ │ │ ├── base │ │ │ │ ├── BaseIntroFragment.java │ │ │ │ ├── BaseApplication.java │ │ │ │ ├── BasePresenter.java │ │ │ │ ├── BaseSwipeBackActivity.java │ │ │ │ └── BaseActivity.java │ │ │ │ ├── receiver │ │ │ │ ├── AlarmReceiver.java │ │ │ │ └── WeChatMsgReceiver.java │ │ │ │ ├── swipeback │ │ │ │ ├── SwipeBackActivityBase.java │ │ │ │ ├── SwipeBackPreferenceActivity.java │ │ │ │ ├── SwipeBackActivityHelper.java │ │ │ │ └── Utils.java │ │ │ │ ├── utils │ │ │ │ ├── DialogUtils.java │ │ │ │ ├── ToastUtil.java │ │ │ │ ├── AVOSUtils.java │ │ │ │ ├── LogUtils.java │ │ │ │ ├── AppConstants.java │ │ │ │ ├── ParallaxTransformer.java │ │ │ │ ├── FloatingRefreshTask.java │ │ │ │ ├── DimenUtils.java │ │ │ │ ├── FloatingUtils.java │ │ │ │ ├── SpUtils.java │ │ │ │ └── FloatingPetManager.java │ │ │ │ ├── presenter │ │ │ │ ├── SettingPresenter.java │ │ │ │ ├── MainPresenter.java │ │ │ │ └── IntroPresenter.java │ │ │ │ ├── adapter │ │ │ │ ├── IntroFragmentAdapter.java │ │ │ │ └── RVMainAdapter.java │ │ │ │ ├── entity │ │ │ │ └── PetInfo.java │ │ │ │ ├── service │ │ │ │ └── FloatingPetService.java │ │ │ │ └── listener │ │ │ │ ├── HidingScrollListener.java │ │ │ │ └── IntroPageChangedListener.java │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── rdc │ │ │ └── goospet │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── rdc │ │ └── goospet │ │ └── ApplicationTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── .idea └── vcs.xml ├── README.md ├── gradle.properties ├── gradlew.bat └── gradlew /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_app.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_app.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_01.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_02.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_03.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_04.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_05.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_06.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_face_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_face_07.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pic_bird_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/pic_bird_main.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pic_cow_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/pic_cow_main.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pic_owl_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/pic_owl_main.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/pic_pig_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/pic_pig_main.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/shadow_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/shadow_left.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pet_hide_left.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_pet_hide_left.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/shadow_bottom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/shadow_bottom.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/shadow_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/shadow_right.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_01.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_02.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_03.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_04.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_05.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_06.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_07.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_08.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_intro_first_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_intro_first_sun.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_pet_hide_right.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable/ic_pet_hide_right.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/ic_arrow_back_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_selected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_selected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/ic_arrow_back_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_selected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_selected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_unselected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_unselected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_unselected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_unselected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/ic_arrow_back_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_selected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_selected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xxhdpi/ic_arrow_back_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xxxhdpi/ic_settings_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_unselected_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xxxhdpi/ic_arrow_back_white_24dp.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_selected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_selected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_unselected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-hdpi/vpi__tab_unselected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_selected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_selected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_unselected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-mdpi/vpi__tab_unselected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_selected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_selected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_unselected_focused_holo.9.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Goo-Yao/GooPet/HEAD/app/src/main/res/drawable-xhdpi/vpi__tab_unselected_pressed_holo.9.png -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/vinterface/SettingVInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.vinterface; 2 | 3 | /** 4 | * Created by Goo on 2016-10-24. 5 | */ 6 | 7 | public interface SettingVInterface { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/minterface/SettingMInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model.minterface; 2 | 3 | /** 4 | * Created by Goo on 2016-10-24. 5 | */ 6 | 7 | public interface SettingMInterface { 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/vinterface/MainVInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.vinterface; 2 | 3 | /** 4 | * Created by Goo on 2016-9-18. 5 | */ 6 | public interface MainVInterface { 7 | void launchDesktopPet(); 8 | } 9 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Aug 28 16:28:46 CST 2016 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/SettingModel.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model; 2 | 3 | import com.rdc.goospet.model.minterface.SettingMInterface; 4 | 5 | /** 6 | * Created by Goo on 2016-10-24. 7 | */ 8 | 9 | public class SettingModel implements SettingMInterface { 10 | } 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/transition_not_move.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/transition_right_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/anim/transition_right_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_swipeback.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/minterface/MainMInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model.minterface; 2 | 3 | import com.rdc.goospet.entity.PetInfo; 4 | 5 | import java.util.ArrayList; 6 | 7 | /** 8 | * Created by Goo on 2016-9-18. 9 | */ 10 | public interface MainMInterface { 11 | ArrayList getPetData(); 12 | } 13 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bg_btn_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-hdpi/bg_btn_accent_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xxxhdpi/bg_btn_light_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/base/BaseIntroFragment.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.base; 2 | 3 | import android.support.v4.app.Fragment; 4 | 5 | /** 6 | * 懒加载、IntroFragment 7 | * Created by Goo on 2016-9-1. 8 | */ 9 | public abstract class BaseIntroFragment extends Fragment { 10 | 11 | public abstract int getViewTag(); 12 | 13 | public abstract int[] getChildViewIds(); 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/test/java/com/rdc/goospet/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * To work on unit tests, switch the Test Artifact in the Build Variants view. 9 | */ 10 | public class ExampleUnitTest { 11 | @Test 12 | public void addition_isCorrect() throws Exception { 13 | assertEquals(4, 2 + 2); 14 | } 15 | } -------------------------------------------------------------------------------- /app/src/androidTest/java/com/rdc/goospet/ApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet; 2 | 3 | import android.app.Application; 4 | import android.test.ApplicationTestCase; 5 | 6 | /** 7 | * Testing Fundamentals 8 | */ 9 | public class ApplicationTest extends ApplicationTestCase { 10 | public ApplicationTest() { 11 | super(Application.class); 12 | } 13 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/receiver/AlarmReceiver.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | /** 8 | * Created by Goo on 2016-9-18. 9 | */ 10 | public class AlarmReceiver extends BroadcastReceiver { 11 | @Override 12 | public void onReceive(Context context, Intent intent) { 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/receiver/WeChatMsgReceiver.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.receiver; 2 | 3 | import android.content.BroadcastReceiver; 4 | import android.content.Context; 5 | import android.content.Intent; 6 | 7 | /** 8 | * Created by Goo on 2016-9-18. 9 | */ 10 | public class WeChatMsgReceiver extends BroadcastReceiver { 11 | 12 | @Override 13 | public void onReceive(Context context, Intent intent) { 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_toolbar.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/minterface/introMInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model.minterface; 2 | 3 | import android.util.SparseArray; 4 | 5 | import com.rdc.goospet.base.BaseIntroFragment; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by Goo on 2016-8-31. 11 | */ 12 | public interface IntroMInterface { 13 | 14 | List getIntroFragemnts(); 15 | 16 | SparseArray getLayoutViewIdsMap(); 17 | } 18 | -------------------------------------------------------------------------------- /app/src/main/res/anim/splash_intro_items.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 14 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GooPet 2 | 概述:一款神奇又有趣的桌面宠物App 3 | ## 开发目标: 4 | - 具有多种动效、表情 5 | - 可自定义名字、技能、属性等 6 | - 具有闹钟提醒、天气等额外小功能 7 | - 随机启动 8 | - 不进入微信,直接提醒、展示微信消息 9 | 10 | ## 开发进度: 11 | - 实现视觉差欢迎界面 12 | - 显示宠物,拥有简单交互功能 13 | - 尚在努力开发中,敬请期待~ 14 | 15 | ## App截图 16 | ![](http://odzvmv4ab.bkt.clouddn.com/GooPet_welcome.png) 17 | ![](http://odzvmv4ab.bkt.clouddn.com/Goo_Pet_3.png) 18 | ![](http://odzvmv4ab.bkt.clouddn.com/Goo_Pet_1.png) 19 | ![](http://odzvmv4ab.bkt.clouddn.com/Goo_Pet_2.png) 20 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_in.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/res/anim/slide_out.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 9 | 13 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/swipeback/SwipeBackActivityBase.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.swipeback; 2 | 3 | public interface SwipeBackActivityBase { 4 | /** 5 | * @return the SwipeBackLayout associated with this activity. 6 | */ 7 | public abstract SwipeBackLayout getSwipeBackLayout(); 8 | 9 | public abstract void setSwipeBackEnable(boolean enable); 10 | 11 | /** 12 | * Scroll out contentView and finish the activity 13 | */ 14 | public abstract void scrollToFinishActivity(); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/base/BaseApplication.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.base; 2 | 3 | import android.app.Application; 4 | 5 | import com.avos.avoscloud.AVOSCloud; 6 | 7 | /** 8 | * Created by Goo on 2016-9-6. 9 | */ 10 | public class BaseApplication extends Application { 11 | @Override 12 | public void onCreate() { 13 | super.onCreate(); 14 | 15 | // 初始化参数依次为 this, AppId, AppKey 16 | AVOSCloud.initialize(this,"Adlpr3dsk0rETlPXReausO2N-gzGzoHsz","JIPILdLkgE2Etvww6KH5u9Qq"); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_widget_pet.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/DialogUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.content.Context; 4 | import android.support.v7.app.AlertDialog; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by Goo on 2016-9-6. 9 | * 对话框工具类 10 | */ 11 | public class DialogUtils { 12 | public static AlertDialog showCoustomDialog(Context context, View dialog, String title) { 13 | AlertDialog.Builder builder = new AlertDialog.Builder(context); 14 | builder.setTitle(title); 15 | builder.setView(dialog); 16 | return builder.show(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/ToastUtil.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.content.Context; 4 | import android.widget.Toast; 5 | 6 | /** 7 | * Created by Goo on 2016-9-6. 8 | * Toast 工具类 9 | */ 10 | public class ToastUtil { 11 | private static Toast mToast = null; 12 | 13 | public static void showToast(Context context, String text) { 14 | if (mToast == null) { 15 | mToast = Toast.makeText(context, text, Toast.LENGTH_SHORT); 16 | } else { 17 | mToast.setDuration(Toast.LENGTH_SHORT); 18 | mToast.setText(text); 19 | } 20 | mToast.show(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/vinterface/IntroVInterface.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.vinterface; 2 | 3 | /** 4 | * Created by Goo on 2016-8-31. 5 | */ 6 | public interface IntroVInterface { 7 | 8 | void showProgressDialog(); 9 | 10 | void dismissDialog(); 11 | 12 | void registerSuccess(String userName); 13 | 14 | void loginSuccess(String userName); 15 | 16 | void errorLoginFail(); 17 | 18 | void errorEmptyInfo(); 19 | 20 | void errorPswNotEqual(); 21 | 22 | void errorEmailInvalid(); 23 | 24 | void errorUserNameRepeat(); 25 | 26 | void errorEmailRepeat(); 27 | 28 | void errorNetWork(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/presenter/SettingPresenter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.presenter; 2 | 3 | import com.rdc.goospet.base.BasePresenter; 4 | import com.rdc.goospet.model.SettingModel; 5 | import com.rdc.goospet.model.minterface.SettingMInterface; 6 | import com.rdc.goospet.view.vinterface.SettingVInterface; 7 | 8 | /** 9 | * Created by Goo on 2016-10-24. 10 | */ 11 | 12 | public class SettingPresenter extends BasePresenter { 13 | 14 | private SettingMInterface mModel; 15 | 16 | public SettingPresenter(SettingVInterface viewInterface) { 17 | super(viewInterface); 18 | mModel = new SettingModel(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in I:\android-sdk-windows/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 | -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/AVOSUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import com.avos.avoscloud.AVUser; 4 | import com.avos.avoscloud.SignUpCallback; 5 | 6 | /** 7 | * Created by Goo on 2016-9-6. 8 | * AVOS 工具类 9 | */ 10 | public class AVOSUtils { 11 | /** 12 | * 注册 13 | * 14 | * @param username 15 | * @param password 16 | * @param email 17 | * @param signUpCallback 18 | */ 19 | public static void signUp(String username, String password, String email, SignUpCallback signUpCallback) { 20 | AVUser user = new AVUser(); 21 | user.setUsername(username); 22 | user.setPassword(password); 23 | user.setEmail(email); 24 | user.signUpInBackground(signUpCallback); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/base/BasePresenter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.base; 2 | 3 | import java.lang.ref.Reference; 4 | import java.lang.ref.WeakReference; 5 | 6 | /** 7 | * Created by Goo on 2016-8-28. 8 | */ 9 | public abstract class BasePresenter { 10 | protected Reference mViewRef = null; 11 | 12 | protected V view; 13 | 14 | public BasePresenter(V viewInterface) { 15 | this.view = viewInterface; 16 | } 17 | 18 | public void attachView(V view) { 19 | mViewRef = new WeakReference(view); 20 | } 21 | 22 | protected V getView() { 23 | return mViewRef.get(); 24 | } 25 | 26 | public void detachView() { 27 | if (mViewRef != null) { 28 | mViewRef.clear(); 29 | mViewRef = null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #3F51B5 5 | #C5CAE9 6 | #03A9F4 7 | #303F9F 8 | #FF5252 9 | #D32F2F 10 | #212121 11 | #757575 12 | #BDBDBD 13 | 14 | 15 | #ffffff 16 | #000000 17 | 18 | 19 | 20 | #4CAF50 21 | #00000000 22 | #40FFFFFF 23 | 24 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_setting.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/activity/SettingActivity.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.activity; 2 | 3 | import com.rdc.goospet.R; 4 | import com.rdc.goospet.base.BaseSwipeBackActivity; 5 | import com.rdc.goospet.presenter.SettingPresenter; 6 | import com.rdc.goospet.view.vinterface.SettingVInterface; 7 | 8 | public class SettingActivity extends BaseSwipeBackActivity implements SettingVInterface { 9 | 10 | 11 | @Override 12 | protected SettingPresenter createPresenter() { 13 | return new SettingPresenter(this); 14 | } 15 | 16 | @Override 17 | protected int setContentViewById() { 18 | return R.layout.activity_setting; 19 | } 20 | 21 | @Override 22 | protected void initAttributes() { 23 | 24 | } 25 | 26 | @Override 27 | protected void initView() { 28 | showToolbarAndShowNavigation("设置"); 29 | } 30 | 31 | @Override 32 | protected void findAllViewById() { 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by Goo on 2016-8-28. 7 | * Log 工具类 8 | */ 9 | public class LogUtils { 10 | private final static String TAG = "Goo's Pet"; 11 | private static boolean isShowLog = true; 12 | 13 | public static void e(String msg) { 14 | if (isShowLog) { 15 | Log.e(TAG, msg); 16 | } 17 | } 18 | 19 | public static void i(String msg) { 20 | if (isShowLog) { 21 | Log.i(TAG, msg); 22 | } 23 | } 24 | 25 | public static void d(String msg) { 26 | if (isShowLog) { 27 | Log.d(TAG, msg); 28 | } 29 | } 30 | 31 | public static void v(String msg) { 32 | if (isShowLog) { 33 | Log.v(TAG, msg); 34 | } 35 | } 36 | 37 | public static void w(String msg) { 38 | if (isShowLog) { 39 | Log.wtf(TAG, msg); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/MainModel.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model; 2 | 3 | import com.rdc.goospet.R; 4 | import com.rdc.goospet.entity.PetInfo; 5 | import com.rdc.goospet.model.minterface.MainMInterface; 6 | import com.rdc.goospet.utils.AppConstants; 7 | 8 | import java.util.ArrayList; 9 | 10 | /** 11 | * Created by Goo on 2016-9-18. 12 | */ 13 | public class MainModel implements MainMInterface { 14 | @Override 15 | public ArrayList getPetData() { 16 | ArrayList data = new ArrayList<>(); 17 | data.add(new PetInfo(AppConstants.PET_OWL, "Bean", "A sleepless owl", R.drawable.pic_owl_main, false)); 18 | data.add(new PetInfo(AppConstants.PET_PIG, "Karo", "A lovely pig", R.drawable.pic_pig_main, false)); 19 | data.add(new PetInfo(AppConstants.PET_COW, "Abbi", "A docile cow", R.drawable.pic_cow_main, false)); 20 | data.add(new PetInfo(AppConstants.PET_BIRD, "Pear", "A cute bird", R.drawable.pic_bird_main, false)); 21 | return data; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/viewholder/RVMainViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.viewholder; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | import android.support.v7.widget.SwitchCompat; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.rdc.goospet.R; 10 | 11 | /** 12 | * Created by Goo on 2016-10-19. 13 | */ 14 | 15 | public class RVMainViewHolder extends RecyclerView.ViewHolder { 16 | public TextView tvTitle; 17 | public TextView tvDescription; 18 | public SwitchCompat swSelect; 19 | public ImageView ivItemPic; 20 | 21 | public RVMainViewHolder(View itemView) { 22 | super(itemView); 23 | tvTitle = (TextView) itemView.findViewById(R.id.tv_title_item); 24 | tvDescription = (TextView) itemView.findViewById(R.id.tv_description); 25 | swSelect = (SwitchCompat) itemView.findViewById(R.id.sw_select); 26 | ivItemPic = (ImageView) itemView.findViewById(R.id.iv_item_pic); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 12 | 13 | 14 | 15 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/adapter/IntroFragmentAdapter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentStatePagerAdapter; 6 | 7 | import com.rdc.goospet.base.BaseIntroFragment; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * Created by Goo on 2016-8-31. 13 | */ 14 | public class IntroFragmentAdapter extends FragmentStatePagerAdapter { 15 | 16 | private List mFragments = null; 17 | 18 | public IntroFragmentAdapter(FragmentManager fm, List fragments) { 19 | super(fm); 20 | mFragments = fragments; 21 | } 22 | 23 | 24 | @Override 25 | public Fragment getItem(int position) { 26 | if (mFragments != null) { 27 | return mFragments.get(position); 28 | } 29 | return null; 30 | 31 | } 32 | 33 | @Override 34 | public int getCount() { 35 | if (mFragments != null) { 36 | return mFragments.size(); 37 | } 38 | return 0; 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | 7 | 40dp 8 | 20dp 9 | 12dp 10 | 10dp 11 | 8dp 12 | 5dp 13 | 14 | 15 | 32sp 16 | 24sp 17 | 22sp 18 | 20sp 19 | 16sp 20 | 14sp 21 | 12sp 22 | 23 | 24 | 84dp 25 | 84dp 26 | 27 | 60000 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/widget/PageIndicator.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.widget; 2 | 3 | import android.support.v4.view.ViewPager; 4 | 5 | /** 6 | * Created by Goo on 2016-8-31. 7 | */ 8 | public interface PageIndicator extends ViewPager.OnPageChangeListener { 9 | /** 10 | * Bind the indicator to a ViewPager. 11 | * 12 | * @param view 13 | */ 14 | void setViewPager(ViewPager view); 15 | 16 | /** 17 | * Bind the indicator to a ViewPager. 18 | * 19 | * @param view 20 | * @param initialPosition 21 | */ 22 | void setViewPager(ViewPager view, int initialPosition); 23 | 24 | /** 25 | *

Set the current page of both the ViewPager and indicator.

26 | * 27 | *

This must be used if you need to set the page before 28 | * the views are drawn on screen (e.g., default start page).

29 | * 30 | * @param item 31 | */ 32 | void setCurrentItem(int item); 33 | 34 | /** 35 | * Set a page change listener which will receive forwarded events. 36 | * 37 | * @param listener 38 | */ 39 | void setOnPageChangeListener(ViewPager.OnPageChangeListener listener); 40 | 41 | /** 42 | * Notify the indicator that the fragment list has changed. 43 | */ 44 | void notifyDataSetChanged(); 45 | } -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/AppConstants.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import com.rdc.goospet.R; 4 | 5 | /** 6 | * Created by Goo on 2016-8-28. 7 | * 常量管理类 8 | */ 9 | public class AppConstants { 10 | public static final int OUT_PENDING_TRANSITION = 10; 11 | public static final int OPEN_PENDING_TRANSITION = 20; 12 | 13 | public static final int INTRO_TAG_FIRST = 1234; 14 | public static final int INTRO_TAG_SECOND = 2345; 15 | public static final int INTRO_TAG_THIRD = 3456; 16 | public static final int INTRO_TAG_FOURTH = 4567; 17 | 18 | public static final float PARALLAX_COEFFICIENT = 1.2f;//视差系数 19 | public static final float DISTANCE_COEFFICIENT = 0.8f;//距离系数 20 | 21 | public static final int INTRO_ANIMATION_DURATION = 500;//动画时间 22 | public static final int INTRO_ANIMATION_OFFSET = 50;//动画间隔 23 | 24 | public static final int INTRO_START_COLOR = R.color.colorIntroLightPrimary; 25 | public static final int INTRO_END_COLOR = R.color.lightOrange; 26 | 27 | public static final String REGEX_EMAIL = "^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$"; 28 | 29 | public static String USER_NAME = null; 30 | 31 | //petId 32 | public static final int PET_OWL = 1221; 33 | public static final int PET_PIG = 1222; 34 | public static final int PET_COW = 1223; 35 | public static final int PET_BIRD = 1224; 36 | 37 | } 38 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | //解决部分第三方库重复打包了META-INF的问题 5 | packagingOptions { 6 | exclude 'META-INF/LICENSE.txt' 7 | exclude 'META-INF/NOTICE.txt' 8 | } 9 | lintOptions { 10 | abortOnError false 11 | } 12 | 13 | compileSdkVersion 24 14 | buildToolsVersion "24.0.0" 15 | 16 | defaultConfig { 17 | applicationId "com.rdc.goospet" 18 | minSdkVersion 21 19 | targetSdkVersion 24 20 | versionCode 1 21 | versionName "1.0" 22 | } 23 | buildTypes { 24 | release { 25 | minifyEnabled false 26 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 27 | } 28 | } 29 | } 30 | 31 | dependencies { 32 | compile fileTree(dir: 'libs', include: ['*.jar']) 33 | testCompile 'junit:junit:4.12' 34 | compile 'com.android.support:appcompat-v7:24.2.1' 35 | compile 'com.android.support:design:24.2.1' 36 | compile 'fr.erictruong:materialedittext:0.2.0' 37 | // LeanCloud 基础包 38 | compile('cn.leancloud.android:avoscloud-sdk:v3.+') 39 | // LeanCloud 统计包 40 | compile('cn.leancloud.android:avoscloud-statistics:v3.+') 41 | compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha8' 42 | compile 'com.android.support:cardview-v7:24.2.1' 43 | compile 'com.android.support:recyclerview-v7:24.2.1' 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/ParallaxTransformer.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.support.v4.view.ViewPager; 4 | import android.util.SparseArray; 5 | import android.view.View; 6 | 7 | /** 8 | * Created by Goo on 2016-9-1. 9 | */ 10 | public class ParallaxTransformer implements ViewPager.PageTransformer { 11 | 12 | private float mParallaxCoefficient; 13 | private float mDistanceCoefficient; 14 | private SparseArray mLayoutViewIdsMap = null; 15 | 16 | public ParallaxTransformer(float parallaxCoefficient, float distanceCoefficient, SparseArray layoutViewIdsMap) { 17 | mParallaxCoefficient = parallaxCoefficient; 18 | mDistanceCoefficient = distanceCoefficient; 19 | mLayoutViewIdsMap = layoutViewIdsMap; 20 | } 21 | 22 | @Override 23 | public void transformPage(View page, float position) { 24 | float scrollXOffset = page.getWidth() * mParallaxCoefficient; 25 | //简单实现:对view遍历,递增视觉差系数 26 | if (mLayoutViewIdsMap != null) { 27 | int[] layer = mLayoutViewIdsMap.get((int) page.getTag()); 28 | for (int id : layer) { 29 | View view = page.findViewById(id); 30 | if (view != null) { 31 | view.setTranslationX(scrollXOffset * position); 32 | } 33 | scrollXOffset *= mDistanceCoefficient; 34 | } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/res/color/vpi__dark_theme.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/swipeback/SwipeBackPreferenceActivity.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rdc.goospet.swipeback; 3 | 4 | import android.os.Bundle; 5 | import android.preference.PreferenceActivity; 6 | import android.view.View; 7 | 8 | public class SwipeBackPreferenceActivity extends PreferenceActivity implements SwipeBackActivityBase { 9 | private SwipeBackActivityHelper mHelper; 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | mHelper = new SwipeBackActivityHelper(this); 15 | mHelper.onActivityCreate(); 16 | } 17 | 18 | @Override 19 | protected void onPostCreate(Bundle savedInstanceState) { 20 | super.onPostCreate(savedInstanceState); 21 | mHelper.onPostCreate(); 22 | } 23 | 24 | @Override 25 | public View findViewById(int id) { 26 | View v = super.findViewById(id); 27 | if (v == null && mHelper != null) 28 | return mHelper.findViewById(id); 29 | return v; 30 | } 31 | 32 | @Override 33 | public SwipeBackLayout getSwipeBackLayout() { 34 | return mHelper.getSwipeBackLayout(); 35 | } 36 | @Override 37 | public void setSwipeBackEnable(boolean enable) { 38 | getSwipeBackLayout().setEnableGesture(enable); 39 | } 40 | 41 | @Override 42 | public void scrollToFinishActivity() { 43 | getSwipeBackLayout().scrollToFinishActivity(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/res/color/vpi__light_theme.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__colors.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | #ff000000 18 | #fff3f3f3 19 | @color/vpi__background_holo_light 20 | @color/vpi__background_holo_dark 21 | #ff4c4c4c 22 | #ffb2b2b2 23 | 24 | @color/vpi__bright_foreground_holo_light 25 | 26 | 27 | @color/vpi__bright_foreground_holo_dark 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/entity/PetInfo.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.entity; 2 | 3 | /** 4 | * Created by Goo on 2016-10-19. 5 | */ 6 | 7 | /** 8 | * 宠物信息配置 9 | */ 10 | public class PetInfo { 11 | private int petId; 12 | private boolean isSelected;//选中 13 | private int picId;//图片资源 14 | private String name;//名字 15 | private String description;//描述 16 | 17 | public PetInfo(int petId, String name, String description, int picId, boolean isSelected) { 18 | this.petId = petId; 19 | this.name = name; 20 | this.description = description; 21 | this.picId = picId; 22 | this.isSelected = isSelected; 23 | } 24 | 25 | public boolean isSelected() { 26 | return isSelected; 27 | } 28 | 29 | public void setSelected(boolean selected) { 30 | isSelected = selected; 31 | } 32 | 33 | public int getPicId() { 34 | return picId; 35 | } 36 | 37 | public void setPicId(int picId) { 38 | this.picId = picId; 39 | } 40 | 41 | public String getName() { 42 | return name; 43 | } 44 | 45 | public void setName(String name) { 46 | this.name = name; 47 | } 48 | 49 | public String getDescription() { 50 | return description; 51 | } 52 | 53 | public void setDescription(String description) { 54 | this.description = description; 55 | } 56 | 57 | 58 | public int getPetId() { 59 | return petId; 60 | } 61 | 62 | public void setPetId(int petId) { 63 | this.petId = petId; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/service/FloatingPetService.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.service; 2 | 3 | import android.app.ActivityManager; 4 | import android.app.Service; 5 | import android.content.Context; 6 | import android.content.Intent; 7 | import android.os.IBinder; 8 | import android.support.annotation.Nullable; 9 | 10 | import com.rdc.goospet.utils.FloatingRefreshTask; 11 | import com.rdc.goospet.utils.LogUtils; 12 | 13 | import java.util.Timer; 14 | 15 | /** 16 | * Created by Goo on 2016-9-18. 17 | */ 18 | public class FloatingPetService extends Service { 19 | private Timer mTimer = null; 20 | 21 | @Nullable 22 | @Override 23 | public IBinder onBind(Intent intent) { 24 | return null; 25 | } 26 | 27 | @Override 28 | public void onCreate() { 29 | LogUtils.e("FloatingPetService - onCreate"); 30 | super.onCreate(); 31 | } 32 | 33 | @Override 34 | public int onStartCommand(Intent intent, int flags, int startId) { 35 | LogUtils.e("FloatingPetService - onStartCommand"); 36 | if (mTimer == null) { 37 | mTimer = new Timer(); 38 | mTimer.scheduleAtFixedRate(new FloatingRefreshTask(this.getPackageManager(), (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE), getApplicationContext()), 0, 500); 39 | } 40 | return super.onStartCommand(intent, flags, startId); 41 | } 42 | 43 | @Override 44 | public void onDestroy() { 45 | LogUtils.e("FloatingPetService - onDestroy"); 46 | mTimer.cancel(); 47 | mTimer = null; 48 | super.onDestroy(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | Goo\'s Pet 3 | 登录 4 | 注册 5 | 你好,很高兴,\n在恰逢其时,遇见你。 6 | 我很笨,没有很大很大的梦想,\n只希望能跟你在一起。 7 | 你是我的注定,我要努力,\n有朝一日成为你的得力助手! 8 | 我们的故事,\n即刻开始。 9 | 登录 10 | 密码 11 | 再输一次密码 12 | 用户名 13 | 社交帐号登录 14 | 注册 15 | 信息不可为空 16 | 两次输入密码不相同 17 | 请输入正确的邮箱 18 | 网络连接中,请稍候 19 | 用户名已存在 20 | 邮箱已被注册 21 | 网络连接失败 22 | 注册成功 23 | E-mail 24 | 用户名或密码不正确 25 | 26 | 27 | 28 | @string/intro_first 29 | @string/intro_second 30 | @string/intro_third 31 | @string/intro_fourth 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 19 | 22 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/FloatingRefreshTask.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.content.pm.PackageManager; 6 | import android.os.Handler; 7 | 8 | import java.util.TimerTask; 9 | 10 | /** 11 | * Created by Goo on 2016-9-18. 12 | */ 13 | public class FloatingRefreshTask extends TimerTask { 14 | private PackageManager mPackageManager; 15 | private ActivityManager mActivityManager; 16 | private Context mContext; 17 | private Handler handler = new Handler(); 18 | 19 | public FloatingRefreshTask(PackageManager packageManager, ActivityManager activityManager, Context context) { 20 | mPackageManager = packageManager; 21 | mActivityManager = activityManager; 22 | mContext = context; 23 | } 24 | 25 | @Override 26 | public void run() { 27 | //当前界面为桌面且没有显示悬浮窗,则显示悬浮窗,否则移除悬浮窗 28 | if (FloatingUtils.isHome(mActivityManager, mPackageManager) && !FloatingPetManager.isFloatingWindowShowing()) { 29 | handler.post(new Runnable() { 30 | @Override 31 | public void run() { 32 | FloatingPetManager.createPetWindow(mContext); 33 | } 34 | }); 35 | } 36 | //当前界面不为桌面,而有显示悬浮窗,需要移除悬浮窗 37 | if (!FloatingUtils.isHome(mActivityManager, mPackageManager) && FloatingPetManager.isFloatingWindowShowing()) { 38 | 39 | } 40 | //当前界面为桌面,有显示悬浮窗,需要内容更新 41 | if (FloatingUtils.isHome(mActivityManager, mPackageManager) && FloatingPetManager.isFloatingWindowShowing()) { 42 | 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/model/IntroModel.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.model; 2 | 3 | import android.util.SparseArray; 4 | 5 | import com.rdc.goospet.base.BaseIntroFragment; 6 | import com.rdc.goospet.model.minterface.IntroMInterface; 7 | import com.rdc.goospet.view.fragment.IntroFirstFragment; 8 | import com.rdc.goospet.view.fragment.IntroFourthFragment; 9 | import com.rdc.goospet.view.fragment.IntroSecondFragment; 10 | import com.rdc.goospet.view.fragment.IntroThirdFragment; 11 | 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | /** 16 | * Created by Goo on 2016-8-31. 17 | */ 18 | public class IntroModel implements IntroMInterface { 19 | private static List list = null; 20 | private static SparseArray layoutViewIdsMap = null; 21 | 22 | @Override 23 | public List getIntroFragemnts() { 24 | if (list == null) { 25 | list = new ArrayList<>(); 26 | list.add(new IntroFirstFragment()); 27 | list.add(new IntroSecondFragment()); 28 | list.add(new IntroThirdFragment()); 29 | list.add(new IntroFourthFragment()); 30 | } 31 | return list; 32 | } 33 | 34 | @Override 35 | public SparseArray getLayoutViewIdsMap() { 36 | if (list != null && layoutViewIdsMap == null) { 37 | layoutViewIdsMap = new SparseArray(); 38 | for (int i = 0; i < list.size(); i++) { 39 | layoutViewIdsMap.put(list.get(i).getViewTag(), list.get(i).getChildViewIds()); 40 | } 41 | return layoutViewIdsMap; 42 | } 43 | return null; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/listener/HidingScrollListener.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.listener; 2 | 3 | import android.support.v7.widget.LinearLayoutManager; 4 | import android.support.v7.widget.RecyclerView; 5 | 6 | /** 7 | * 滚动隐藏功能接口 - RecyclerView.OnScrollListener 8 | */ 9 | public abstract class HidingScrollListener extends RecyclerView.OnScrollListener { 10 | 11 | private static final int HIDE_THRESHOLD = 20; 12 | 13 | private int mScrolledDistance = 0; 14 | private boolean mControlsVisible = true; 15 | 16 | 17 | @Override 18 | public void onScrolled(RecyclerView recyclerView, int dx, int dy) { 19 | super.onScrolled(recyclerView, dx, dy); 20 | 21 | int firstVisibleItem = ((LinearLayoutManager) recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); 22 | 23 | if (firstVisibleItem == 0) { 24 | if (!mControlsVisible) { 25 | onShow(); 26 | mControlsVisible = true; 27 | } 28 | } else { 29 | if (mScrolledDistance > HIDE_THRESHOLD && mControlsVisible) { 30 | onHide(); 31 | mControlsVisible = false; 32 | mScrolledDistance = 0; 33 | } else if (mScrolledDistance < -HIDE_THRESHOLD && !mControlsVisible) { 34 | onShow(); 35 | mControlsVisible = true; 36 | mScrolledDistance = 0; 37 | } 38 | } 39 | if ((mControlsVisible && dy > 0) || (!mControlsVisible && dy < 0)) { 40 | mScrolledDistance += dy; 41 | } 42 | } 43 | 44 | public abstract void onHide(); 45 | 46 | public abstract void onShow(); 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/base/BaseSwipeBackActivity.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rdc.goospet.base; 3 | 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.rdc.goospet.swipeback.SwipeBackActivityBase; 8 | import com.rdc.goospet.swipeback.SwipeBackActivityHelper; 9 | import com.rdc.goospet.swipeback.SwipeBackLayout; 10 | import com.rdc.goospet.swipeback.Utils; 11 | 12 | 13 | public abstract class BaseSwipeBackActivity> extends BaseActivity implements SwipeBackActivityBase { 14 | private SwipeBackActivityHelper mHelper; 15 | 16 | @Override 17 | public void onCreate(Bundle savedInstanceState) { 18 | super.onCreate(savedInstanceState); 19 | mHelper = new SwipeBackActivityHelper(this); 20 | mHelper.onActivityCreate(); 21 | } 22 | 23 | @Override 24 | protected void onPostCreate(Bundle savedInstanceState) { 25 | super.onPostCreate(savedInstanceState); 26 | mHelper.onPostCreate(); 27 | } 28 | 29 | @Override 30 | public View findViewById(int id) { 31 | View v = super.findViewById(id); 32 | if (v == null && mHelper != null) 33 | return mHelper.findViewById(id); 34 | return v; 35 | } 36 | 37 | @Override 38 | public SwipeBackLayout getSwipeBackLayout() { 39 | return mHelper.getSwipeBackLayout(); 40 | } 41 | 42 | @Override 43 | public void setSwipeBackEnable(boolean enable) { 44 | getSwipeBackLayout().setEnableGesture(enable); 45 | } 46 | 47 | @Override 48 | public void scrollToFinishActivity() { 49 | Utils.convertActivityToTranslucent(this); 50 | getSwipeBackLayout().scrollToFinishActivity(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/DimenUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.content.Context; 4 | 5 | /** 6 | * 尺寸工具类 7 | * Created by Goo on 2016-10-24. 8 | */ 9 | 10 | public class DimenUtils { 11 | /** 12 | * dp -> px 13 | * 14 | * @param context 15 | * @param dipValue 16 | * @return 17 | */ 18 | public static int dip2px(Context context, float dipValue) { 19 | final float scale = context.getResources().getDisplayMetrics().density; 20 | return (int) (dipValue * scale + 0.5f); 21 | } 22 | 23 | /** 24 | * px -> dp 25 | * 26 | * @param context 27 | * @param px 28 | * @return 29 | */ 30 | public static int px2dp(Context context, float px) { 31 | final float scale = context.getResources().getDisplayMetrics().density; 32 | return (int) (px / scale + 0.5f); 33 | } 34 | 35 | /** 36 | * 获取状态栏高度 37 | * 38 | * @param context 39 | * @return 40 | */ 41 | public static int getAppBarHeight(Context context) { 42 | return DimenUtils.dip2px(context, 56) + getStatusBarHeight(context); 43 | } 44 | 45 | /** 46 | * 获取状态栏高度 47 | * 48 | * @return 49 | */ 50 | public static int getStatusBarHeight(Context context) { 51 | 52 | return context.getResources().getDimensionPixelSize(context.getResources().getIdentifier("status_bar_height", "dimen", "android")); 53 | } 54 | 55 | /** 56 | * 获取底部操作栏高度 57 | * 58 | * @param context 59 | * @return 60 | */ 61 | public static int getNavBarHeight(Context context) { 62 | return context.getResources().getDimensionPixelSize(context.getResources().getIdentifier("navigation_bar_height", "dimen", "android")); 63 | 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/swipeback/SwipeBackActivityHelper.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.swipeback; 2 | 3 | import android.app.Activity; 4 | import android.graphics.Color; 5 | import android.graphics.drawable.ColorDrawable; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | 9 | import com.rdc.goospet.R; 10 | 11 | 12 | public class SwipeBackActivityHelper { 13 | private Activity mActivity; 14 | 15 | private SwipeBackLayout mSwipeBackLayout; 16 | 17 | public SwipeBackActivityHelper(Activity activity) { 18 | mActivity = activity; 19 | } 20 | 21 | @SuppressWarnings("deprecation") 22 | public void onActivityCreate() { 23 | mActivity.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 24 | mActivity.getWindow().getDecorView().setBackgroundDrawable(null); 25 | mSwipeBackLayout = (SwipeBackLayout) LayoutInflater.from(mActivity).inflate( 26 | R.layout.layout_swipeback, null); 27 | mSwipeBackLayout.addSwipeListener(new SwipeBackLayout.SwipeListener() { 28 | @Override 29 | public void onScrollStateChange(int state, float scrollPercent) { 30 | } 31 | 32 | @Override 33 | public void onEdgeTouch(int edgeFlag) { 34 | Utils.convertActivityToTranslucent(mActivity); 35 | } 36 | 37 | @Override 38 | public void onScrollOverThreshold() { 39 | 40 | } 41 | }); 42 | } 43 | 44 | public void onPostCreate() { 45 | mSwipeBackLayout.attachToActivity(mActivity); 46 | } 47 | 48 | public View findViewById(int id) { 49 | if (mSwipeBackLayout != null) { 50 | return mSwipeBackLayout.findViewById(id); 51 | } 52 | return null; 53 | } 54 | 55 | public SwipeBackLayout getSwipeBackLayout() { 56 | return mSwipeBackLayout; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 30 | 31 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/listener/IntroPageChangedListener.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.listener; 2 | 3 | import android.animation.ArgbEvaluator; 4 | import android.content.res.Resources; 5 | import android.support.v4.view.ViewPager; 6 | import android.widget.TextSwitcher; 7 | 8 | import com.rdc.goospet.R; 9 | import com.rdc.goospet.utils.AppConstants; 10 | 11 | /** 12 | * Created by Goo on 2016-9-2. 13 | */ 14 | public class IntroPageChangedListener implements ViewPager.OnPageChangeListener { 15 | private ArgbEvaluator mColorEvaluator; 16 | 17 | private int mPageWidth, mTotalScrollWidth; 18 | 19 | private int mGuideStartBackgroundColor, mGuideEndBackgroundColor; 20 | 21 | private ViewPager mVp; 22 | 23 | private TextSwitcher mTSwitcher; 24 | private String[] mIntroTips; 25 | 26 | public IntroPageChangedListener(ViewPager vp, TextSwitcher tSwitcher, int pageWidth, int pageNum, Resources resources) { 27 | mVp = vp; 28 | mTSwitcher = tSwitcher; 29 | mColorEvaluator = new ArgbEvaluator(); 30 | 31 | mPageWidth = pageWidth; 32 | mTotalScrollWidth = mPageWidth * pageNum; 33 | 34 | mGuideStartBackgroundColor = resources.getColor(AppConstants.INTRO_START_COLOR); 35 | mGuideEndBackgroundColor = resources.getColor(AppConstants.INTRO_END_COLOR); 36 | 37 | mIntroTips = resources.getStringArray(R.array.array_intro_tips); 38 | } 39 | 40 | @Override 41 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 42 | float ratio = (mPageWidth * position + positionOffsetPixels) / (float) mTotalScrollWidth; 43 | Integer color = (Integer) mColorEvaluator.evaluate(ratio, mGuideStartBackgroundColor, mGuideEndBackgroundColor); 44 | mVp.setBackgroundColor(color); 45 | } 46 | 47 | @Override 48 | public void onPageSelected(int position) { 49 | 50 | mTSwitcher.setText(mIntroTips[position]); 51 | } 52 | 53 | @Override 54 | public void onPageScrollStateChanged(int state) { 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/FloatingUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Intent; 5 | import android.content.pm.PackageManager; 6 | import android.content.pm.ResolveInfo; 7 | import android.view.View; 8 | 9 | import java.lang.reflect.Field; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | /** 14 | * Created by Goo on 2016-9-18. 15 | */ 16 | public class FloatingUtils { 17 | 18 | /** 19 | * 判断是否在桌面 20 | * 21 | * @param manager 22 | * @param packageManager 23 | * @return 24 | */ 25 | public static boolean isHome(ActivityManager manager, PackageManager packageManager) { 26 | List rti = manager.getRunningTasks(1); 27 | return getHomes(packageManager).contains(rti.get(0).topActivity.getPackageName()); 28 | } 29 | 30 | /** 31 | * 获得属于桌面的应用的应用包名称 32 | * 33 | * @return 返回包含所有包名的字符串列表 34 | */ 35 | private static List getHomes(PackageManager packageManager) { 36 | List names = new ArrayList(); 37 | Intent intent = new Intent(Intent.ACTION_MAIN); 38 | intent.addCategory(Intent.CATEGORY_HOME); 39 | List resolveInfo = packageManager.queryIntentActivities(intent, 40 | PackageManager.MATCH_DEFAULT_ONLY); 41 | for (ResolveInfo ri : resolveInfo) { 42 | names.add(ri.activityInfo.packageName); 43 | } 44 | return names; 45 | } 46 | 47 | /** 48 | * 用于获取状态栏的高度。 49 | * 50 | * @return 返回状态栏高度的像素值。 51 | */ 52 | public static int getStatusBarHeight(View view) { 53 | try { 54 | Class c = Class.forName("com.android.internal.R$dimen"); 55 | Object o = c.newInstance(); 56 | Field field = c.getField("status_bar_height"); 57 | int x = (Integer) field.get(o); 58 | return view.getResources().getDimensionPixelSize(x); 59 | } catch (Exception e) { 60 | e.printStackTrace(); 61 | } 62 | return -1; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__styles.xml: -------------------------------------------------------------------------------- 1 | 15 | 16 | 17 | 18 | 22 | 23 | 24 | 25 | 36 | 37 | 41 | 42 | 46 | 47 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/vpi__tab_indicator.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/SpUtils.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.content.Context; 4 | import android.content.SharedPreferences; 5 | 6 | /** 7 | * Created by Goo on 2016-8-28. 8 | * SharedPreferences 工具类 9 | */ 10 | public class SpUtils { 11 | 12 | private static final String FILE_NAME = "pet_date"; 13 | 14 | /** 15 | * 保存数据的方法,我们需要拿到保存数据的具体类型,然后根据类型调用不同的保存方法 16 | * 17 | * @param context 18 | * @param key 19 | * @param object 20 | */ 21 | public static void setParam(Context context, String key, Object object) { 22 | 23 | String type = object.getClass().getSimpleName(); 24 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 25 | SharedPreferences.Editor editor = sp.edit(); 26 | 27 | if ("String".equals(type)) { 28 | editor.putString(key, (String) object); 29 | } else if ("Integer".equals(type)) { 30 | editor.putInt(key, (Integer) object); 31 | } else if ("Boolean".equals(type)) { 32 | editor.putBoolean(key, (Boolean) object); 33 | } else if ("Float".equals(type)) { 34 | editor.putFloat(key, (Float) object); 35 | } else if ("Long".equals(type)) { 36 | editor.putLong(key, (Long) object); 37 | } 38 | 39 | editor.commit(); 40 | } 41 | 42 | 43 | /** 44 | * 得到保存数据的方法,我们根据默认值得到保存的数据的具体类型,然后调用相对于的方法获取值 45 | * 46 | * @param context 47 | * @param key 48 | * @param defaultObject 49 | * @return 50 | */ 51 | public static Object getParam(Context context, String key, Object defaultObject) { 52 | String type = defaultObject.getClass().getSimpleName(); 53 | SharedPreferences sp = context.getSharedPreferences(FILE_NAME, Context.MODE_PRIVATE); 54 | 55 | if ("String".equals(type)) { 56 | return sp.getString(key, (String) defaultObject); 57 | } else if ("Integer".equals(type)) { 58 | return sp.getInt(key, (Integer) defaultObject); 59 | } else if ("Boolean".equals(type)) { 60 | return sp.getBoolean(key, (Boolean) defaultObject); 61 | } else if ("Float".equals(type)) { 62 | return sp.getFloat(key, (Float) defaultObject); 63 | } else if ("Long".equals(type)) { 64 | return sp.getLong(key, (Long) defaultObject); 65 | } 66 | 67 | return null; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/fragment/IntroFourthFragment.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.animation.Animation; 9 | import android.view.animation.AnimationUtils; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.base.BaseIntroFragment; 13 | import com.rdc.goospet.utils.AppConstants; 14 | 15 | /** 16 | * Created by Goo on 2016-9-1. 17 | */ 18 | public class IntroFourthFragment extends BaseIntroFragment { 19 | 20 | private int[] mAnimationViewIds = { 21 | R.id.iv_intro_1, R.id.iv_intro_2, R.id.iv_intro_3, 22 | R.id.iv_intro_4, R.id.iv_intro_5, R.id.iv_intro_6, R.id.iv_intro_7, R.id.iv_intro_8 23 | }; 24 | 25 | @Override 26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 27 | View rootView = inflater.inflate(R.layout.fragment_intro_first, container, false); 28 | rootView.setTag(AppConstants.INTRO_TAG_FOURTH); 29 | return rootView; 30 | } 31 | 32 | @Override 33 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 34 | super.onViewCreated(view, savedInstanceState); 35 | initAnim(view); 36 | } 37 | 38 | /** 39 | * 为intro元素添加动画 40 | * 41 | * @param view 42 | */ 43 | private void initAnim(View view) { 44 | for (int i = 0; i < mAnimationViewIds.length; i++) { 45 | Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.splash_intro_items); 46 | animation.setDuration(AppConstants.INTRO_ANIMATION_DURATION); 47 | animation.setStartOffset(AppConstants.INTRO_ANIMATION_OFFSET * i); 48 | view.findViewById(mAnimationViewIds[i]).startAnimation(animation); 49 | } 50 | } 51 | 52 | @Override 53 | public int[] getChildViewIds() { 54 | return new int[]{ 55 | R.id.iv_intro_1, 56 | R.id.iv_intro_2, 57 | R.id.iv_intro_3, 58 | R.id.iv_intro_4, 59 | R.id.iv_intro_5, 60 | R.id.iv_intro_6, 61 | R.id.iv_intro_7, R.id.iv_intro_8 62 | }; 63 | } 64 | 65 | @Override 66 | public int getViewTag() { 67 | return AppConstants.INTRO_TAG_FOURTH; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/fragment/IntroThirdFragment.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.animation.Animation; 9 | import android.view.animation.AnimationUtils; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.base.BaseIntroFragment; 13 | import com.rdc.goospet.utils.AppConstants; 14 | 15 | /** 16 | * Created by Goo on 2016-9-1. 17 | */ 18 | public class IntroThirdFragment extends BaseIntroFragment { 19 | 20 | private int[] mAnimationViewIds = { 21 | R.id.iv_intro_1, R.id.iv_intro_2, R.id.iv_intro_3, 22 | R.id.iv_intro_4, R.id.iv_intro_5, R.id.iv_intro_6, R.id.iv_intro_7, R.id.iv_intro_8 23 | }; 24 | 25 | @Override 26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 27 | View rootView = inflater.inflate(R.layout.fragment_intro_first, container, false); 28 | rootView.setTag(AppConstants.INTRO_TAG_THIRD); 29 | 30 | return rootView; 31 | } 32 | 33 | @Override 34 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | initAnim(view); 37 | } 38 | 39 | /** 40 | * 为intro元素添加动画 41 | * 42 | * @param view 43 | */ 44 | private void initAnim(View view) { 45 | for (int i = 0; i < mAnimationViewIds.length; i++) { 46 | Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.splash_intro_items); 47 | animation.setDuration(AppConstants.INTRO_ANIMATION_DURATION); 48 | animation.setStartOffset(AppConstants.INTRO_ANIMATION_OFFSET * i); 49 | view.findViewById(mAnimationViewIds[i]).startAnimation(animation); 50 | } 51 | } 52 | 53 | @Override 54 | public int[] getChildViewIds() { 55 | return new int[]{ 56 | R.id.iv_intro_1, 57 | R.id.iv_intro_2, 58 | R.id.iv_intro_3, 59 | R.id.iv_intro_4, 60 | R.id.iv_intro_5, 61 | R.id.iv_intro_6, 62 | R.id.iv_intro_7, R.id.iv_intro_8 63 | }; 64 | } 65 | 66 | @Override 67 | public int getViewTag() { 68 | return AppConstants.INTRO_TAG_THIRD; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/fragment/IntroSecondFragment.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.animation.Animation; 9 | import android.view.animation.AnimationUtils; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.base.BaseIntroFragment; 13 | import com.rdc.goospet.utils.AppConstants; 14 | 15 | /** 16 | * Created by Goo on 2016-9-1. 17 | */ 18 | public class IntroSecondFragment extends BaseIntroFragment { 19 | 20 | 21 | private int[] mAnimationViewIds = { 22 | R.id.iv_intro_1, R.id.iv_intro_2, R.id.iv_intro_3, 23 | R.id.iv_intro_4, R.id.iv_intro_5, R.id.iv_intro_6, R.id.iv_intro_7, R.id.iv_intro_8 24 | }; 25 | 26 | @Override 27 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 28 | View rootView = inflater.inflate(R.layout.fragment_intro_first, container, false); 29 | rootView.setTag(AppConstants.INTRO_TAG_SECOND); 30 | return rootView; 31 | } 32 | 33 | @Override 34 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 35 | super.onViewCreated(view, savedInstanceState); 36 | initAnim(view); 37 | } 38 | 39 | /** 40 | * 为intro元素添加动画 41 | * 42 | * @param view 43 | */ 44 | private void initAnim(View view) { 45 | for (int i = 0; i < mAnimationViewIds.length; i++) { 46 | Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.splash_intro_items); 47 | animation.setDuration(AppConstants.INTRO_ANIMATION_DURATION); 48 | animation.setStartOffset(AppConstants.INTRO_ANIMATION_OFFSET * i); 49 | view.findViewById(mAnimationViewIds[i]).startAnimation(animation); 50 | } 51 | } 52 | 53 | @Override 54 | public int[] getChildViewIds() { 55 | return new int[]{ 56 | R.id.iv_intro_1, 57 | R.id.iv_intro_2, 58 | R.id.iv_intro_3, 59 | R.id.iv_intro_4, 60 | R.id.iv_intro_5, 61 | R.id.iv_intro_6, 62 | R.id.iv_intro_7, R.id.iv_intro_8 63 | }; 64 | } 65 | 66 | @Override 67 | public int getViewTag() { 68 | return AppConstants.INTRO_TAG_SECOND; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/utils/FloatingPetManager.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.utils; 2 | 3 | import android.content.Context; 4 | import android.graphics.PixelFormat; 5 | import android.view.Gravity; 6 | import android.view.WindowManager; 7 | 8 | import com.rdc.goospet.view.widget.FloatingPetView; 9 | 10 | /** 11 | * 悬浮宠物管理类 12 | * Created by Goo on 2016-9-18. 13 | */ 14 | public class FloatingPetManager { 15 | 16 | /** 17 | * 悬浮宠物实例 18 | */ 19 | private static FloatingPetView mFPetView; 20 | 21 | /** 22 | * 增添及删除悬浮窗 23 | */ 24 | private static WindowManager mWindowManager; 25 | 26 | /** 27 | * 参数 28 | */ 29 | private static WindowManager.LayoutParams mParams; 30 | 31 | /** 32 | * 创建悬浮宠物 33 | * 34 | * @param context 35 | */ 36 | public static void createPetWindow(Context context) { 37 | WindowManager windowManager = getWindowManager(context); 38 | int screenWidth = windowManager.getDefaultDisplay().getWidth(); 39 | int screenHeight = windowManager.getDefaultDisplay().getHeight(); 40 | if (mFPetView == null) { 41 | mFPetView = new FloatingPetView(context); 42 | if (mParams == null) { 43 | mParams = new WindowManager.LayoutParams(); 44 | mParams.type = WindowManager.LayoutParams.TYPE_PHONE; 45 | mParams.format = PixelFormat.RGBA_8888; 46 | mParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 47 | | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; 48 | mParams.gravity = Gravity.LEFT | Gravity.TOP; 49 | mParams.width = mFPetView.viewWidth; 50 | mParams.height = mFPetView.viewHeight; 51 | mParams.x = screenWidth; 52 | mParams.y = screenHeight / 2; 53 | } 54 | mFPetView.setParams(mParams); 55 | windowManager.addView(mFPetView, mParams); 56 | } 57 | } 58 | 59 | private static WindowManager getWindowManager(Context context) { 60 | if (mWindowManager == null) { 61 | mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 62 | } 63 | return mWindowManager; 64 | } 65 | 66 | /** 67 | * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。 68 | * 69 | * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。 70 | */ 71 | public static boolean isFloatingWindowShowing() { 72 | return mFPetView != null; 73 | } 74 | 75 | 76 | } 77 | -------------------------------------------------------------------------------- /app/src/main/res/layout-xlarge/layout_rv_item_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 29 | 30 | 40 | 41 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/fragment/IntroFirstFragment.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.view.animation.Animation; 9 | import android.view.animation.AnimationUtils; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.base.BaseIntroFragment; 13 | import com.rdc.goospet.utils.AppConstants; 14 | 15 | /** 16 | * Created by Goo on 2016-9-1. 17 | */ 18 | public class IntroFirstFragment extends BaseIntroFragment { 19 | 20 | private int[] mAnimationViewIds = { 21 | R.id.iv_intro_1, R.id.iv_intro_2, R.id.iv_intro_3, 22 | R.id.iv_intro_4, R.id.iv_intro_5, R.id.iv_intro_6, R.id.iv_intro_7, R.id.iv_intro_8 23 | }; 24 | 25 | @Override 26 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 27 | View rootView = inflater.inflate(R.layout.fragment_intro_first, container, false); 28 | rootView.setTag(AppConstants.INTRO_TAG_FIRST); 29 | return rootView; 30 | } 31 | 32 | @Override 33 | public void setUserVisibleHint(boolean isVisibleToUser) { 34 | super.setUserVisibleHint(isVisibleToUser); 35 | } 36 | 37 | @Override 38 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { 39 | super.onViewCreated(view, savedInstanceState); 40 | initAnim(view); 41 | } 42 | 43 | /** 44 | * 为intro元素添加动画 45 | * 46 | * @param view 47 | */ 48 | private void initAnim(View view) { 49 | for (int i = 0; i < mAnimationViewIds.length; i++) { 50 | Animation animation = AnimationUtils.loadAnimation(getActivity(), R.anim.splash_intro_items); 51 | animation.setDuration(AppConstants.INTRO_ANIMATION_DURATION); 52 | animation.setStartOffset(AppConstants.INTRO_ANIMATION_OFFSET * i); 53 | view.findViewById(mAnimationViewIds[i]).startAnimation(animation); 54 | } 55 | } 56 | 57 | @Override 58 | public int[] getChildViewIds() { 59 | return new int[]{ 60 | R.id.iv_intro_1, 61 | R.id.iv_intro_2, 62 | R.id.iv_intro_3, 63 | R.id.iv_intro_4, 64 | R.id.iv_intro_5, 65 | R.id.iv_intro_6, 66 | R.id.iv_intro_7, 67 | R.id.iv_intro_8 68 | 69 | }; 70 | } 71 | 72 | 73 | @Override 74 | public int getViewTag() { 75 | return AppConstants.INTRO_TAG_FIRST; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog_login.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 34 | 35 | 44 | 45 | 54 | 55 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__defaults.xml: -------------------------------------------------------------------------------- 1 | 2 | 16 | 17 | 18 | true 19 | #FFFFFFFF 20 | #00000000 21 | 0 22 | 3dp 23 | false 24 | #FFDDDDDD 25 | 1dp 26 | 27 | 12dp 28 | 4dp 29 | 1dp 30 | #FF33B5E5 31 | #FFBBBBBB 32 | true 33 | 34 | 4dp 35 | #FF33B5E5 36 | 2dp 37 | 2 38 | 4dp 39 | 20dp 40 | 7dp 41 | 0 42 | #FFFFFFFF 43 | true 44 | #BBFFFFFF 45 | 15dp 46 | 5dp 47 | 7dp 48 | 49 | true 50 | 300 51 | 400 52 | #FF33B5E5 53 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_rv_item_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 16 | 17 | 27 | 28 | 47 | 48 | 61 | 62 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_dialog_register.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 21 | 22 | 33 | 34 | 46 | 47 | 59 | 60 | 61 | 70 | 71 | 72 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/presenter/MainPresenter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.presenter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.support.v7.widget.helper.ItemTouchHelper; 6 | import android.view.View; 7 | import android.widget.CompoundButton; 8 | 9 | import com.rdc.goospet.adapter.RVMainAdapter; 10 | import com.rdc.goospet.base.BasePresenter; 11 | import com.rdc.goospet.entity.PetInfo; 12 | import com.rdc.goospet.model.MainModel; 13 | import com.rdc.goospet.model.minterface.MainMInterface; 14 | import com.rdc.goospet.utils.AppConstants; 15 | import com.rdc.goospet.utils.ToastUtil; 16 | import com.rdc.goospet.view.vinterface.MainVInterface; 17 | 18 | /** 19 | * Created by Goo on 2016-9-18. 20 | */ 21 | public class MainPresenter extends BasePresenter { 22 | 23 | private MainMInterface mModel; 24 | 25 | public MainPresenter(MainVInterface viewInterface) { 26 | super(viewInterface); 27 | mModel = new MainModel(); 28 | } 29 | 30 | /** 31 | * 获取已配置的RVAdapter 32 | * 33 | * @param context 34 | * @return 35 | */ 36 | public RVMainAdapter getRVAdapter(final Context context) { 37 | RVMainAdapter adapter = new RVMainAdapter(context, mModel.getPetData()); 38 | adapter.setOnRvItemClickListener(new RVMainAdapter.OnRvItemClickListener() { 39 | @Override 40 | public void onItemClick(View view, PetInfo petInfo) { 41 | ToastUtil.showToast(context, "PetInfo:" + petInfo.getName() + "\n" + petInfo.getDescription()); 42 | } 43 | }); 44 | adapter.setOnPetSelectedListener(new RVMainAdapter.OnPetSelectedListener() { 45 | 46 | @Override 47 | public void onPetSelected(CompoundButton buttonView, int petId) { 48 | boolean isCheck = buttonView.isChecked(); 49 | if (isCheck) { 50 | view.launchDesktopPet(); 51 | } 52 | switch (petId) { 53 | case AppConstants.PET_BIRD: 54 | break; 55 | case AppConstants.PET_COW: 56 | break; 57 | case AppConstants.PET_PIG: 58 | break; 59 | case AppConstants.PET_OWL: 60 | break; 61 | default: 62 | break; 63 | } 64 | } 65 | }); 66 | return adapter; 67 | } 68 | 69 | 70 | public ItemTouchHelper getItemTouchHelper(final RVMainAdapter adapter) { 71 | return new ItemTouchHelper(new ItemTouchHelper.Callback() { 72 | 73 | @Override 74 | public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { 75 | return makeMovementFlags(ItemTouchHelper.UP | 76 | ItemTouchHelper.DOWN, 0); 77 | } 78 | 79 | @Override 80 | public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { 81 | int fromPosition = viewHolder.getAdapterPosition(); 82 | int toPosition = target.getAdapterPosition(); 83 | adapter.swapData(fromPosition, toPosition); 84 | return true; 85 | } 86 | 87 | @Override 88 | public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { 89 | } 90 | 91 | @Override 92 | public boolean isLongPressDragEnabled() { 93 | return true; 94 | } 95 | 96 | }); 97 | } 98 | 99 | 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/presenter/IntroPresenter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.presenter; 2 | 3 | import android.support.v4.app.FragmentManager; 4 | 5 | import com.avos.avoscloud.AVException; 6 | import com.avos.avoscloud.AVUser; 7 | import com.avos.avoscloud.LogInCallback; 8 | import com.avos.avoscloud.SignUpCallback; 9 | import com.rdc.goospet.adapter.IntroFragmentAdapter; 10 | import com.rdc.goospet.base.BasePresenter; 11 | import com.rdc.goospet.model.IntroModel; 12 | import com.rdc.goospet.model.minterface.IntroMInterface; 13 | import com.rdc.goospet.utils.AVOSUtils; 14 | import com.rdc.goospet.utils.AppConstants; 15 | import com.rdc.goospet.utils.ParallaxTransformer; 16 | import com.rdc.goospet.view.vinterface.IntroVInterface; 17 | 18 | import java.util.regex.Pattern; 19 | 20 | /** 21 | * Created by Goo on 2016-8-31. 22 | */ 23 | public class IntroPresenter extends BasePresenter { 24 | 25 | private IntroMInterface mModel; 26 | 27 | public IntroPresenter(IntroVInterface viewInterface) { 28 | super(viewInterface); 29 | mModel = new IntroModel(); 30 | } 31 | 32 | /** 33 | * 获得 introAdapter 34 | * 35 | * @param fm 36 | * @return 37 | */ 38 | public IntroFragmentAdapter getPagerAdapter(FragmentManager fm) { 39 | return new IntroFragmentAdapter(fm, mModel.getIntroFragemnts()); 40 | } 41 | 42 | public ParallaxTransformer getTransformer() { 43 | return new ParallaxTransformer(AppConstants.PARALLAX_COEFFICIENT, AppConstants.DISTANCE_COEFFICIENT, mModel.getLayoutViewIdsMap()); 44 | } 45 | 46 | public void login(final String userName, String psw) { 47 | if (userName.isEmpty() || psw.isEmpty()) { 48 | view.errorEmptyInfo(); 49 | } else { 50 | view.showProgressDialog(); 51 | AVUser.logInInBackground(userName, psw, new LogInCallback() { 52 | @Override 53 | public void done(AVUser avUser, AVException e) { 54 | view.dismissDialog(); 55 | if (avUser != null) { 56 | view.loginSuccess(avUser.getUsername()); 57 | } else { 58 | view.errorLoginFail(); 59 | } 60 | } 61 | }); 62 | } 63 | 64 | } 65 | 66 | public void register(final String userName, String email, String psw, String pswAgain) { 67 | if (userName.isEmpty() || email.isEmpty() || psw.isEmpty() || pswAgain.isEmpty()) { 68 | view.errorEmptyInfo(); 69 | } else if (!psw.equals(pswAgain)) { 70 | view.errorPswNotEqual(); 71 | } else if (!Pattern.compile(AppConstants.REGEX_EMAIL).matcher(email).find()) { 72 | view.errorEmailInvalid(); 73 | } else { 74 | view.showProgressDialog(); 75 | AVOSUtils.signUp(userName, psw, email, new SignUpCallback() { 76 | @Override 77 | public void done(AVException e) { 78 | view.dismissDialog(); 79 | if (e == null) { 80 | view.registerSuccess(userName); 81 | } else { 82 | switch (e.getCode()) { 83 | case 202: 84 | view.errorUserNameRepeat(); 85 | break; 86 | case 203: 87 | view.errorEmailRepeat(); 88 | break; 89 | default: 90 | view.errorNetWork(); 91 | break; 92 | } 93 | } 94 | } 95 | }); 96 | } 97 | 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_intro.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 22 | 23 | 34 | 35 | 45 | 46 | 47 | 48 | 57 | 58 | 59 | 67 | 68 | 79 | 80 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fragment_intro_first.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 13 | 14 | 20 | 21 | 30 | 31 | 39 | 40 | 48 | 49 | 59 | 60 | 68 | 69 | 78 | 79 | 88 | 89 | 90 | 91 | 92 | 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/adapter/RVMainAdapter.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.adapter; 2 | 3 | import android.content.Context; 4 | import android.support.v7.widget.RecyclerView; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.CompoundButton; 9 | import android.widget.ImageView; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.entity.PetInfo; 13 | import com.rdc.goospet.view.viewholder.RVMainViewHolder; 14 | 15 | import java.util.ArrayList; 16 | import java.util.Collections; 17 | 18 | /** 19 | * Adapter - 主界面RecyclerView 20 | * Created by Goo on 2016-10-19. 21 | */ 22 | public class RVMainAdapter extends RecyclerView.Adapter implements View.OnClickListener, CompoundButton.OnCheckedChangeListener { 23 | private Context mContext; 24 | private LayoutInflater mLayoutInflater; 25 | private ArrayList mData; 26 | 27 | public RVMainAdapter(Context context, ArrayList data) { 28 | mContext = context; 29 | mData = data; 30 | mLayoutInflater = LayoutInflater.from(context); 31 | } 32 | 33 | @Override 34 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 35 | View rootView = mLayoutInflater.inflate(R.layout.layout_rv_item_main, parent, false); 36 | RVMainViewHolder holder = new RVMainViewHolder(rootView); 37 | rootView.setOnClickListener(this); 38 | return holder; 39 | } 40 | 41 | @Override 42 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 43 | PetInfo tempInfo = mData.get(position); 44 | if (holder instanceof RVMainViewHolder) { 45 | RVMainViewHolder mainHolder = (RVMainViewHolder) holder; 46 | mainHolder.tvTitle.setText(tempInfo.getName()); 47 | mainHolder.tvDescription.setText(tempInfo.getDescription()); 48 | mainHolder.swSelect.setChecked(tempInfo.isSelected()); 49 | mainHolder.swSelect.setTag(tempInfo.getPicId()); 50 | mainHolder.swSelect.setOnCheckedChangeListener(this); 51 | mainHolder.ivItemPic.setScaleType(ImageView.ScaleType.CENTER_CROP); 52 | mainHolder.ivItemPic.setBackgroundResource(tempInfo.getPicId()); 53 | 54 | holder.itemView.setTag(mData.get(position)); 55 | } 56 | } 57 | 58 | @Override 59 | public int getItemCount() { 60 | return mData.size(); 61 | } 62 | 63 | @Override 64 | public void onClick(View v) { 65 | if (mOnItemClickListener != null) { 66 | mOnItemClickListener.onItemClick(v, (PetInfo) v.getTag()); 67 | } 68 | } 69 | 70 | private OnRvItemClickListener mOnItemClickListener = null; 71 | private OnPetSelectedListener mSelectedListener = null; 72 | 73 | @Override 74 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 75 | if (mSelectedListener != null) { 76 | mSelectedListener.onPetSelected(buttonView, (Integer) buttonView.getTag()); 77 | } 78 | } 79 | 80 | public static interface OnRvItemClickListener { 81 | void onItemClick(View view, PetInfo petInfo); 82 | } 83 | 84 | public static interface OnPetSelectedListener { 85 | void onPetSelected(CompoundButton buttonView, int petId); 86 | } 87 | 88 | public void setOnPetSelectedListener(OnPetSelectedListener listener) { 89 | mSelectedListener = listener; 90 | } 91 | 92 | public void setOnRvItemClickListener(OnRvItemClickListener listener) { 93 | mOnItemClickListener = listener; 94 | } 95 | 96 | public void swapData(int fromPosition, int toPosition) { 97 | if (fromPosition < toPosition) { 98 | for (int i = fromPosition; i < toPosition; i++) { 99 | Collections.swap(mData, i, i + 1); 100 | } 101 | } else { 102 | for (int i = fromPosition; i > toPosition; i--) { 103 | Collections.swap(mData, i, i - 1); 104 | } 105 | } 106 | notifyItemMoved(fromPosition, toPosition); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/swipeback/Utils.java: -------------------------------------------------------------------------------- 1 | 2 | package com.rdc.goospet.swipeback; 3 | 4 | import android.app.Activity; 5 | import android.app.ActivityOptions; 6 | import android.os.Build; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | public class Utils { 11 | private Utils() { 12 | } 13 | 14 | /** 15 | * Convert a translucent themed Activity 16 | * {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque 17 | * Activity. 18 | *

19 | * Call this whenever the background of a translucent Activity has changed 20 | * to become opaque. Doing so will allow the {@link android.view.Surface} of 21 | * the Activity behind to be released. 22 | *

23 | * This call has no effect on non-translucent activities or on activities 24 | * with the {@link android.R.attr#windowIsFloating} attribute. 25 | */ 26 | public static void convertActivityFromTranslucent(Activity activity) { 27 | try { 28 | Method method = Activity.class.getDeclaredMethod("convertFromTranslucent"); 29 | method.setAccessible(true); 30 | method.invoke(activity); 31 | } catch (Throwable t) { 32 | } 33 | } 34 | 35 | /** 36 | * Convert a translucent themed Activity 37 | * {@link android.R.attr#windowIsTranslucent} back from opaque to 38 | * translucent following a call to 39 | * {@link #convertActivityFromTranslucent(Activity)} . 40 | *

41 | * Calling this allows the Activity behind this one to be seen again. Once 42 | * all such Activities have been redrawn 43 | *

44 | * This call has no effect on non-translucent activities or on activities 45 | * with the {@link android.R.attr#windowIsFloating} attribute. 46 | */ 47 | public static void convertActivityToTranslucent(Activity activity) { 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 49 | convertActivityToTranslucentAfterL(activity); 50 | } else { 51 | convertActivityToTranslucentBeforeL(activity); 52 | } 53 | } 54 | 55 | /** 56 | * Calling the convertToTranslucent method on platforms before Android 5.0 57 | */ 58 | public static void convertActivityToTranslucentBeforeL(Activity activity) { 59 | try { 60 | Class[] classes = Activity.class.getDeclaredClasses(); 61 | Class translucentConversionListenerClazz = null; 62 | for (Class clazz : classes) { 63 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 64 | translucentConversionListenerClazz = clazz; 65 | } 66 | } 67 | Method method = Activity.class.getDeclaredMethod("convertToTranslucent", 68 | translucentConversionListenerClazz); 69 | method.setAccessible(true); 70 | method.invoke(activity, new Object[] { 71 | null 72 | }); 73 | } catch (Throwable t) { 74 | } 75 | } 76 | 77 | /** 78 | * Calling the convertToTranslucent method on platforms after Android 5.0 79 | */ 80 | private static void convertActivityToTranslucentAfterL(Activity activity) { 81 | try { 82 | Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions"); 83 | getActivityOptions.setAccessible(true); 84 | Object options = getActivityOptions.invoke(activity); 85 | 86 | Class[] classes = Activity.class.getDeclaredClasses(); 87 | Class translucentConversionListenerClazz = null; 88 | for (Class clazz : classes) { 89 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 90 | translucentConversionListenerClazz = clazz; 91 | } 92 | } 93 | Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent", 94 | translucentConversionListenerClazz, ActivityOptions.class); 95 | convertToTranslucent.setAccessible(true); 96 | convertToTranslucent.invoke(activity, null, options); 97 | } catch (Throwable t) { 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.activity; 2 | 3 | import android.content.Intent; 4 | import android.support.constraint.ConstraintLayout; 5 | import android.support.design.widget.FloatingActionButton; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.support.v7.widget.helper.ItemTouchHelper; 9 | import android.view.View; 10 | import android.view.animation.AccelerateInterpolator; 11 | import android.view.animation.DecelerateInterpolator; 12 | 13 | import com.rdc.goospet.R; 14 | import com.rdc.goospet.adapter.RVMainAdapter; 15 | import com.rdc.goospet.base.BaseActivity; 16 | import com.rdc.goospet.listener.HidingScrollListener; 17 | import com.rdc.goospet.presenter.MainPresenter; 18 | import com.rdc.goospet.service.FloatingPetService; 19 | import com.rdc.goospet.utils.DimenUtils; 20 | import com.rdc.goospet.view.vinterface.MainVInterface; 21 | 22 | /** 23 | * 主界面 24 | */ 25 | public class MainActivity extends BaseActivity implements MainVInterface, View.OnClickListener { 26 | 27 | 28 | private RecyclerView mRvMain; 29 | private FloatingActionButton mFABSetting; 30 | 31 | @Override 32 | protected MainPresenter createPresenter() { 33 | return new MainPresenter(this); 34 | } 35 | 36 | @Override 37 | protected int setContentViewById() { 38 | return R.layout.activity_main; 39 | } 40 | 41 | @Override 42 | protected void initAttributes() { 43 | 44 | } 45 | 46 | @Override 47 | protected void initView() { 48 | findAllViewById(); 49 | initRv(); 50 | mFABSetting.setOnClickListener(this); 51 | } 52 | 53 | /** 54 | * 加载R 55 | */ 56 | private void initRv() { 57 | RVMainAdapter rvAdapter = mPresenter.getRVAdapter(this); 58 | mRvMain.setLayoutManager(new LinearLayoutManager(this)); 59 | mRvMain.setAdapter(rvAdapter); 60 | mRvMain.addOnScrollListener(new HidingScrollListener() { 61 | @Override 62 | public void onHide() { 63 | hideFAB(); 64 | } 65 | 66 | @Override 67 | public void onShow() { 68 | showFAB(); 69 | } 70 | }); 71 | ItemTouchHelper itemHelper = mPresenter.getItemTouchHelper(rvAdapter); 72 | itemHelper.attachToRecyclerView(mRvMain); 73 | } 74 | 75 | 76 | /** 77 | * 显示悬浮按钮 78 | */ 79 | private void showFAB() { 80 | mFABSetting.animate().translationY(0).setInterpolator(new DecelerateInterpolator(1)).start(); 81 | } 82 | 83 | /** 84 | * 隐藏悬浮按钮 85 | */ 86 | private void hideFAB() { 87 | ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) mFABSetting.getLayoutParams(); 88 | int fabBottomMargin = lp.bottomMargin; 89 | mFABSetting.animate().translationY(mFABSetting.getHeight() + fabBottomMargin + DimenUtils.getNavBarHeight(this) + DimenUtils.getStatusBarHeight(this)). 90 | setInterpolator(new AccelerateInterpolator(2)).start(); 91 | } 92 | 93 | 94 | @Override 95 | protected void findAllViewById() { 96 | mRvMain = $(R.id.rv_main); 97 | mFABSetting = $(R.id.fab_setting); 98 | } 99 | 100 | @Override 101 | public void onClick(View view) { 102 | switch (view.getId()) { 103 | case R.id.rv_main: 104 | break; 105 | case R.id.fab_setting: 106 | Intent intent = new Intent(MainActivity.this, SettingActivity.class); 107 | startActivityWithAnim(intent); 108 | break; 109 | // case R.id.btn_show: 110 | // //启动悬浮pet 111 | // Intent intent = new Intent(MainActivity.this, FloatingPetService.class); 112 | // startService(intent); 113 | // Intent home = new Intent(Intent.ACTION_MAIN); 114 | // home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 115 | // home.addCategory(Intent.CATEGORY_HOME); 116 | // startActivity(home); 117 | // break; 118 | } 119 | } 120 | 121 | @Override 122 | protected void onDestroy() { 123 | // stopService(); 124 | super.onDestroy(); 125 | } 126 | 127 | @Override 128 | public void launchDesktopPet() { 129 | //启动悬浮pet 130 | Intent intent = new Intent(MainActivity.this, FloatingPetService.class); 131 | startService(intent); 132 | Intent home = new Intent(Intent.ACTION_MAIN); 133 | home.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); 134 | home.addCategory(Intent.CATEGORY_HOME); 135 | startActivity(home); 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/base/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.base; 2 | 3 | import android.app.ProgressDialog; 4 | import android.content.Intent; 5 | import android.os.Build; 6 | import android.os.Bundle; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.support.v7.widget.Toolbar; 9 | import android.view.View; 10 | 11 | import com.rdc.goospet.R; 12 | import com.rdc.goospet.utils.AppConstants; 13 | import com.rdc.goospet.utils.DimenUtils; 14 | 15 | /** 16 | * Created by Goo on 2016-8-28. 17 | */ 18 | public abstract class BaseActivity> extends AppCompatActivity { 19 | protected Toolbar toolbar; 20 | protected P mPresenter; 21 | private ProgressDialog mProgressDialog; 22 | 23 | 24 | @Override 25 | public void onCreate(Bundle savedInstanceState) { 26 | super.onCreate(savedInstanceState); 27 | setContentView(setContentViewById()); 28 | //创建Presenter,并把自己交给Present 29 | mPresenter = createPresenter(); 30 | mPresenter.attachView((V) this); 31 | initAttributes(); 32 | initView(); 33 | } 34 | 35 | //获取Presenter; 36 | protected abstract P createPresenter(); 37 | 38 | protected abstract int setContentViewById(); 39 | 40 | protected abstract void initAttributes(); 41 | 42 | protected abstract void initView(); 43 | 44 | protected abstract void findAllViewById(); 45 | 46 | /** 47 | * @param title 直接显示返回箭头的toolbar 48 | */ 49 | public void showToolbarAndShowNavigation(String title) { 50 | toolbar = (Toolbar) findViewById(R.id.toolbar); 51 | setToolbarTitle(title); 52 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { 53 | toolbar.getLayoutParams().height = DimenUtils.getAppBarHeight(this); 54 | toolbar.setPadding(toolbar.getPaddingLeft(), 55 | DimenUtils.getStatusBarHeight(this), 56 | toolbar.getPaddingRight(), 57 | toolbar.getPaddingBottom()); 58 | } 59 | showToolBar(); 60 | showOrHideToolBarNavigation(true); 61 | } 62 | 63 | 64 | /** 65 | * 设置toolbar标题 66 | * 67 | * @param title 68 | */ 69 | private void setToolbarTitle(String title) { 70 | if (toolbar != null) { 71 | toolbar.setTitle(title); 72 | toolbar.setTitleTextColor(0xFFFFFFFF); 73 | } 74 | } 75 | 76 | /** 77 | * 显示ToolBar 78 | */ 79 | private void showToolBar() { 80 | if (toolbar != null) { 81 | setSupportActionBar(toolbar); 82 | } 83 | if (getSupportActionBar() != null) { 84 | getSupportActionBar().show(); 85 | } 86 | } 87 | 88 | /** 89 | * 是否隐藏ToolBar返回按钮 90 | * 91 | * @param show 92 | */ 93 | public void showOrHideToolBarNavigation(boolean show) { 94 | if (show) { 95 | //设置返回键 96 | if (getSupportActionBar() != null) { 97 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 98 | } 99 | toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp); 100 | toolbar.setNavigationOnClickListener(new View.OnClickListener() { 101 | @Override 102 | public void onClick(View v) { 103 | finish(); 104 | setPendingTransition(AppConstants.OUT_PENDING_TRANSITION); 105 | } 106 | }); 107 | } 108 | } 109 | 110 | /** 111 | * Activity切换动画 112 | * 113 | * @param TYPE 114 | */ 115 | public void setPendingTransition(int TYPE) { 116 | if (TYPE == AppConstants.OPEN_PENDING_TRANSITION) { 117 | overridePendingTransition(R.anim.transition_right_in, 118 | R.anim.transition_not_move); 119 | } else if (TYPE == AppConstants.OUT_PENDING_TRANSITION) { 120 | overridePendingTransition(R.anim.transition_not_move, 121 | R.anim.transition_right_out); 122 | } 123 | } 124 | 125 | /** 126 | * 启动Activity 127 | * 128 | * @param clazz 129 | */ 130 | protected void launchActivity(Class clazz) { 131 | Intent intent = new Intent(this, clazz); 132 | startActivity(intent); 133 | } 134 | 135 | /** 136 | * 启动Activity - 有启动码 137 | * 138 | * @param clazz 139 | * @param requestCode 140 | */ 141 | protected void launchActivity(Class clazz, int requestCode) { 142 | Intent intent = new Intent(this, clazz); 143 | startActivityForResult(intent, requestCode); 144 | } 145 | 146 | /** 147 | * 替换 findViewById 148 | * 149 | * @param viewId 150 | * @param 151 | * @return 152 | */ 153 | protected T $(int viewId) { 154 | return (T) findViewById(viewId); 155 | } 156 | 157 | 158 | protected void showProgressDialog(String msg) { 159 | if (mProgressDialog == null) 160 | mProgressDialog = new ProgressDialog(this); 161 | mProgressDialog.setMessage(msg); 162 | //可取消 163 | mProgressDialog.setCancelable(true); 164 | //不显示进度 165 | mProgressDialog.setIndeterminate(false); 166 | mProgressDialog.show(); 167 | } 168 | 169 | protected void dismissProgressDialog() { 170 | if (mProgressDialog != null && mProgressDialog.isShowing()) 171 | mProgressDialog.dismiss(); 172 | } 173 | 174 | /** 175 | * 带动画启动Activity 176 | * 177 | * @param intent 178 | */ 179 | protected void startActivityWithAnim(Intent intent) { 180 | startActivity(intent); 181 | setPendingTransition(AppConstants.OPEN_PENDING_TRANSITION); 182 | } 183 | 184 | /** 185 | * 带动画关闭Activity 186 | */ 187 | protected void finishActivityWithAnim() { 188 | finish(); 189 | setPendingTransition(AppConstants.OUT_PENDING_TRANSITION); 190 | } 191 | 192 | 193 | } 194 | -------------------------------------------------------------------------------- /app/src/main/res/values/vpi__attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/widget/FloatingPetView.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.widget; 2 | 3 | import android.animation.ValueAnimator; 4 | import android.content.Context; 5 | import android.util.DisplayMetrics; 6 | import android.view.LayoutInflater; 7 | import android.view.MotionEvent; 8 | import android.view.View; 9 | import android.view.WindowManager; 10 | import android.widget.ImageView; 11 | import android.widget.LinearLayout; 12 | 13 | import com.rdc.goospet.R; 14 | import com.rdc.goospet.utils.FloatingUtils; 15 | import com.rdc.goospet.utils.LogUtils; 16 | 17 | import java.util.Random; 18 | 19 | /** 20 | * Created by Goo on 2016-9-18. 21 | */ 22 | public class FloatingPetView extends LinearLayout { 23 | /** 24 | * 窗体宽高 25 | */ 26 | public static int viewWidth, viewHeight; 27 | 28 | /** 29 | * 系统状态栏高度 30 | */ 31 | private static int statusBarHeight; 32 | 33 | /** 34 | * 屏幕宽高 35 | */ 36 | private int screenHeight, screenWidth; 37 | 38 | /** 39 | * 窗体管理 40 | */ 41 | private WindowManager mWindowManager; 42 | private WindowManager.LayoutParams mParams; 43 | 44 | /** 45 | * 悬浮窗Iv 46 | */ 47 | private ImageView mIvPet; 48 | 49 | /** 50 | * 位置参数 51 | */ 52 | private float xInView, yInView, xDownInScreen, yDownInScreen, xInScreen, yInScreen; 53 | 54 | /** 55 | * 是否按住状态 56 | */ 57 | private boolean isPressed = false; 58 | 59 | /** 60 | * 是否需要隐藏 61 | */ 62 | private boolean isNeedHide = false; 63 | 64 | /** 65 | * 动画 - 按住状态 66 | */ 67 | private ValueAnimator mTouchedAnim; 68 | 69 | /** 70 | * 动画 - 移动状态 71 | */ 72 | private ValueAnimator mMovingAnim; 73 | 74 | 75 | public FloatingPetView(Context context) { 76 | super(context); 77 | initView(context); 78 | } 79 | 80 | /** 81 | * 初始化视图 82 | * 83 | * @param context 84 | */ 85 | private void initView(Context context) { 86 | LayoutInflater.from(context).inflate(R.layout.layout_widget_pet, this); 87 | findAllViewById(); 88 | initViewParams(context); 89 | defaultPetStatus(); 90 | } 91 | 92 | private void findAllViewById() { 93 | mIvPet = (ImageView) findViewById(R.id.iv_pet); 94 | } 95 | 96 | /** 97 | * 初始化窗体宽高参数 98 | */ 99 | private void initViewParams(Context context) { 100 | View view = findViewById(R.id.ll_pet); 101 | viewWidth = view.getLayoutParams().width; 102 | viewHeight = view.getLayoutParams().height; 103 | DisplayMetrics dm = new DisplayMetrics(); 104 | mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); 105 | mWindowManager.getDefaultDisplay().getMetrics(dm); 106 | statusBarHeight = FloatingUtils.getStatusBarHeight(this); 107 | if (statusBarHeight != -1) { 108 | screenWidth = dm.widthPixels; 109 | screenHeight = dm.heightPixels - statusBarHeight; 110 | } else { 111 | LogUtils.e("statusBarHeight = -1"); 112 | } 113 | } 114 | 115 | /** 116 | * 设置宠物样式 117 | * 118 | * @param resid 119 | */ 120 | private void setPetImg(int resid) { 121 | mIvPet.setBackgroundResource(resid); 122 | } 123 | 124 | /** 125 | * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。 126 | * 127 | * @param params 小悬浮窗的参数 128 | */ 129 | public void setParams(WindowManager.LayoutParams params) { 130 | mParams = params; 131 | } 132 | 133 | /** 134 | * 处理控件触摸事件 135 | * 136 | * @param event 137 | * @return 138 | */ 139 | @Override 140 | public boolean onTouchEvent(MotionEvent event) { 141 | switch (event.getAction()) { 142 | case MotionEvent.ACTION_DOWN: 143 | isPressed = true; 144 | refreshParamsForDown(event); 145 | updatePetState(); 146 | break; 147 | case MotionEvent.ACTION_MOVE: 148 | isNeedHide = false; 149 | refreshParamsForMove(event); 150 | updatePetPosition(); 151 | updatePetState(); 152 | break; 153 | case MotionEvent.ACTION_UP: 154 | isPressed = false; 155 | 156 | if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) { 157 | //触摸坐标不变,即点击事件 158 | updatePetState(); 159 | } else if (xInScreen < screenWidth / 8) { //当在这个位置放手时宠物贴边隐藏 160 | hideLeft(); 161 | } else if (xInScreen > screenWidth * 7 / 8) { 162 | hideRight(); 163 | break; 164 | } else { 165 | updatePetState(); 166 | } 167 | } 168 | return true; 169 | } 170 | 171 | /** 172 | * 右边贴边 173 | */ 174 | private void hideRight() { 175 | setPetImg(R.drawable.ic_pet_hide_right); 176 | } 177 | 178 | /** 179 | * 左边贴边 180 | */ 181 | private void hideLeft() { 182 | setPetImg(R.drawable.ic_pet_hide_left); 183 | } 184 | 185 | /** 186 | * 更新宠物状态 187 | */ 188 | private void updatePetState() { 189 | if (isPressed) { 190 | //按住状态 191 | touchPetStatus(); 192 | } else if (isNeedHide) { 193 | //没有按住,需要贴边,贴边即可 194 | } else { 195 | //没有按住,也不需要贴边,默认状态即可 196 | defaultPetStatus(); 197 | } 198 | } 199 | 200 | private void defaultPetStatus() { 201 | switch (new Random().nextInt(5) + 3) { 202 | case 3: 203 | setPetImg(R.drawable.ic_face_03); 204 | break; 205 | case 4: 206 | setPetImg(R.drawable.ic_face_04); 207 | break; 208 | case 5: 209 | setPetImg(R.drawable.ic_face_05); 210 | break; 211 | case 6: 212 | setPetImg(R.drawable.ic_face_06); 213 | break; 214 | case 7: 215 | setPetImg(R.drawable.ic_face_07); 216 | break; 217 | } 218 | } 219 | 220 | /** 221 | * 按住(拎起)状态,随机更换表情 222 | */ 223 | private void touchPetStatus() { 224 | setPetImg(R.drawable.ic_face_02); 225 | } 226 | 227 | /** 228 | * 更新参数 - 移动时刻 229 | * 230 | * @param event 231 | */ 232 | private void refreshParamsForMove(MotionEvent event) { 233 | xInScreen = event.getRawX(); 234 | yInScreen = event.getRawY() - FloatingUtils.getStatusBarHeight(this); 235 | } 236 | 237 | /** 238 | * 更新参数 - 按下时刻 239 | * 240 | * @param event 241 | */ 242 | private void refreshParamsForDown(MotionEvent event) { 243 | xInView = event.getX(); 244 | yInView = event.getY(); 245 | xDownInScreen = event.getRawX(); 246 | yDownInScreen = event.getRawY() - FloatingUtils.getStatusBarHeight(this); 247 | refreshParamsForMove(event); 248 | } 249 | 250 | /** 251 | * 更新小悬浮窗在屏幕中的位置。 252 | */ 253 | private void updatePetPosition() { 254 | mParams.x = (int) (xInScreen - xInView); 255 | mParams.y = (int) (yInScreen - yInView); 256 | mWindowManager.updateViewLayout(this, mParams); 257 | } 258 | } 259 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/activity/IntroActivity.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.activity; 2 | 3 | import android.content.Intent; 4 | import android.support.v4.view.ViewPager; 5 | import android.support.v7.app.AlertDialog; 6 | import android.view.LayoutInflater; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | import android.widget.EditText; 10 | import android.widget.MaterialEditText; 11 | import android.widget.TextSwitcher; 12 | import android.widget.TextView; 13 | 14 | import com.rdc.goospet.R; 15 | import com.rdc.goospet.adapter.IntroFragmentAdapter; 16 | import com.rdc.goospet.base.BaseActivity; 17 | import com.rdc.goospet.listener.IntroPageChangedListener; 18 | import com.rdc.goospet.presenter.IntroPresenter; 19 | import com.rdc.goospet.utils.AppConstants; 20 | import com.rdc.goospet.utils.DialogUtils; 21 | import com.rdc.goospet.utils.ToastUtil; 22 | import com.rdc.goospet.view.vinterface.IntroVInterface; 23 | import com.rdc.goospet.view.widget.CirclePageIndicator; 24 | 25 | /** 26 | * Created by Goo on 2016-8-28. 27 | * 介绍界面(界面设计暂定) 28 | */ 29 | public class IntroActivity extends BaseActivity implements IntroVInterface, View.OnClickListener { 30 | 31 | private ViewPager mVpIntro; 32 | private CirclePageIndicator mIndicator; 33 | private IntroFragmentAdapter mPagerAdapter; 34 | 35 | private TextView mTvIntroLogin, mTvIntroRegister; 36 | private TextView mTvLogin, mTvSocialLogin, mTvRegister; 37 | private TextSwitcher mTSwitcher; 38 | 39 | private EditText mEtAccount, mEtPsw, mEtRAccount, mEtREmail, mEtRPsw, mEtRPswAgain; 40 | 41 | private AlertDialog mLoginDialog, mRegisterDialog = null; 42 | 43 | 44 | @Override 45 | protected IntroPresenter createPresenter() { 46 | return new IntroPresenter(this); 47 | } 48 | 49 | 50 | @Override 51 | protected int setContentViewById() { 52 | return R.layout.activity_intro; 53 | } 54 | 55 | @Override 56 | protected void initAttributes() { 57 | 58 | } 59 | 60 | @Override 61 | protected void initView() { 62 | findAllViewById(); 63 | setAllClickListener(); 64 | initVp(); 65 | initIndicator(); 66 | } 67 | 68 | private void initVp() { 69 | mPagerAdapter = mPresenter.getPagerAdapter(getSupportFragmentManager()); 70 | mVpIntro.setOffscreenPageLimit(0); 71 | mVpIntro.setAdapter(mPagerAdapter); 72 | mVpIntro.setPageTransformer(true, mPresenter.getTransformer()); 73 | } 74 | 75 | private void initIndicator() { 76 | mIndicator.setViewPager(mVpIntro); 77 | mIndicator.setPageColor(getResources().getColor(R.color.standardWhite)); 78 | mIndicator.setFillColor(getResources().getColor(R.color.colorAccent)); 79 | mIndicator.setOnPageChangeListener(new IntroPageChangedListener(mVpIntro, mTSwitcher, getWindowManager().getDefaultDisplay().getWidth(), mPagerAdapter.getCount(), getResources())); 80 | } 81 | 82 | private void setAllClickListener() { 83 | mTvIntroLogin.setOnClickListener(this); 84 | mTvIntroRegister.setOnClickListener(this); 85 | } 86 | 87 | @Override 88 | protected void findAllViewById() { 89 | mVpIntro = $(R.id.vp_intro); 90 | mIndicator = $(R.id.cpi); 91 | mTvIntroLogin = $(R.id.tv_intro_login); 92 | mTvIntroRegister = $(R.id.tv_intro_register); 93 | mTSwitcher = $(R.id.ts_intro); 94 | } 95 | 96 | @Override 97 | public void onClick(View view) { 98 | switch (view.getId()) { 99 | case R.id.tv_intro_login: 100 | showLoginDialog(); 101 | break; 102 | case R.id.tv_intro_register: 103 | showRegisterDialog(); 104 | break; 105 | case R.id.tv_login: 106 | dismissDialog(); 107 | mPresenter.login(mEtAccount.getText().toString(), mEtPsw.getText().toString()); 108 | break; 109 | case R.id.tv_social_login: 110 | break; 111 | case R.id.tv_register: 112 | mPresenter.register(mEtRAccount.getText().toString(), mEtREmail.getText().toString(), mEtRPsw.getText().toString(), mEtRPswAgain.getText().toString()); 113 | break; 114 | } 115 | } 116 | 117 | 118 | private void showLoginDialog() { 119 | LayoutInflater inflater = getLayoutInflater(); 120 | View loginDialog = inflater.inflate(R.layout.layout_dialog_login, (ViewGroup) findViewById(R.id.ll_dialog)); 121 | 122 | mEtAccount = (MaterialEditText) loginDialog.findViewById(R.id.et_account); 123 | mEtPsw = (MaterialEditText) loginDialog.findViewById(R.id.et_psw); 124 | mTvLogin = (TextView) loginDialog.findViewById(R.id.tv_login); 125 | mTvSocialLogin = (TextView) loginDialog.findViewById(R.id.tv_social_login); 126 | mTvLogin.setOnClickListener(this); 127 | mTvSocialLogin.setOnClickListener(this); 128 | 129 | mLoginDialog = DialogUtils.showCoustomDialog(this, loginDialog, "登录"); 130 | 131 | } 132 | 133 | private void showRegisterDialog() { 134 | 135 | LayoutInflater inflater = getLayoutInflater(); 136 | View registerDialog = inflater.inflate(R.layout.layout_dialog_register, (ViewGroup) findViewById(R.id.ll_dialog)); 137 | 138 | mTvRegister = (TextView) registerDialog.findViewById(R.id.tv_register); 139 | mEtRAccount = (EditText) registerDialog.findViewById(R.id.et_register_account); 140 | mEtREmail = (EditText) registerDialog.findViewById(R.id.et_register_email); 141 | mEtRPsw = (EditText) registerDialog.findViewById(R.id.et_register_psw); 142 | mEtRPswAgain = (EditText) registerDialog.findViewById(R.id.et_register_psw_again); 143 | mTvRegister.setOnClickListener(this); 144 | 145 | mRegisterDialog = DialogUtils.showCoustomDialog(this, registerDialog, "注册"); 146 | } 147 | 148 | @Override 149 | public void showProgressDialog() { 150 | super.showProgressDialog(getString(R.string.tips_net_working)); 151 | } 152 | 153 | @Override 154 | public void dismissDialog() { 155 | super.dismissProgressDialog(); 156 | } 157 | 158 | @Override 159 | public void registerSuccess(String userName) { 160 | ToastUtil.showToast(this, getString(R.string.tips_register_success)); 161 | EnterMain(userName); 162 | 163 | } 164 | 165 | @Override 166 | public void loginSuccess(String userName) { 167 | EnterMain(userName); 168 | } 169 | 170 | @Override 171 | public void errorLoginFail() { 172 | ToastUtil.showToast(this, getString(R.string.tips_error_login)); 173 | } 174 | 175 | @Override 176 | public void errorEmptyInfo() { 177 | ToastUtil.showToast(this, getString(R.string.error_empty_info)); 178 | } 179 | 180 | @Override 181 | public void errorPswNotEqual() { 182 | ToastUtil.showToast(this, getString(R.string.error_psw_not_equal)); 183 | } 184 | 185 | @Override 186 | public void errorEmailInvalid() { 187 | ToastUtil.showToast(this, getString(R.string.error_email_invalid)); 188 | } 189 | 190 | @Override 191 | public void errorUserNameRepeat() { 192 | ToastUtil.showToast(this, getString(R.string.error_username_repeat)); 193 | 194 | } 195 | 196 | @Override 197 | public void errorEmailRepeat() { 198 | ToastUtil.showToast(this, getString(R.string.error_email_repeat)); 199 | } 200 | 201 | @Override 202 | public void errorNetWork() { 203 | ToastUtil.showToast(this, getString(R.string.error_network)); 204 | } 205 | 206 | /** 207 | * 进入主界面 208 | * 209 | * @param userName 210 | */ 211 | private void EnterMain(String userName) { 212 | AppConstants.USER_NAME = userName; 213 | Intent intent = new Intent(IntroActivity.this, MainActivity.class); 214 | startActivityWithAnim(intent); 215 | finish(); 216 | } 217 | 218 | @Override 219 | protected void onDestroy() { 220 | if (mLoginDialog != null) { 221 | mLoginDialog.dismiss(); 222 | } 223 | if (mRegisterDialog != null) { 224 | mRegisterDialog.dismiss(); 225 | } 226 | super.onDestroy(); 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /app/src/main/java/com/rdc/goospet/view/widget/CirclePageIndicator.java: -------------------------------------------------------------------------------- 1 | package com.rdc.goospet.view.widget; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.drawable.Drawable; 9 | import android.os.Parcel; 10 | import android.os.Parcelable; 11 | import android.support.v4.view.MotionEventCompat; 12 | import android.support.v4.view.ViewConfigurationCompat; 13 | import android.support.v4.view.ViewPager; 14 | import android.util.AttributeSet; 15 | import android.view.MotionEvent; 16 | import android.view.View; 17 | import android.view.ViewConfiguration; 18 | 19 | import com.rdc.goospet.R; 20 | 21 | import static android.graphics.Paint.ANTI_ALIAS_FLAG; 22 | import static android.widget.LinearLayout.HORIZONTAL; 23 | import static android.widget.LinearLayout.VERTICAL; 24 | 25 | /** 26 | * from Android ViewPagerIndicator 27 | *

28 | * Created by Goo on 2016-8-31. 29 | */ 30 | public class CirclePageIndicator extends View implements PageIndicator { 31 | private static final int INVALID_POINTER = -1; 32 | 33 | private float mRadius; 34 | private final Paint mPaintPageFill = new Paint(ANTI_ALIAS_FLAG); 35 | private final Paint mPaintStroke = new Paint(ANTI_ALIAS_FLAG); 36 | private final Paint mPaintFill = new Paint(ANTI_ALIAS_FLAG); 37 | private ViewPager mViewPager; 38 | private ViewPager.OnPageChangeListener mListener; 39 | private int mCurrentPage; 40 | private int mSnapPage; 41 | private float mPageOffset; 42 | private int mScrollState; 43 | private int mOrientation; 44 | private boolean mCentered; 45 | private boolean mSnap; 46 | 47 | private int mTouchSlop; 48 | private float mLastMotionX = -1; 49 | private int mActivePointerId = INVALID_POINTER; 50 | private boolean mIsDragging; 51 | 52 | 53 | public CirclePageIndicator(Context context) { 54 | this(context, null); 55 | } 56 | 57 | public CirclePageIndicator(Context context, AttributeSet attrs) { 58 | this(context, attrs, R.attr.vpiCirclePageIndicatorStyle); 59 | } 60 | 61 | public CirclePageIndicator(Context context, AttributeSet attrs, int defStyle) { 62 | super(context, attrs, defStyle); 63 | if (isInEditMode()) return; 64 | 65 | //Load defaults from resources 66 | final Resources res = getResources(); 67 | final int defaultPageColor = res.getColor(R.color.default_circle_indicator_page_color); 68 | final int defaultFillColor = res.getColor(R.color.default_circle_indicator_fill_color); 69 | final int defaultOrientation = res.getInteger(R.integer.default_circle_indicator_orientation); 70 | final int defaultStrokeColor = res.getColor(R.color.default_circle_indicator_stroke_color); 71 | final float defaultStrokeWidth = res.getDimension(R.dimen.default_circle_indicator_stroke_width); 72 | final float defaultRadius = res.getDimension(R.dimen.default_circle_indicator_radius); 73 | final boolean defaultCentered = res.getBoolean(R.bool.default_circle_indicator_centered); 74 | final boolean defaultSnap = res.getBoolean(R.bool.default_circle_indicator_snap); 75 | 76 | //Retrieve styles attributes 77 | TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CirclePageIndicator, defStyle, 0); 78 | 79 | mCentered = a.getBoolean(R.styleable.CirclePageIndicator_centered, defaultCentered); 80 | mOrientation = a.getInt(R.styleable.CirclePageIndicator_android_orientation, defaultOrientation); 81 | mPaintPageFill.setStyle(Paint.Style.FILL); 82 | mPaintPageFill.setColor(a.getColor(R.styleable.CirclePageIndicator_pageColor, defaultPageColor)); 83 | mPaintStroke.setStyle(Paint.Style.STROKE); 84 | mPaintStroke.setColor(a.getColor(R.styleable.CirclePageIndicator_strokeColor, defaultStrokeColor)); 85 | mPaintStroke.setStrokeWidth(a.getDimension(R.styleable.CirclePageIndicator_strokeWidth, defaultStrokeWidth)); 86 | mPaintFill.setStyle(Paint.Style.FILL); 87 | mPaintFill.setColor(a.getColor(R.styleable.CirclePageIndicator_fillColor, defaultFillColor)); 88 | mRadius = a.getDimension(R.styleable.CirclePageIndicator_radius, defaultRadius); 89 | mSnap = a.getBoolean(R.styleable.CirclePageIndicator_snap, defaultSnap); 90 | 91 | Drawable background = a.getDrawable(R.styleable.CirclePageIndicator_android_background); 92 | if (background != null) { 93 | setBackgroundDrawable(background); 94 | } 95 | 96 | a.recycle(); 97 | 98 | final ViewConfiguration configuration = ViewConfiguration.get(context); 99 | mTouchSlop = ViewConfigurationCompat.getScaledPagingTouchSlop(configuration); 100 | } 101 | 102 | 103 | public void setCentered(boolean centered) { 104 | mCentered = centered; 105 | invalidate(); 106 | } 107 | 108 | public boolean isCentered() { 109 | return mCentered; 110 | } 111 | 112 | public void setPageColor(int pageColor) { 113 | mPaintPageFill.setColor(pageColor); 114 | invalidate(); 115 | } 116 | 117 | public int getPageColor() { 118 | return mPaintPageFill.getColor(); 119 | } 120 | 121 | public void setFillColor(int fillColor) { 122 | mPaintFill.setColor(fillColor); 123 | invalidate(); 124 | } 125 | 126 | public int getFillColor() { 127 | return mPaintFill.getColor(); 128 | } 129 | 130 | public void setOrientation(int orientation) { 131 | switch (orientation) { 132 | case HORIZONTAL: 133 | case VERTICAL: 134 | mOrientation = orientation; 135 | requestLayout(); 136 | break; 137 | 138 | default: 139 | throw new IllegalArgumentException("Orientation must be either HORIZONTAL or VERTICAL."); 140 | } 141 | } 142 | 143 | public int getOrientation() { 144 | return mOrientation; 145 | } 146 | 147 | public void setStrokeColor(int strokeColor) { 148 | mPaintStroke.setColor(strokeColor); 149 | invalidate(); 150 | } 151 | 152 | public int getStrokeColor() { 153 | return mPaintStroke.getColor(); 154 | } 155 | 156 | public void setStrokeWidth(float strokeWidth) { 157 | mPaintStroke.setStrokeWidth(strokeWidth); 158 | invalidate(); 159 | } 160 | 161 | public float getStrokeWidth() { 162 | return mPaintStroke.getStrokeWidth(); 163 | } 164 | 165 | public void setRadius(float radius) { 166 | mRadius = radius; 167 | invalidate(); 168 | } 169 | 170 | public float getRadius() { 171 | return mRadius; 172 | } 173 | 174 | public void setSnap(boolean snap) { 175 | mSnap = snap; 176 | invalidate(); 177 | } 178 | 179 | public boolean isSnap() { 180 | return mSnap; 181 | } 182 | 183 | @Override 184 | protected void onDraw(Canvas canvas) { 185 | super.onDraw(canvas); 186 | 187 | if (mViewPager == null) { 188 | return; 189 | } 190 | final int count = mViewPager.getAdapter().getCount(); 191 | if (count == 0) { 192 | return; 193 | } 194 | 195 | if (mCurrentPage >= count) { 196 | setCurrentItem(count - 1); 197 | return; 198 | } 199 | 200 | int longSize; 201 | int longPaddingBefore; 202 | int longPaddingAfter; 203 | int shortPaddingBefore; 204 | if (mOrientation == HORIZONTAL) { 205 | longSize = getWidth(); 206 | longPaddingBefore = getPaddingLeft(); 207 | longPaddingAfter = getPaddingRight(); 208 | shortPaddingBefore = getPaddingTop(); 209 | } else { 210 | longSize = getHeight(); 211 | longPaddingBefore = getPaddingTop(); 212 | longPaddingAfter = getPaddingBottom(); 213 | shortPaddingBefore = getPaddingLeft(); 214 | } 215 | 216 | final float threeRadius = mRadius * 3; 217 | final float shortOffset = shortPaddingBefore + mRadius; 218 | float longOffset = longPaddingBefore + mRadius; 219 | if (mCentered) { 220 | longOffset += ((longSize - longPaddingBefore - longPaddingAfter) / 2.0f) - ((count * threeRadius) / 2.0f); 221 | } 222 | 223 | float dX; 224 | float dY; 225 | 226 | float pageFillRadius = mRadius; 227 | if (mPaintStroke.getStrokeWidth() > 0) { 228 | pageFillRadius -= mPaintStroke.getStrokeWidth() / 2.0f; 229 | } 230 | 231 | //Draw stroked circles 232 | for (int iLoop = 0; iLoop < count; iLoop++) { 233 | float drawLong = longOffset + (iLoop * threeRadius); 234 | if (mOrientation == HORIZONTAL) { 235 | dX = drawLong; 236 | dY = shortOffset; 237 | } else { 238 | dX = shortOffset; 239 | dY = drawLong; 240 | } 241 | // Only paint fill if not completely transparent 242 | if (mPaintPageFill.getAlpha() > 0) { 243 | canvas.drawCircle(dX, dY, pageFillRadius, mPaintPageFill); 244 | } 245 | 246 | // Only paint stroke if a stroke width was non-zero 247 | if (pageFillRadius != mRadius) { 248 | canvas.drawCircle(dX, dY, mRadius, mPaintStroke); 249 | } 250 | } 251 | 252 | //Draw the filled circle according to the current scroll 253 | float cx = (mSnap ? mSnapPage : mCurrentPage) * threeRadius; 254 | if (!mSnap) { 255 | cx += mPageOffset * threeRadius; 256 | } 257 | if (mOrientation == HORIZONTAL) { 258 | dX = longOffset + cx; 259 | dY = shortOffset; 260 | } else { 261 | dX = shortOffset; 262 | dY = longOffset + cx; 263 | } 264 | canvas.drawCircle(dX, dY, mRadius, mPaintFill); 265 | } 266 | 267 | public boolean onTouchEvent(android.view.MotionEvent ev) { 268 | if (super.onTouchEvent(ev)) { 269 | return true; 270 | } 271 | if ((mViewPager == null) || (mViewPager.getAdapter().getCount() == 0)) { 272 | return false; 273 | } 274 | 275 | final int action = ev.getAction() & MotionEventCompat.ACTION_MASK; 276 | switch (action) { 277 | case MotionEvent.ACTION_DOWN: 278 | mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 279 | mLastMotionX = ev.getX(); 280 | break; 281 | 282 | case MotionEvent.ACTION_MOVE: { 283 | final int activePointerIndex = MotionEventCompat.findPointerIndex(ev, mActivePointerId); 284 | final float x = MotionEventCompat.getX(ev, activePointerIndex); 285 | final float deltaX = x - mLastMotionX; 286 | 287 | if (!mIsDragging) { 288 | if (Math.abs(deltaX) > mTouchSlop) { 289 | mIsDragging = true; 290 | } 291 | } 292 | 293 | if (mIsDragging) { 294 | mLastMotionX = x; 295 | if (mViewPager.isFakeDragging() || mViewPager.beginFakeDrag()) { 296 | mViewPager.fakeDragBy(deltaX); 297 | } 298 | } 299 | 300 | break; 301 | } 302 | 303 | case MotionEvent.ACTION_CANCEL: 304 | case MotionEvent.ACTION_UP: 305 | if (!mIsDragging) { 306 | final int count = mViewPager.getAdapter().getCount(); 307 | final int width = getWidth(); 308 | final float halfWidth = width / 2f; 309 | final float sixthWidth = width / 6f; 310 | 311 | if ((mCurrentPage > 0) && (ev.getX() < halfWidth - sixthWidth)) { 312 | if (action != MotionEvent.ACTION_CANCEL) { 313 | mViewPager.setCurrentItem(mCurrentPage - 1); 314 | } 315 | return true; 316 | } else if ((mCurrentPage < count - 1) && (ev.getX() > halfWidth + sixthWidth)) { 317 | if (action != MotionEvent.ACTION_CANCEL) { 318 | mViewPager.setCurrentItem(mCurrentPage + 1); 319 | } 320 | return true; 321 | } 322 | } 323 | 324 | mIsDragging = false; 325 | mActivePointerId = INVALID_POINTER; 326 | if (mViewPager.isFakeDragging()) mViewPager.endFakeDrag(); 327 | break; 328 | 329 | case MotionEventCompat.ACTION_POINTER_DOWN: { 330 | final int index = MotionEventCompat.getActionIndex(ev); 331 | mLastMotionX = MotionEventCompat.getX(ev, index); 332 | mActivePointerId = MotionEventCompat.getPointerId(ev, index); 333 | break; 334 | } 335 | 336 | case MotionEventCompat.ACTION_POINTER_UP: 337 | final int pointerIndex = MotionEventCompat.getActionIndex(ev); 338 | final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex); 339 | if (pointerId == mActivePointerId) { 340 | final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 341 | mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); 342 | } 343 | mLastMotionX = MotionEventCompat.getX(ev, MotionEventCompat.findPointerIndex(ev, mActivePointerId)); 344 | break; 345 | } 346 | 347 | return true; 348 | } 349 | 350 | @Override 351 | public void setViewPager(ViewPager view) { 352 | if (mViewPager == view) { 353 | return; 354 | } 355 | if (mViewPager != null) { 356 | mViewPager.setOnPageChangeListener(null); 357 | } 358 | if (view.getAdapter() == null) { 359 | throw new IllegalStateException("ViewPager does not have adapter instance."); 360 | } 361 | mViewPager = view; 362 | mViewPager.setOnPageChangeListener(this); 363 | invalidate(); 364 | } 365 | 366 | @Override 367 | public void setViewPager(ViewPager view, int initialPosition) { 368 | setViewPager(view); 369 | setCurrentItem(initialPosition); 370 | } 371 | 372 | @Override 373 | public void setCurrentItem(int item) { 374 | if (mViewPager == null) { 375 | throw new IllegalStateException("ViewPager has not been bound."); 376 | } 377 | mViewPager.setCurrentItem(item); 378 | mCurrentPage = item; 379 | invalidate(); 380 | } 381 | 382 | @Override 383 | public void notifyDataSetChanged() { 384 | invalidate(); 385 | } 386 | 387 | @Override 388 | public void onPageScrollStateChanged(int state) { 389 | mScrollState = state; 390 | 391 | if (mListener != null) { 392 | mListener.onPageScrollStateChanged(state); 393 | } 394 | } 395 | 396 | @Override 397 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { 398 | mCurrentPage = position; 399 | mPageOffset = positionOffset; 400 | invalidate(); 401 | 402 | if (mListener != null) { 403 | mListener.onPageScrolled(position, positionOffset, positionOffsetPixels); 404 | } 405 | } 406 | 407 | @Override 408 | public void onPageSelected(int position) { 409 | if (mSnap || mScrollState == ViewPager.SCROLL_STATE_IDLE) { 410 | mCurrentPage = position; 411 | mSnapPage = position; 412 | invalidate(); 413 | } 414 | 415 | if (mListener != null) { 416 | mListener.onPageSelected(position); 417 | } 418 | } 419 | 420 | @Override 421 | public void setOnPageChangeListener(ViewPager.OnPageChangeListener listener) { 422 | mListener = listener; 423 | } 424 | 425 | /* 426 | * (non-Javadoc) 427 | * 428 | * @see android.view.View#onMeasure(int, int) 429 | */ 430 | @Override 431 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 432 | if (mOrientation == HORIZONTAL) { 433 | setMeasuredDimension(measureLong(widthMeasureSpec), measureShort(heightMeasureSpec)); 434 | } else { 435 | setMeasuredDimension(measureShort(widthMeasureSpec), measureLong(heightMeasureSpec)); 436 | } 437 | } 438 | 439 | /** 440 | * Determines the width of this view 441 | * 442 | * @param measureSpec A measureSpec packed into an int 443 | * @return The width of the view, honoring constraints from measureSpec 444 | */ 445 | private int measureLong(int measureSpec) { 446 | int result; 447 | int specMode = MeasureSpec.getMode(measureSpec); 448 | int specSize = MeasureSpec.getSize(measureSpec); 449 | 450 | if ((specMode == MeasureSpec.EXACTLY) || (mViewPager == null)) { 451 | //We were told how big to be 452 | result = specSize; 453 | } else { 454 | //Calculate the width according the views count 455 | final int count = mViewPager.getAdapter().getCount(); 456 | result = (int) (getPaddingLeft() + getPaddingRight() 457 | + (count * 2 * mRadius) + (count - 1) * mRadius + 1); 458 | //Respect AT_MOST value if that was what is called for by measureSpec 459 | if (specMode == MeasureSpec.AT_MOST) { 460 | result = Math.min(result, specSize); 461 | } 462 | } 463 | return result; 464 | } 465 | 466 | /** 467 | * Determines the height of this view 468 | * 469 | * @param measureSpec A measureSpec packed into an int 470 | * @return The height of the view, honoring constraints from measureSpec 471 | */ 472 | private int measureShort(int measureSpec) { 473 | int result; 474 | int specMode = MeasureSpec.getMode(measureSpec); 475 | int specSize = MeasureSpec.getSize(measureSpec); 476 | 477 | if (specMode == MeasureSpec.EXACTLY) { 478 | //We were told how big to be 479 | result = specSize; 480 | } else { 481 | //Measure the height 482 | result = (int) (2 * mRadius + getPaddingTop() + getPaddingBottom() + 1); 483 | //Respect AT_MOST value if that was what is called for by measureSpec 484 | if (specMode == MeasureSpec.AT_MOST) { 485 | result = Math.min(result, specSize); 486 | } 487 | } 488 | return result; 489 | } 490 | 491 | @Override 492 | public void onRestoreInstanceState(Parcelable state) { 493 | SavedState savedState = (SavedState) state; 494 | super.onRestoreInstanceState(savedState.getSuperState()); 495 | mCurrentPage = savedState.currentPage; 496 | mSnapPage = savedState.currentPage; 497 | requestLayout(); 498 | } 499 | 500 | @Override 501 | public Parcelable onSaveInstanceState() { 502 | Parcelable superState = super.onSaveInstanceState(); 503 | SavedState savedState = new SavedState(superState); 504 | savedState.currentPage = mCurrentPage; 505 | return savedState; 506 | } 507 | 508 | static class SavedState extends BaseSavedState { 509 | int currentPage; 510 | 511 | public SavedState(Parcelable superState) { 512 | super(superState); 513 | } 514 | 515 | private SavedState(Parcel in) { 516 | super(in); 517 | currentPage = in.readInt(); 518 | } 519 | 520 | @Override 521 | public void writeToParcel(Parcel dest, int flags) { 522 | super.writeToParcel(dest, flags); 523 | dest.writeInt(currentPage); 524 | } 525 | 526 | @SuppressWarnings("UnusedDeclaration") 527 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 528 | @Override 529 | public SavedState createFromParcel(Parcel in) { 530 | return new SavedState(in); 531 | } 532 | 533 | @Override 534 | public SavedState[] newArray(int size) { 535 | return new SavedState[size]; 536 | } 537 | }; 538 | } 539 | } 540 | 541 | --------------------------------------------------------------------------------