├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── zhl │ │ └── secondaryscreen │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── assets │ │ └── biking_is_cool.json │ ├── java │ │ └── com │ │ │ └── zhl │ │ │ └── secondaryscreen │ │ │ ├── activity │ │ │ ├── MainActivity.java │ │ │ └── SecondFloorActivity.java │ │ │ ├── adapter │ │ │ └── MyPaperAdapter.java │ │ │ ├── fragment │ │ │ ├── MainFragment.java │ │ │ ├── OtherFragment.java │ │ │ ├── ProgressbarFragment.java │ │ │ ├── RecyclerViewRefreshFragment.java │ │ │ ├── ScrollViewRefreshFragment.java │ │ │ └── TagImageFragment.java │ │ │ └── view │ │ │ ├── CustomRefreshHeader.java │ │ │ ├── ImageProgressBar.java │ │ │ ├── OnSecondFloorScrollistener.java │ │ │ ├── OnStateListener.java │ │ │ ├── SecondFloorView.java │ │ │ ├── SecondaryScreenView.java │ │ │ └── TagImageView.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ ├── drawable_refresh_tv.xml │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_custom_progress_bar.xml │ │ ├── activity_custom_refresh_header.xml │ │ ├── activity_custom_view_test.xml │ │ ├── activity_main.xml │ │ ├── activity_pull_secondview.xml │ │ ├── custom_refresh_header.xml │ │ ├── fg_second_floor.xml │ │ └── item_cardview.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── arrow_down.png │ │ ├── bg2.jpg │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── img_1.jpg │ │ ├── img_3.jpg │ │ ├── progressbar_bg.jpg │ │ ├── second_floor_main.png │ │ ├── secondary_screen.jpg │ │ ├── top_right_search_black.png │ │ ├── v1.jpg │ │ ├── v2.jpg │ │ └── v3.jpg │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── zhl │ └── secondaryscreen │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── image ├── show.gif ├── show_video.jpg └── show_video.mp4 ├── settings.gradle ├── show.gif ├── show2.jpg ├── show3.gif └── video_show_secondfloorview.gif /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/caches 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | /.idea/navEditor.xml 9 | /.idea/assetWizardSettings.xml 10 | .DS_Store 11 | /build 12 | /captures 13 | .externalNativeBuild 14 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 15 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 9 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # SecondaryScreen 2 | 3 | - 因为只有一个自定义ViewGroup就不上传maven了,直接拷入工程去用就O了。用法参考demo 4 | 5 | - 下拉刷新 继续刷新进入二楼 6 | 7 | 8 | 9 | 10 | 11 | - 还有一个imageViewProgressbar 12 | 13 | 14 | 15 | - TagImageView 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.zhl.secondaryscreen" 7 | minSdkVersion 19 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | dataBinding { 20 | enabled = true 21 | } 22 | } 23 | 24 | dependencies { 25 | implementation fileTree(include: ['*.jar'], dir: 'libs') 26 | implementation 'com.android.support:appcompat-v7:28.0.0' 27 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 28 | testImplementation 'junit:junit:4.12' 29 | implementation 'com.scwang.smartrefresh:SmartRefreshLayout:1.0.5.1' 30 | implementation 'com.github.hackware1993:magicindicator:1.5.0' 31 | implementation 'com.airbnb.android:lottie:2.7.0' 32 | implementation 'com.airbnb.android:lottie:2.7.0' 33 | implementation 'com.android.support:recyclerview-v7:28.0.0' 34 | implementation 'com.android.support:cardview-v7:28.0.0' 35 | implementation('com.zhy:base-rvadapter:3.0.3') { 36 | exclude(group: 'com.android.support', module: 'recyclerview-v7') 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/zhl/secondaryscreen/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.zhl.secondaryscreen", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/activity/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.activity; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v4.view.ViewPager; 7 | import android.support.v7.app.AppCompatActivity; 8 | import android.view.View; 9 | import android.widget.ImageView; 10 | 11 | import com.zhl.secondaryscreen.R; 12 | import com.zhl.secondaryscreen.adapter.MyPaperAdapter; 13 | import com.zhl.secondaryscreen.view.SecondaryScreenView; 14 | 15 | import net.lucode.hackware.magicindicator.MagicIndicator; 16 | import net.lucode.hackware.magicindicator.ViewPagerHelper; 17 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator; 18 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; 19 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; 20 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; 21 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; 22 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView; 23 | 24 | import java.util.ArrayList; 25 | 26 | public class MainActivity extends AppCompatActivity { 27 | private MagicIndicator magicIndicator; 28 | private ViewPager mViewPager; 29 | private ArrayList mTitleDataList = new ArrayList<>(); 30 | SecondaryScreenView secondaryScreenView; 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_main); 35 | mTitleDataList.add("主页"); 36 | mTitleDataList.add("发现"); 37 | mTitleDataList.add("推荐"); 38 | mTitleDataList.add("日报"); 39 | mTitleDataList.add("ImageProgressBar"); 40 | mTitleDataList.add("ImageTag"); 41 | magicIndicator = (MagicIndicator) findViewById(R.id.magic_indicator); 42 | secondaryScreenView = findViewById(R.id.secondaryScreenView); 43 | mViewPager = findViewById(R.id.viewpager); 44 | mViewPager.setAdapter(new MyPaperAdapter(getSupportFragmentManager(),mTitleDataList)); 45 | CommonNavigator commonNavigator = new CommonNavigator(this); 46 | commonNavigator.setAdapter(new CommonNavigatorAdapter() { 47 | 48 | @Override 49 | public int getCount() { 50 | return mTitleDataList == null ? 0 : mTitleDataList.size(); 51 | } 52 | 53 | @Override 54 | public IPagerTitleView getTitleView(Context context, final int index) { 55 | ColorTransitionPagerTitleView colorTransitionPagerTitleView = new ColorTransitionPagerTitleView(context); 56 | colorTransitionPagerTitleView.setNormalColor(Color.GRAY); 57 | colorTransitionPagerTitleView.setSelectedColor(Color.BLACK); 58 | colorTransitionPagerTitleView.setText(mTitleDataList.get(index)); 59 | colorTransitionPagerTitleView.setOnClickListener(new View.OnClickListener() { 60 | @Override 61 | public void onClick(View view) { 62 | mViewPager.setCurrentItem(index); 63 | } 64 | }); 65 | return colorTransitionPagerTitleView; 66 | } 67 | 68 | @Override 69 | public IPagerIndicator getIndicator(Context context) { 70 | LinePagerIndicator indicator = new LinePagerIndicator(context); 71 | indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT); 72 | return indicator; 73 | } 74 | }); 75 | magicIndicator.setNavigator(commonNavigator); 76 | ViewPagerHelper.bind(magicIndicator, mViewPager); 77 | ImageView btnSearch = findViewById(R.id.top_search); 78 | btnSearch.setOnClickListener(new View.OnClickListener() { 79 | @Override 80 | public void onClick(View v) { 81 | secondaryScreenView.translateToSecondaryView(); 82 | } 83 | }); 84 | } 85 | 86 | @Override 87 | public void onBackPressed() { 88 | if(!secondaryScreenView.isStillMainView()){ 89 | secondaryScreenView.translateToMainView(); 90 | }else{ 91 | super.onBackPressed(); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/activity/SecondFloorActivity.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.activity; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v4.app.FragmentStatePagerAdapter; 8 | import android.support.v4.view.ViewPager; 9 | import android.support.v7.app.AppCompatActivity; 10 | import android.view.View; 11 | 12 | import com.zhl.secondaryscreen.R; 13 | import com.zhl.secondaryscreen.fragment.RecyclerViewRefreshFragment; 14 | import com.zhl.secondaryscreen.fragment.ScrollViewRefreshFragment; 15 | 16 | import net.lucode.hackware.magicindicator.MagicIndicator; 17 | import net.lucode.hackware.magicindicator.ViewPagerHelper; 18 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.CommonNavigator; 19 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.CommonNavigatorAdapter; 20 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerIndicator; 21 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.abs.IPagerTitleView; 22 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.indicators.LinePagerIndicator; 23 | import net.lucode.hackware.magicindicator.buildins.commonnavigator.titles.ColorTransitionPagerTitleView; 24 | 25 | import java.util.ArrayList; 26 | 27 | public class SecondFloorActivity extends AppCompatActivity { 28 | private MagicIndicator magicIndicator; 29 | private ViewPager mViewPager; 30 | private ArrayList mTitleDataList = new ArrayList<>(); 31 | @Override 32 | protected void onCreate(Bundle savedInstanceState) { 33 | super.onCreate(savedInstanceState); 34 | setContentView(R.layout.activity_pull_secondview); 35 | mTitleDataList.add("RecyclerView"); 36 | mTitleDataList.add("ScrollView"); 37 | magicIndicator = (MagicIndicator) findViewById(R.id.magic_indicator); 38 | mViewPager = findViewById(R.id.viewpager); 39 | mViewPager.setAdapter(new FragmentStatePagerAdapter(getSupportFragmentManager()) { 40 | @Override 41 | public Fragment getItem(int i) { 42 | Fragment fg = null; 43 | switch (i){ 44 | case 0: 45 | fg = new RecyclerViewRefreshFragment(); 46 | break; 47 | case 1: 48 | fg = new ScrollViewRefreshFragment(); 49 | break; 50 | } 51 | return fg; 52 | } 53 | 54 | @Override 55 | public int getCount() { 56 | return mTitleDataList.size(); 57 | } 58 | }); 59 | CommonNavigator commonNavigator = new CommonNavigator(this); 60 | commonNavigator.setAdapter(new CommonNavigatorAdapter() { 61 | 62 | @Override 63 | public int getCount() { 64 | return mTitleDataList == null ? 0 : mTitleDataList.size(); 65 | } 66 | 67 | @Override 68 | public IPagerTitleView getTitleView(Context context, final int index) { 69 | ColorTransitionPagerTitleView colorTransitionPagerTitleView = new ColorTransitionPagerTitleView(context); 70 | colorTransitionPagerTitleView.setNormalColor(Color.GRAY); 71 | colorTransitionPagerTitleView.setSelectedColor(Color.BLACK); 72 | colorTransitionPagerTitleView.setText(mTitleDataList.get(index)); 73 | colorTransitionPagerTitleView.setOnClickListener(new View.OnClickListener() { 74 | @Override 75 | public void onClick(View view) { 76 | mViewPager.setCurrentItem(index); 77 | } 78 | }); 79 | return colorTransitionPagerTitleView; 80 | } 81 | 82 | @Override 83 | public IPagerIndicator getIndicator(Context context) { 84 | LinePagerIndicator indicator = new LinePagerIndicator(context); 85 | indicator.setMode(LinePagerIndicator.MODE_WRAP_CONTENT); 86 | return indicator; 87 | } 88 | }); 89 | magicIndicator.setNavigator(commonNavigator); 90 | ViewPagerHelper.bind(magicIndicator, mViewPager); 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/adapter/MyPaperAdapter.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.adapter; 2 | 3 | import android.support.v4.app.Fragment; 4 | import android.support.v4.app.FragmentManager; 5 | import android.support.v4.app.FragmentPagerAdapter; 6 | 7 | import com.zhl.secondaryscreen.R; 8 | import com.zhl.secondaryscreen.fragment.MainFragment; 9 | import com.zhl.secondaryscreen.fragment.OtherFragment; 10 | import com.zhl.secondaryscreen.fragment.ProgressbarFragment; 11 | import com.zhl.secondaryscreen.fragment.TagImageFragment; 12 | 13 | import java.util.ArrayList; 14 | 15 | /** 16 | * 描述: 17 | * Created by zhaohl on 2019-1-21. 18 | */ 19 | public class MyPaperAdapter extends FragmentPagerAdapter { 20 | private ArrayList mDatas ; 21 | 22 | public MyPaperAdapter(FragmentManager fm) { 23 | this(fm,null); 24 | } 25 | 26 | public MyPaperAdapter(FragmentManager fm, ArrayList mDatas){ 27 | super(fm); 28 | this.mDatas = mDatas; 29 | } 30 | 31 | @Override 32 | public Fragment getItem(int position) { 33 | Fragment fragment = null; 34 | switch (position){ 35 | case 0: 36 | fragment = new MainFragment(); 37 | break; 38 | case 1: 39 | fragment = OtherFragment.newInstance(mDatas.get(position), R.mipmap.v1); 40 | break; 41 | case 2: 42 | fragment = OtherFragment.newInstance(mDatas.get(position),R.mipmap.v2); 43 | break; 44 | case 3: 45 | fragment = OtherFragment.newInstance(mDatas.get(position),R.mipmap.v3); 46 | break; 47 | case 4: 48 | fragment = ProgressbarFragment.newInstance(); 49 | break; 50 | case 5: 51 | fragment = TagImageFragment.newInstance(); 52 | break; 53 | } 54 | return fragment; 55 | } 56 | 57 | @Override 58 | public int getCount() { 59 | return mDatas==null?0:mDatas.size(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/MainFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.content.Intent; 4 | import android.os.Bundle; 5 | import android.support.annotation.NonNull; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.app.Fragment; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | 14 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 15 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 16 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 17 | import com.zhl.secondaryscreen.R; 18 | import com.zhl.secondaryscreen.activity.SecondFloorActivity; 19 | import com.zhy.adapter.recyclerview.CommonAdapter; 20 | import com.zhy.adapter.recyclerview.MultiItemTypeAdapter; 21 | import com.zhy.adapter.recyclerview.base.ViewHolder; 22 | 23 | import java.util.ArrayList; 24 | import java.util.List; 25 | 26 | /** 27 | * 描述: 28 | * Created by zhaohl on 2019-1-21. 29 | */ 30 | public class MainFragment extends Fragment { 31 | private RecyclerView mRecyclerView; 32 | private List datas = new ArrayList<>(); 33 | private SmartRefreshLayout refreshView ; 34 | private CommonAdapter mAdapter; 35 | @Override 36 | public void onCreate(@Nullable Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | } 39 | 40 | @Nullable 41 | @Override 42 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 43 | View view = inflater.inflate(R.layout.activity_custom_refresh_header,null); 44 | refreshView = view.findViewById(R.id.refresh_layout); 45 | mRecyclerView = view.findViewById(R.id.recyclerview); 46 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 47 | for (int i = 0; i < 30; i++) { 48 | datas.add("custom_refresh_header" + i); 49 | } 50 | mRecyclerView.setAdapter(mAdapter = new CommonAdapter(getContext(), R.layout.item_cardview, datas) { 51 | @Override 52 | protected void convert(ViewHolder holder, String s, int position) { 53 | holder.setText(R.id.item_tx, s); 54 | } 55 | 56 | }); 57 | refreshView.setOnRefreshListener(new OnRefreshListener() { 58 | @Override 59 | public void onRefresh(RefreshLayout refreshLayout) { 60 | refreshView.postDelayed(new Runnable() { 61 | @Override 62 | public void run() { 63 | refreshView.finishRefresh(); 64 | } 65 | },2000); 66 | } 67 | }); 68 | mAdapter.setOnItemClickListener(new MultiItemTypeAdapter.OnItemClickListener() { 69 | @Override 70 | public void onItemClick(View view, RecyclerView.ViewHolder holder, int position) { 71 | Intent intent = new Intent(getContext(), SecondFloorActivity.class); 72 | startActivity(intent); 73 | } 74 | 75 | @Override 76 | public boolean onItemLongClick(View view, RecyclerView.ViewHolder holder, int position) { 77 | return false; 78 | } 79 | }); 80 | return view; 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/OtherFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | import android.widget.ImageView; 11 | 12 | /** 13 | * 描述: 14 | * Created by zhaohl on 2019-1-21. 15 | */ 16 | public class OtherFragment extends Fragment { 17 | private String title; 18 | private int imgResID; 19 | public static OtherFragment newInstance(String title, int ImgResid){ 20 | OtherFragment fg = new OtherFragment(); 21 | fg.title = title; 22 | fg.imgResID = ImgResid; 23 | return fg; 24 | } 25 | @Override 26 | public void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | } 29 | 30 | @Nullable 31 | @Override 32 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 33 | // TextView textView = new TextView(getContext()); 34 | // textView.setText(title); 35 | // textView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 36 | // textView.setGravity(Gravity.CENTER); 37 | ImageView imageView = new ImageView(getContext()); 38 | imageView.setBackgroundResource(imgResID); 39 | imageView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 40 | return imageView; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/ProgressbarFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.os.Handler; 5 | import android.os.Message; 6 | import android.support.annotation.NonNull; 7 | import android.support.annotation.Nullable; 8 | import android.support.v4.app.Fragment; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.view.ViewGroup; 12 | 13 | import com.zhl.secondaryscreen.R; 14 | import com.zhl.secondaryscreen.view.ImageProgressBar; 15 | 16 | /** 17 | * 描述: 18 | * Created by zhaohl on 2019-6-26. 19 | */ 20 | public class ProgressbarFragment extends Fragment { 21 | private static final int UPDATE_PROGRESS=0; 22 | boolean stop; 23 | ImageProgressBar progressBar,progressBar2; 24 | Handler handler = new Handler(){ 25 | public void handleMessage(Message msg) { 26 | switch (msg.what) { 27 | case UPDATE_PROGRESS: 28 | progressBar.setProgress(msg.arg1); 29 | progressBar2.setProgress(msg.arg1); 30 | break; 31 | default: 32 | break; 33 | } 34 | }; 35 | }; 36 | 37 | public static ProgressbarFragment newInstance(){ 38 | ProgressbarFragment fg = new ProgressbarFragment(); 39 | return fg; 40 | } 41 | @Override 42 | public void onCreate(@Nullable Bundle savedInstanceState) { 43 | super.onCreate(savedInstanceState); 44 | } 45 | 46 | @Nullable 47 | @Override 48 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 49 | View view = inflater.inflate(R.layout.activity_custom_progress_bar,null); 50 | progressBar = view.findViewById(R.id.progressBar); 51 | progressBar2 = view.findViewById(R.id.progressBar2); 52 | return view; 53 | } 54 | 55 | @Override 56 | public void onActivityCreated(@Nullable Bundle savedInstanceState) { 57 | super.onActivityCreated(savedInstanceState); 58 | new Thread(new Runnable() { 59 | @Override 60 | public void run() { 61 | int progress = 0; 62 | while(!stop){ 63 | if(progress>=100){ 64 | break; 65 | } 66 | Message msg = handler.obtainMessage(); 67 | try { 68 | Thread.sleep(50); 69 | } catch (InterruptedException e) { 70 | e.printStackTrace(); 71 | } 72 | progress+=1; 73 | msg.what= UPDATE_PROGRESS; 74 | msg.arg1 = progress; 75 | msg.sendToTarget(); 76 | } 77 | progress = 0; 78 | } 79 | }).start(); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/RecyclerViewRefreshFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.support.v7.widget.LinearLayoutManager; 8 | import android.support.v7.widget.RecyclerView; 9 | import android.util.Log; 10 | import android.view.LayoutInflater; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.widget.TextView; 14 | 15 | import com.scwang.smartrefresh.layout.SmartRefreshLayout; 16 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 17 | import com.scwang.smartrefresh.layout.listener.OnRefreshListener; 18 | import com.zhl.secondaryscreen.R; 19 | import com.zhl.secondaryscreen.view.OnSecondFloorScrollistener; 20 | import com.zhl.secondaryscreen.view.OnStateListener; 21 | import com.zhl.secondaryscreen.view.SecondFloorView; 22 | import com.zhy.adapter.recyclerview.CommonAdapter; 23 | import com.zhy.adapter.recyclerview.base.ViewHolder; 24 | 25 | import java.util.ArrayList; 26 | import java.util.List; 27 | 28 | /** 29 | * 描述: 30 | * Created by zhaohl on 2020-4-3. 31 | */ 32 | public class RecyclerViewRefreshFragment extends Fragment { 33 | private RecyclerView mRecyclerView; 34 | private List datas = new ArrayList<>(); 35 | private SmartRefreshLayout refreshView ; 36 | private CommonAdapter mAdapter; 37 | SecondFloorView secondFloorView; 38 | TextView tvHeader; 39 | @Override 40 | public void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | } 43 | 44 | @Nullable 45 | @Override 46 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 47 | View view = inflater.inflate(R.layout.activity_custom_refresh_header,null); 48 | refreshView = view.findViewById(R.id.refresh_layout); 49 | refreshView.setEnableRefresh(false); 50 | mRecyclerView = view.findViewById(R.id.recyclerview); 51 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext())); 52 | for (int i = 0; i < 30; i++) { 53 | datas.add("recyclerview in secondfloorview" + i); 54 | } 55 | mRecyclerView.setAdapter(mAdapter = new CommonAdapter(getContext(), R.layout.item_cardview, datas) { 56 | 57 | @Override 58 | protected void convert(ViewHolder holder, String s, int position) { 59 | holder.setText(R.id.item_tx, s); 60 | } 61 | }); 62 | refreshView.setOnRefreshListener(new OnRefreshListener() { 63 | @Override 64 | public void onRefresh(RefreshLayout refreshLayout) { 65 | refreshView.postDelayed(new Runnable() { 66 | @Override 67 | public void run() { 68 | refreshView.finishRefresh(); 69 | } 70 | },2000); 71 | } 72 | }); 73 | secondFloorView = view.findViewById(R.id.second_floor_view); 74 | tvHeader = view.findViewById(R.id.tv_pull_header); 75 | secondFloorView.setOnSecondFloorScrollistener(new OnSecondFloorScrollistener() { 76 | @Override 77 | public void onScroll(int scrollY) { 78 | // Log.d("mytag","scrolly==="+scrollY); 79 | } 80 | 81 | @Override 82 | public void onSwipeToSecondFloor() { 83 | 84 | } 85 | 86 | @Override 87 | public void onSwipeToMain() { 88 | 89 | } 90 | 91 | @Override 92 | public void onRefresh() { 93 | Log.d("mytag","开始刷新"); 94 | secondFloorView.postDelayed(new Runnable() { 95 | @Override 96 | public void run() { 97 | secondFloorView.finishRefresh(); 98 | } 99 | },2000); 100 | } 101 | }); 102 | secondFloorView.setOnStateListener(new OnStateListener() { 103 | @Override 104 | public void onStateChanged(String state) { 105 | // Log.d("mytag","onStateChanged=="+state); 106 | } 107 | 108 | @Override 109 | public void onStateRefreshing() { 110 | Log.d("mytag","onStateRefreshing"); 111 | tvHeader.setText("正在刷新..."); 112 | } 113 | 114 | @Override 115 | public void onStatePullToRefresh() { 116 | Log.d("mytag","onStatePullToRefresh"); 117 | tvHeader.setText("下拉赢好礼 ↓"); 118 | } 119 | 120 | @Override 121 | public void onStateReleaseToRefresh() { 122 | Log.d("mytag","onStateReleaseToRefresh"); 123 | tvHeader.setText("松开开始刷新 ↑"); 124 | } 125 | 126 | @Override 127 | public void onStateReleaseToSecond() { 128 | Log.d("mytag","onStateReleaseToSecond"); 129 | tvHeader.setText("松开进入二楼"); 130 | } 131 | 132 | @Override 133 | public void onStateReleaseToMain() { 134 | Log.d("mytag","onStateReleaseToMain"); 135 | tvHeader.setText("松开回到主页"); 136 | } 137 | 138 | @Override 139 | public void onStateMain() { 140 | Log.d("mytag","onStateMain"); 141 | tvHeader.setText("下拉赢好礼 ↓"); 142 | tvHeader.setVisibility(View.VISIBLE); 143 | } 144 | 145 | @Override 146 | public void onStateSecond() { 147 | Log.d("mytag","onStateSecond"); 148 | tvHeader.setVisibility(View.GONE); 149 | } 150 | }); 151 | return view; 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/ScrollViewRefreshFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.util.Log; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import com.zhl.secondaryscreen.R; 14 | import com.zhl.secondaryscreen.view.OnSecondFloorScrollistener; 15 | import com.zhl.secondaryscreen.view.OnStateListener; 16 | import com.zhl.secondaryscreen.view.SecondFloorView; 17 | 18 | /** 19 | * 描述: 20 | * Created by zhaohl on 2020-4-3. 21 | */ 22 | public class ScrollViewRefreshFragment extends Fragment { 23 | SecondFloorView secondFloorView; 24 | TextView refreshView; 25 | 26 | @Override 27 | public void onCreate(@Nullable Bundle savedInstanceState) { 28 | super.onCreate(savedInstanceState); 29 | } 30 | 31 | @Nullable 32 | @Override 33 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 34 | View view = inflater.inflate(R.layout.fg_second_floor,null); 35 | initView(view); 36 | return view; 37 | } 38 | 39 | private void initView(View view) { 40 | secondFloorView = view.findViewById(R.id.second_floor_view); 41 | refreshView = view.findViewById(R.id.tv_pull_header); 42 | secondFloorView.setOnSecondFloorScrollistener(new OnSecondFloorScrollistener() { 43 | @Override 44 | public void onScroll(int scrollY) { 45 | // Log.d("mytag","scrolly==="+scrollY); 46 | } 47 | 48 | @Override 49 | public void onSwipeToSecondFloor() { 50 | 51 | } 52 | 53 | @Override 54 | public void onSwipeToMain() { 55 | 56 | } 57 | 58 | @Override 59 | public void onRefresh() { 60 | Log.d("mytag","开始刷新"); 61 | secondFloorView.postDelayed(new Runnable() { 62 | @Override 63 | public void run() { 64 | secondFloorView.finishRefresh(); 65 | } 66 | },2000); 67 | } 68 | }); 69 | secondFloorView.setOnStateListener(new OnStateListener() { 70 | @Override 71 | public void onStateChanged(String state) { 72 | // Log.d("mytag","onStateChanged=="+state); 73 | } 74 | 75 | @Override 76 | public void onStateRefreshing() { 77 | Log.d("mytag","onStateRefreshing"); 78 | refreshView.setText("正在刷新..."); 79 | } 80 | 81 | @Override 82 | public void onStatePullToRefresh() { 83 | Log.d("mytag","onStatePullToRefresh"); 84 | refreshView.setText("下拉赢好礼 ↓"); 85 | } 86 | 87 | @Override 88 | public void onStateReleaseToRefresh() { 89 | Log.d("mytag","onStateReleaseToRefresh"); 90 | refreshView.setText("松开开始刷新 ↑"); 91 | } 92 | 93 | @Override 94 | public void onStateReleaseToSecond() { 95 | Log.d("mytag","onStateReleaseToSecond"); 96 | refreshView.setText("松开进入二楼"); 97 | } 98 | 99 | @Override 100 | public void onStateReleaseToMain() { 101 | Log.d("mytag","onStateReleaseToMain"); 102 | refreshView.setText("松开回到主页"); 103 | } 104 | 105 | @Override 106 | public void onStateMain() { 107 | Log.d("mytag","onStateMain"); 108 | refreshView.setText("下拉赢好礼 ↓"); 109 | refreshView.setVisibility(View.VISIBLE); 110 | } 111 | 112 | @Override 113 | public void onStateSecond() { 114 | Log.d("mytag","onStateSecond"); 115 | refreshView.setVisibility(View.GONE); 116 | } 117 | }); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/fragment/TagImageFragment.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.fragment; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.support.v4.app.Fragment; 7 | import android.view.LayoutInflater; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import com.zhl.secondaryscreen.R; 12 | import com.zhl.secondaryscreen.view.TagImageView; 13 | 14 | /** 15 | * 描述: 16 | * Created by zhaohl on 2019-6-26. 17 | */ 18 | public class TagImageFragment extends Fragment { 19 | TagImageView imageView; 20 | 21 | public static TagImageFragment newInstance(){ 22 | return new TagImageFragment(); 23 | } 24 | 25 | @Override 26 | public void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | } 29 | 30 | @Nullable 31 | @Override 32 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { 33 | View view = inflater.inflate(R.layout.activity_custom_view_test, null); 34 | imageView = view.findViewById(R.id.tag_img); 35 | // imageView.setTagSize(50); 36 | // imageView.setTagLocation(TagImageView.Location.ON_TOP_lEFT); 37 | // imageView.showTag(false); 38 | // imageView.setTagBackgroud(Color.parseColor("#FF3396FF")); 39 | // imageView.setTagTextColor(Color.parseColor("#FFFF336D")); 40 | return view; 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/CustomRefreshHeader.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | import android.content.Context; 4 | import android.support.annotation.NonNull; 5 | import android.support.annotation.Nullable; 6 | import android.util.AttributeSet; 7 | import android.util.Log; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.widget.ImageView; 11 | import android.widget.LinearLayout; 12 | import android.widget.TextView; 13 | 14 | import com.airbnb.lottie.LottieAnimationView; 15 | import com.scwang.smartrefresh.layout.api.RefreshHeader; 16 | import com.scwang.smartrefresh.layout.api.RefreshKernel; 17 | import com.scwang.smartrefresh.layout.api.RefreshLayout; 18 | import com.scwang.smartrefresh.layout.constant.RefreshState; 19 | import com.scwang.smartrefresh.layout.constant.SpinnerStyle; 20 | import com.zhl.secondaryscreen.R; 21 | 22 | /** 23 | * 描述: 24 | * Created by zhaohl on 2019-1-16. 25 | */ 26 | public class CustomRefreshHeader extends LinearLayout implements RefreshHeader { 27 | private LottieAnimationView lottieAnimationView; 28 | private ImageView arrow; 29 | private TextView tipView; 30 | 31 | public CustomRefreshHeader(Context context) { 32 | this(context, null); 33 | } 34 | 35 | public CustomRefreshHeader(Context context, @Nullable AttributeSet attrs) { 36 | this(context, attrs, -1); 37 | } 38 | 39 | public CustomRefreshHeader(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 40 | super(context, attrs, defStyleAttr); 41 | View view = LayoutInflater.from(context).inflate(R.layout.custom_refresh_header, null); 42 | lottieAnimationView = view.findViewById(R.id.lottie_anim); 43 | arrow = view.findViewById(R.id.arrow); 44 | tipView = view.findViewById(R.id.tip_view); 45 | addView(view); 46 | } 47 | 48 | @NonNull 49 | @Override 50 | public View getView() { 51 | return this; 52 | } 53 | 54 | @NonNull 55 | @Override 56 | public SpinnerStyle getSpinnerStyle() { 57 | return SpinnerStyle.Translate; 58 | } 59 | 60 | @Override 61 | public void setPrimaryColors(int... colors) { 62 | 63 | } 64 | 65 | @Override 66 | public void onInitialized(@NonNull RefreshKernel kernel, int height, int extendHeight) { 67 | 68 | } 69 | 70 | @Override 71 | public void onPulling(float percent, int offset, int height, int extendHeight) { 72 | Log.d("mytag","----onPulling..."); 73 | } 74 | 75 | @Override 76 | public void onReleasing(float percent, int offset, int height, int extendHeight) { 77 | Log.d("mytag","----onReleasing..."); 78 | } 79 | 80 | @Override 81 | public void onReleased(RefreshLayout refreshLayout, int height, int extendHeight) { 82 | Log.d("mytag","----onReleased..."); 83 | } 84 | 85 | @Override 86 | public void onStartAnimator(@NonNull RefreshLayout refreshLayout, int height, int extendHeight) { 87 | lottieAnimationView.playAnimation(); 88 | Log.d("mytag","----onStartAnimator..."); 89 | } 90 | 91 | @Override 92 | public int onFinish(@NonNull RefreshLayout refreshLayout, boolean success) { 93 | lottieAnimationView.pauseAnimation(); 94 | if (success) { 95 | tipView.setText("刷新成功"); 96 | } else { 97 | tipView.setText("刷新失败"); 98 | } 99 | return 400; 100 | } 101 | 102 | @Override 103 | public void onHorizontalDrag(float percentX, int offsetX, int offsetMax) { 104 | 105 | } 106 | 107 | @Override 108 | public boolean isSupportHorizontalDrag() { 109 | return false; 110 | } 111 | 112 | @Override 113 | public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) { 114 | switch (newState) { 115 | case None: 116 | case PullDownToRefresh: 117 | tipView.setText("下拉开始刷新"); 118 | arrow.setVisibility(VISIBLE); 119 | arrow.animate().rotation(0); 120 | break; 121 | case ReleaseToRefresh: 122 | tipView.setText("释放刷新"); 123 | arrow.animate().rotation(180); 124 | break; 125 | case Refreshing: 126 | tipView.setText("正在刷新..."); 127 | arrow.setVisibility(GONE); 128 | Log.d("mytag","----正在刷新..."); 129 | break; 130 | 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/ImageProgressBar.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Bitmap; 6 | import android.graphics.BitmapFactory; 7 | import android.graphics.Canvas; 8 | import android.graphics.Paint; 9 | import android.graphics.PorterDuff; 10 | import android.graphics.PorterDuffXfermode; 11 | import android.graphics.Rect; 12 | import android.graphics.RectF; 13 | import android.support.annotation.Nullable; 14 | import android.util.AttributeSet; 15 | import android.view.View; 16 | 17 | import com.zhl.secondaryscreen.R; 18 | 19 | 20 | /** 21 | * 描述: 22 | * Created by zhaohl on 2018-11-27. 23 | */ 24 | public class ImageProgressBar extends View { 25 | private Paint paint; 26 | private Bitmap bgBitmap; 27 | private int bgResID = -1; 28 | private int roundConer; 29 | private int max = 100; 30 | private float progress = 0; 31 | private int coverColor = 0x77E6E9E7; 32 | private int mode = 0; 33 | private PorterDuff.Mode styleMode = PorterDuff.Mode.DST_IN; 34 | public ImageProgressBar(Context context) { 35 | this(context,null); 36 | } 37 | 38 | public ImageProgressBar(Context context, @Nullable AttributeSet attrs) { 39 | this(context, attrs,-1); 40 | } 41 | 42 | public ImageProgressBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | paint = new Paint(Paint.ANTI_ALIAS_FLAG); 45 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.ImageProgressBar); 46 | bgResID = array.getResourceId(R.styleable.ImageProgressBar_imagebg,-1); 47 | roundConer = (int) array.getDimension(R.styleable.ImageProgressBar_roundConer,5); 48 | coverColor = array.getColor(R.styleable.ImageProgressBar_coverColor,coverColor); 49 | mode = array.getInt(R.styleable.ImageProgressBar_styleMode,coverColor); 50 | switch (mode){ 51 | case 0: 52 | styleMode = PorterDuff.Mode.DST_IN; 53 | break; 54 | case 1: 55 | styleMode = PorterDuff.Mode.SRC_IN; 56 | break; 57 | } 58 | array.recycle(); 59 | if(bgResID!=-1){ 60 | generateImageBg(bgResID); 61 | }else{ 62 | throw new RuntimeException("need a image bg!"); 63 | } 64 | setLayerType(View.LAYER_TYPE_SOFTWARE,paint);// 关掉硬件加速 否则 paint.setXfermode 无效 65 | } 66 | 67 | public void setImageBg(Bitmap bgBitmap){ 68 | this.bgBitmap = bgBitmap; 69 | invalidate(); 70 | } 71 | public void setImageBg(int resID){ 72 | this.bgResID = resID; 73 | generateImageBg(bgResID); 74 | invalidate(); 75 | } 76 | 77 | private void generateImageBg(int res) { 78 | BitmapFactory.Options options = new BitmapFactory.Options(); 79 | bgBitmap = BitmapFactory.decodeResource(getResources(),res,options); 80 | } 81 | 82 | @Override 83 | protected void onDraw(Canvas canvas) { 84 | drawImageBg(canvas); 85 | drawProgress(canvas); 86 | } 87 | 88 | private void drawProgress(Canvas canvas) { 89 | paint.setColor(coverColor); 90 | paint.setXfermode(new PorterDuffXfermode(styleMode)); 91 | canvas.drawRect(new Rect((int) ((progress/max)*getWidth()),0,getWidth(),getHeight()),paint); 92 | paint.setXfermode(null); 93 | } 94 | 95 | private void drawImageBg(Canvas canvas) { 96 | paint = new Paint(Paint.ANTI_ALIAS_FLAG);// 这里不重新初始化一个画笔刷新后绘出的底图会出问题 97 | bgBitmap = Bitmap.createScaledBitmap(bgBitmap,getWidth(),getHeight(),true); 98 | canvas.drawRoundRect(new RectF(0,0,getWidth(),getHeight()),roundConer,roundConer,paint); 99 | paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 100 | canvas.drawBitmap(bgBitmap,0,0,paint); 101 | } 102 | 103 | 104 | public int getMax() { 105 | return max; 106 | } 107 | 108 | public void setMax(int max) { 109 | this.max = max; 110 | } 111 | 112 | public float getProgress() { 113 | return progress; 114 | } 115 | 116 | public void setProgress(int progress) { 117 | if (progress > max) { 118 | progress = max; 119 | } else { 120 | this.progress = progress; 121 | postInvalidate(); 122 | } 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/OnSecondFloorScrollistener.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | /** 4 | * 描述: 5 | * Created by zhaohl on 2020-3-31. 6 | */ 7 | public interface OnSecondFloorScrollistener { 8 | /** 9 | * 滚动回调 10 | * @param scrollY 11 | */ 12 | public void onScroll(int scrollY); 13 | 14 | /** 15 | * 切换到第二页 16 | */ 17 | public void onSwipeToSecondFloor(); 18 | 19 | /** 20 | * 切换到主页 21 | */ 22 | public void onSwipeToMain(); 23 | 24 | /** 25 | * 刷新 26 | */ 27 | public void onRefresh(); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/OnStateListener.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | /** 4 | * 描述: 5 | * Created by zhaohl on 2020-4-1. 6 | */ 7 | public interface OnStateListener { 8 | public void onStateChanged(String state); 9 | public void onStateRefreshing(); 10 | public void onStatePullToRefresh(); 11 | public void onStateReleaseToRefresh(); 12 | public void onStateReleaseToSecond(); 13 | public void onStateReleaseToMain(); 14 | public void onStateMain(); 15 | public void onStateSecond(); 16 | } 17 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/SecondFloorView.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorSet; 5 | import android.animation.ObjectAnimator; 6 | import android.animation.ValueAnimator; 7 | import android.content.Context; 8 | import android.content.res.TypedArray; 9 | import android.graphics.Rect; 10 | import android.support.v4.view.ViewPager; 11 | import android.support.v7.widget.GridLayoutManager; 12 | import android.support.v7.widget.LinearLayoutManager; 13 | import android.support.v7.widget.RecyclerView; 14 | import android.support.v7.widget.StaggeredGridLayoutManager; 15 | import android.util.AttributeSet; 16 | import android.util.Log; 17 | import android.view.MotionEvent; 18 | import android.view.View; 19 | import android.view.ViewConfiguration; 20 | import android.view.ViewGroup; 21 | import android.view.animation.LinearInterpolator; 22 | import android.widget.AbsListView; 23 | import android.widget.ListView; 24 | 25 | import com.zhl.secondaryscreen.R; 26 | 27 | import java.util.ArrayList; 28 | 29 | /** 30 | * 描述:下拉的展示第二屏的viewgroup(类似mgtv下拉展示广告) 31 | * Created by zhaohl on 2020-03-31. 32 | */ 33 | public class SecondFloorView extends ViewGroup { 34 | private View secondaryView; 35 | private View mainView; 36 | private int downX, downY, endY, lastTouchX, lastTouchY; 37 | private boolean isBeingDraged; 38 | private float resistance = 0.60f;// 下拉阻力 39 | private boolean isScrollerDown = true; 40 | private int pullRefreshDistance = 260; 41 | private int topOffset = 0;// mainview头部偏移 42 | private ArrayList viewPagers = new ArrayList<>(); 43 | private ArrayList recyclerViews = new ArrayList<>(); 44 | private ArrayList absListViews = new ArrayList<>(); 45 | private float touchSlop; 46 | private OnSecondFloorScrollistener scrollistener; 47 | private OnStateListener stateListener; 48 | private String curState = State.STATE_MAIN; 49 | private MotionEvent touchEvent; 50 | 51 | public SecondFloorView(Context context) { 52 | this(context, null); 53 | } 54 | 55 | public SecondFloorView(Context context, AttributeSet attrs) { 56 | this(context, attrs, -1); 57 | } 58 | 59 | public SecondFloorView(Context context, AttributeSet attrs, int defStyleAttr) { 60 | super(context, attrs, defStyleAttr); 61 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SecondFloorView); 62 | resistance = array.getFloat(R.styleable.SecondFloorView_resistance, resistance); 63 | pullRefreshDistance = array.getInteger(R.styleable.SecondFloorView_pullRefreshDistance, pullRefreshDistance); 64 | topOffset = array.getDimensionPixelSize(R.styleable.SecondFloorView_topOffset,topOffset); 65 | touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 66 | if (stateListener != null) { 67 | stateListener.onStateMain(); 68 | } 69 | } 70 | 71 | @Override 72 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 73 | int count = getChildCount(); 74 | if (count > 2) { 75 | throw new RuntimeException("only can host 2 direct child view"); 76 | } 77 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 78 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 79 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 80 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 81 | int usedWidth = 0; 82 | int usedHeight = 0; 83 | for (int i = 0; i < getChildCount(); i++) { 84 | View childView = getChildAt(i); 85 | if (childView.getVisibility() != View.GONE) { 86 | SecondFloorView.LayoutParams params = (SecondFloorView.LayoutParams) childView.getLayoutParams(); 87 | int childWidthSpec = MeasureSpec.AT_MOST; 88 | int childHeightSpec = MeasureSpec.AT_MOST; 89 | switch (params.width) { 90 | case SecondFloorView.LayoutParams.MATCH_PARENT: 91 | if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) { 92 | childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); 93 | } else { 94 | childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 95 | } 96 | break; 97 | case SecondFloorView.LayoutParams.WRAP_CONTENT: 98 | if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) { 99 | childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST); 100 | } else { 101 | childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 102 | } 103 | break; 104 | default: 105 | childWidthSpec = MeasureSpec.makeMeasureSpec(params.width, MeasureSpec.EXACTLY); 106 | break; 107 | } 108 | usedWidth += MeasureSpec.getSize(childWidthSpec) + params.leftMargin + params.rightMargin; 109 | switch (params.height) { 110 | case SecondFloorView.LayoutParams.MATCH_PARENT: 111 | if (heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST) { 112 | childHeightSpec = MeasureSpec.makeMeasureSpec(heightSize+topOffset, MeasureSpec.EXACTLY); 113 | } else { 114 | childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 115 | } 116 | break; 117 | case SecondFloorView.LayoutParams.WRAP_CONTENT: 118 | if (heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST) { 119 | childHeightSpec = MeasureSpec.makeMeasureSpec(heightSize+topOffset, MeasureSpec.AT_MOST); 120 | } else { 121 | childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 122 | } 123 | break; 124 | default: 125 | childHeightSpec = MeasureSpec.makeMeasureSpec(params.height+topOffset, MeasureSpec.EXACTLY); 126 | break; 127 | } 128 | usedHeight += MeasureSpec.getSize(childHeightSpec) + params.bottomMargin + params.topMargin; 129 | measureChild(childView, childWidthSpec, childHeightSpec); 130 | } 131 | } 132 | if (widthMode == MeasureSpec.UNSPECIFIED) { 133 | widthSize = usedWidth; 134 | } 135 | if (heightMode == MeasureSpec.UNSPECIFIED) { 136 | heightSize = usedHeight; 137 | } 138 | setMeasuredDimension(widthSize, heightSize); 139 | secondaryView = getChildAt(0); 140 | mainView = getChildAt(1); 141 | } 142 | 143 | @Override 144 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 145 | getAllRecyclerView(recyclerViews, this); 146 | getAllAbsListView(absListViews, this); 147 | if (secondaryView != null) { 148 | secondaryView.layout(0, -secondaryView.getMeasuredHeight()+topOffset, secondaryView.getMeasuredWidth(), topOffset); 149 | } 150 | if (mainView != null) { 151 | mainView.layout(0, topOffset, mainView.getMeasuredWidth(), secondaryView.getMeasuredHeight()); 152 | } 153 | } 154 | 155 | private void getAllViewPager(ArrayList viewPagers, ViewGroup parent) { 156 | int childCount = parent.getChildCount(); 157 | for (int i = 0; i < childCount; i++) { 158 | View child = parent.getChildAt(i); 159 | if (child instanceof ViewPager) { 160 | viewPagers.add((ViewPager) child); 161 | } else if (child instanceof ViewGroup) { 162 | getAllViewPager(viewPagers, (ViewGroup) child); 163 | } 164 | } 165 | } 166 | 167 | private void getAllRecyclerView(ArrayList recyclerViews, ViewGroup parent) { 168 | int childCount = parent.getChildCount(); 169 | for (int i = 0; i < childCount; i++) { 170 | View child = parent.getChildAt(i); 171 | if (child instanceof RecyclerView) { 172 | recyclerViews.add((RecyclerView) child); 173 | } else if (child instanceof ViewGroup) { 174 | getAllRecyclerView(recyclerViews, (ViewGroup) child); 175 | } 176 | } 177 | } 178 | 179 | private void getAllAbsListView(ArrayList listViews, ViewGroup parent) { 180 | int childCount = parent.getChildCount(); 181 | for (int i = 0; i < childCount; i++) { 182 | View child = parent.getChildAt(i); 183 | if (child instanceof ListView) { 184 | listViews.add((ListView) child); 185 | } else if (child instanceof ViewGroup) { 186 | getAllAbsListView(listViews, (ViewGroup) child); 187 | } 188 | } 189 | } 190 | 191 | @Override 192 | public boolean onInterceptTouchEvent(MotionEvent ev) { 193 | // // 处理viewpager的事件冲突 194 | // ViewPager pager = getTouchedViewPager(ev); 195 | // if(pager!=null&&pager.getCurrentItem()!=0){ 196 | // return super.onInterceptTouchEvent(ev); 197 | // } 198 | // 处理recyclerview和listview的事件冲突 199 | RecyclerView recyclerView = getTouchedRecyclerView(ev); 200 | boolean recyclerViewFirstItemVisible = false; 201 | boolean absListViewFirstItemVisible = false; 202 | if (recyclerView != null) { 203 | RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); 204 | if (layoutManager != null && layoutManager instanceof LinearLayoutManager) { 205 | if (((LinearLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition() != 0) { 206 | return super.onInterceptTouchEvent(ev); 207 | } else { 208 | recyclerViewFirstItemVisible = true; 209 | } 210 | } else if (layoutManager != null && layoutManager instanceof GridLayoutManager) { 211 | if (((GridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPosition() != 0) { 212 | return super.onInterceptTouchEvent(ev); 213 | } else { 214 | recyclerViewFirstItemVisible = true; 215 | } 216 | } else if (layoutManager != null && layoutManager instanceof StaggeredGridLayoutManager) { 217 | int[] mFirstVisible = null; 218 | mFirstVisible = ((StaggeredGridLayoutManager) layoutManager).findFirstCompletelyVisibleItemPositions(mFirstVisible); 219 | if (mFirstVisible != null && mFirstVisible[0] != 0) { 220 | return super.onInterceptTouchEvent(ev); 221 | } else { 222 | recyclerViewFirstItemVisible = true; 223 | } 224 | } 225 | } 226 | AbsListView absListView = getTouchedAbsListView(ev); 227 | if (absListView != null) { 228 | if (absListView.getFirstVisiblePosition() != 0) { 229 | return super.onInterceptTouchEvent(ev); 230 | } else { 231 | absListViewFirstItemVisible = true; 232 | } 233 | } 234 | 235 | switch (ev.getAction()) { 236 | case MotionEvent.ACTION_DOWN: 237 | downX = (int) ev.getRawX(); 238 | downY = (int) ev.getRawY(); 239 | break; 240 | case MotionEvent.ACTION_MOVE: 241 | float delX = ev.getRawX() - downX; 242 | float delY = ev.getRawY() - downY; 243 | if (Math.abs(delY) > touchSlop && Math.abs(delY) > Math.abs(delX) && (recyclerViewFirstItemVisible || absListViewFirstItemVisible) && delY > 0) { 244 | return true; 245 | } 246 | if (mainView.getScrollY() == 0 && delY > 0) { 247 | return true; 248 | } 249 | if (curState == State.STATE_REFRESHING) { 250 | return true; 251 | } 252 | // if(secondaryView.getX()==0f&& Math.abs(delX)>touchSlop&& Math.abs(delX)> Math.abs(delY)&&pager!=null&&pager.getCurrentItem()==pager.getChildCount()-1&&delX<0){ 253 | // return true; 254 | // } 255 | break; 256 | case MotionEvent.ACTION_UP: 257 | break; 258 | } 259 | 260 | return super.onInterceptTouchEvent(ev); 261 | } 262 | 263 | private ViewPager getTouchedViewPager(MotionEvent ev) { 264 | if (viewPagers == null || viewPagers.size() == 0) { 265 | return null; 266 | } 267 | Rect mRect = new Rect(); 268 | for (ViewPager viewPager : viewPagers) { 269 | viewPager.getHitRect(mRect); 270 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) { 271 | return viewPager; 272 | } 273 | } 274 | return null; 275 | } 276 | 277 | private RecyclerView getTouchedRecyclerView(MotionEvent ev) { 278 | if (recyclerViews == null || recyclerViews.size() == 0) { 279 | return null; 280 | } 281 | Rect mRect = new Rect(); 282 | for (RecyclerView recyclerView : recyclerViews) { 283 | recyclerView.getHitRect(mRect); 284 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) { 285 | return recyclerView; 286 | } 287 | } 288 | return null; 289 | } 290 | 291 | private AbsListView getTouchedAbsListView(MotionEvent ev) { 292 | if (absListViews == null || absListViews.size() == 0) { 293 | return null; 294 | } 295 | Rect mRect = new Rect(); 296 | for (AbsListView listView : absListViews) { 297 | listView.getHitRect(mRect); 298 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) { 299 | return listView; 300 | } 301 | } 302 | return null; 303 | } 304 | 305 | @Override 306 | public boolean onTouchEvent(MotionEvent event) { 307 | touchEvent = event; 308 | switch (event.getAction()) { 309 | case MotionEvent.ACTION_DOWN: 310 | downX = (int) event.getRawX(); 311 | downY = (int) event.getRawY(); 312 | break; 313 | case MotionEvent.ACTION_MOVE: 314 | isBeingDraged = true; 315 | int moveX = (int) (event.getRawX() - downX); 316 | int moveY = (int) (event.getRawY() - downY); 317 | if (secondaryView.getY() < 0) { 318 | moveY *= resistance; 319 | } 320 | if (moveY > 0) { 321 | isScrollerDown = true; 322 | } else { 323 | isScrollerDown = false; 324 | } 325 | int translateY_second = endY + moveY; 326 | int translateY_main = endY + moveY; 327 | if (translateY_second >= secondaryView.getHeight()) { 328 | translateY_second = secondaryView.getHeight(); 329 | translateY_main = mainView.getHeight(); 330 | } 331 | if (translateY_second <= 0) { 332 | translateY_second = 0; 333 | translateY_main = 0; 334 | } 335 | secondaryView.setTranslationY(translateY_second); 336 | mainView.setTranslationY(translateY_main); 337 | if (isScrollerDown) { 338 | if (Math.abs(translateY_main) > 0 && Math.abs(translateY_main) <= pullRefreshDistance) { 339 | curState = State.STATE_PULL_TO_REFRESH; 340 | if (stateListener != null) { 341 | stateListener.onStatePullToRefresh(); 342 | stateListener.onStateChanged(curState); 343 | } 344 | } else if (Math.abs(translateY_main) > pullRefreshDistance && Math.abs(translateY_main) < mainView.getHeight() / 3) { 345 | if(curState!=State.STATE_REFRESHING){ 346 | curState = State.STATE_RELEASE_TO_REFRESH; 347 | if (stateListener != null) { 348 | stateListener.onStateReleaseToRefresh(); 349 | stateListener.onStateChanged(curState); 350 | } 351 | } 352 | } else if (Math.abs(translateY_main) >= mainView.getHeight() / 3) { 353 | if(curState!=State.STATE_REFRESHING){ 354 | curState = State.STATE_RELEASE_TO_SECOND; 355 | if (stateListener != null) { 356 | stateListener.onStateReleaseToSecond(); 357 | stateListener.onStateChanged(curState); 358 | } 359 | } 360 | } 361 | } else { 362 | if (Math.abs(translateY_main) >= mainView.getHeight() / 3) { 363 | curState = State.STATE_RELEASE_TO_MAIN; 364 | if (stateListener != null) { 365 | stateListener.onStateReleaseToMain(); 366 | stateListener.onStateChanged(curState); 367 | } 368 | } else { 369 | curState = State.STATE_SECOND; 370 | if (stateListener != null) { 371 | stateListener.onStateSecond(); 372 | stateListener.onStateChanged(curState); 373 | } 374 | } 375 | } 376 | if (scrollistener != null) { 377 | scrollistener.onScroll(translateY_main); 378 | } 379 | lastTouchX = (int) event.getRawX(); 380 | lastTouchY = (int) event.getRawY(); 381 | break; 382 | case MotionEvent.ACTION_UP: 383 | isBeingDraged = false; 384 | endY = (int) mainView.getTranslationY(); 385 | if (curState == State.STATE_RELEASE_TO_REFRESH) { 386 | if (scrollistener != null) { 387 | startReleaseAnim(); 388 | } else { 389 | startTranslateAnim(); 390 | } 391 | }else if(curState == State.STATE_REFRESHING){ 392 | startReleaseAnim(); 393 | }else { 394 | startTranslateAnim(); 395 | } 396 | 397 | break; 398 | } 399 | return true; 400 | } 401 | 402 | public void translateToSecondaryView() { 403 | endY = mainView.getHeight(); 404 | isScrollerDown = true; 405 | startTranslateAnim(); 406 | } 407 | 408 | public void translateToMainView() { 409 | endY = mainView.getHeight() / 3; 410 | isScrollerDown = false; 411 | startTranslateAnim(); 412 | } 413 | 414 | public void finishRefresh() { 415 | translateToMainView(); 416 | } 417 | 418 | public boolean isStillMainView() { 419 | return endY == 0 && mainView.getTranslationY() == 0; 420 | } 421 | 422 | public String getCurState() { 423 | return curState; 424 | } 425 | 426 | public void setCurState(String curState) { 427 | this.curState = curState; 428 | } 429 | 430 | private void startReleaseAnim() { 431 | float secondTranslationY = pullRefreshDistance; 432 | float mainTranslationY = pullRefreshDistance; 433 | AnimatorSet animator = new AnimatorSet(); 434 | ObjectAnimator animator_secondaryView = ObjectAnimator.ofFloat(secondaryView, "translationY", secondTranslationY); 435 | ObjectAnimator animator_mainView = ObjectAnimator.ofFloat(mainView, "translationY", mainTranslationY); 436 | animator_mainView.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 437 | @Override 438 | public void onAnimationUpdate(ValueAnimator animation) { 439 | float value = (float) animation.getAnimatedValue(); 440 | if (scrollistener != null) { 441 | scrollistener.onScroll((int) value); 442 | } 443 | } 444 | }); 445 | animator.setDuration(200); 446 | animator.setInterpolator(new LinearInterpolator()); 447 | animator.addListener(new Animator.AnimatorListener() { 448 | @Override 449 | public void onAnimationStart(Animator animation) { 450 | 451 | } 452 | 453 | @Override 454 | public void onAnimationEnd(Animator animation) { 455 | curState = State.STATE_REFRESHING; 456 | endY = (int) mainView.getTranslationY(); 457 | if (scrollistener != null) { 458 | scrollistener.onRefresh(); 459 | } 460 | if (stateListener != null) { 461 | stateListener.onStateRefreshing(); 462 | } 463 | Log.d("mytag", "----curState===" + curState); 464 | } 465 | 466 | @Override 467 | public void onAnimationCancel(Animator animation) { 468 | 469 | } 470 | 471 | @Override 472 | public void onAnimationRepeat(Animator animation) { 473 | 474 | } 475 | }); 476 | animator.play(animator_secondaryView).with(animator_mainView); 477 | animator.start(); 478 | 479 | } 480 | 481 | private void startTranslateAnim() { 482 | float secondTranslationY = 0; 483 | float mainTranslationY = 0; 484 | if (isScrollerDown) {//下滑 485 | if (endY > secondaryView.getHeight() / 3-100) { 486 | secondTranslationY = secondaryView.getHeight()-topOffset; 487 | mainTranslationY = mainView.getHeight(); 488 | isScrollerDown = false; 489 | } else { 490 | secondTranslationY = 0; 491 | mainTranslationY = 0; 492 | isScrollerDown = true; 493 | } 494 | } else { 495 | if (endY < mainView.getHeight() * 2 / 3+100) { 496 | secondTranslationY = 0; 497 | mainTranslationY = 0; 498 | isScrollerDown = true; 499 | } else { 500 | secondTranslationY = secondaryView.getHeight()-topOffset; 501 | mainTranslationY = mainView.getHeight(); 502 | isScrollerDown = false; 503 | } 504 | } 505 | AnimatorSet animator = new AnimatorSet(); 506 | ObjectAnimator animator_secondaryView = ObjectAnimator.ofFloat(secondaryView, "translationY", secondTranslationY); 507 | ObjectAnimator animator_mainView = ObjectAnimator.ofFloat(mainView, "translationY", mainTranslationY); 508 | animator_mainView.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 509 | @Override 510 | public void onAnimationUpdate(ValueAnimator animation) { 511 | float value = (float) animation.getAnimatedValue(); 512 | if (scrollistener != null) { 513 | scrollistener.onScroll((int) value); 514 | } 515 | } 516 | }); 517 | animator.setDuration(200); 518 | animator.setInterpolator(new LinearInterpolator()); 519 | animator.addListener(new Animator.AnimatorListener() { 520 | @Override 521 | public void onAnimationStart(Animator animation) { 522 | 523 | } 524 | 525 | @Override 526 | public void onAnimationEnd(Animator animation) { 527 | endY = (int) mainView.getTranslationY(); 528 | Log.d("mytag", "----endy==" + endY); 529 | if (endY == 0) { 530 | curState = State.STATE_MAIN; 531 | if (stateListener != null) { 532 | stateListener.onStateMain(); 533 | } 534 | } else if (endY >= mainView.getHeight()) { 535 | curState = State.STATE_SECOND; 536 | if (stateListener != null) { 537 | stateListener.onStateSecond(); 538 | } 539 | } 540 | long time = System.currentTimeMillis(); 541 | if (isBeingDraged) { 542 | isBeingDraged = false; 543 | SecondFloorView.super.dispatchTouchEvent(MotionEvent.obtain(time, time, MotionEvent.ACTION_DOWN, lastTouchX, lastTouchY, 0)); 544 | SecondFloorView.super.dispatchTouchEvent(MotionEvent.obtain(time, time, MotionEvent.ACTION_MOVE, lastTouchX, lastTouchY, 0)); 545 | } 546 | Log.d("mytag", "----curState===" + curState); 547 | } 548 | 549 | @Override 550 | public void onAnimationCancel(Animator animation) { 551 | 552 | } 553 | 554 | @Override 555 | public void onAnimationRepeat(Animator animation) { 556 | 557 | } 558 | }); 559 | animator.play(animator_secondaryView).with(animator_mainView); 560 | animator.start(); 561 | 562 | } 563 | 564 | public static class LayoutParams extends MarginLayoutParams { 565 | 566 | public LayoutParams(Context c, AttributeSet attrs) { 567 | super(c, attrs); 568 | } 569 | 570 | public LayoutParams(int width, int height) { 571 | super(width, height); 572 | } 573 | 574 | public LayoutParams(ViewGroup.LayoutParams source) { 575 | super(source); 576 | } 577 | } 578 | 579 | @Override 580 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 581 | return new SecondFloorView.LayoutParams(p); 582 | } 583 | 584 | @Override 585 | protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 586 | return new SecondFloorView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 587 | } 588 | 589 | @Override 590 | public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 591 | return new SecondFloorView.LayoutParams(getContext(), attrs); 592 | } 593 | 594 | @Override 595 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 596 | return p instanceof SecondFloorView.LayoutParams; 597 | } 598 | 599 | public float getResistance() { 600 | return resistance; 601 | } 602 | 603 | public void setResistance(float resistance) { 604 | this.resistance = resistance; 605 | } 606 | 607 | public OnSecondFloorScrollistener getSecondFloorScrollistener() { 608 | return scrollistener; 609 | } 610 | 611 | public void setOnSecondFloorScrollistener(OnSecondFloorScrollistener scrollistener) { 612 | this.scrollistener = scrollistener; 613 | } 614 | 615 | public OnStateListener getOnStateListener() { 616 | return stateListener; 617 | } 618 | 619 | public void setOnStateListener(OnStateListener stateListener) { 620 | this.stateListener = stateListener; 621 | } 622 | 623 | public static class State { 624 | public static final String STATE_IDAL = "STATE_IDAL"; 625 | public static final String STATE_PULL_TO_REFRESH = "STATE_PULL_TO_REFRESH"; 626 | public static final String STATE_RELEASE_TO_REFRESH = "STATE_RELEASE_TO_REFRESH"; 627 | public static final String STATE_REFRESHING = "STATE_REFRESHING"; 628 | public static final String STATE_RELEASE_TO_SECOND = "STATE_RELEASE_TO_SECOND"; 629 | public static final String STATE_RELEASE_TO_MAIN = "STATE_RELEASE_TO_MAIN"; 630 | public static final String STATE_MAIN = "STATE_MAIN"; 631 | public static final String STATE_SECOND = "STATE_SECOND"; 632 | } 633 | } 634 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/SecondaryScreenView.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorSet; 5 | import android.animation.ObjectAnimator; 6 | import android.content.Context; 7 | import android.content.res.TypedArray; 8 | import android.graphics.Rect; 9 | import android.support.v4.view.ViewPager; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | import android.view.View; 13 | import android.view.ViewConfiguration; 14 | import android.view.ViewGroup; 15 | import android.view.animation.LinearInterpolator; 16 | 17 | import com.zhl.secondaryscreen.R; 18 | 19 | import java.util.ArrayList; 20 | 21 | /** 22 | * 描述:左滑负一屏的viewgroup 23 | * Created by zhaohl on 2019-1-18. 24 | */ 25 | public class SecondaryScreenView extends ViewGroup { 26 | private View secondaryView; 27 | private View mainView; 28 | private int downX, downY, endX; 29 | private float rate = 0.60f; 30 | private boolean isScrollerRight = true; 31 | private ArrayList viewPagers = new ArrayList<>(); 32 | private float touchSlop; 33 | 34 | public SecondaryScreenView(Context context) { 35 | this(context, null); 36 | } 37 | 38 | public SecondaryScreenView(Context context, AttributeSet attrs) { 39 | this(context, attrs, -1); 40 | } 41 | 42 | public SecondaryScreenView(Context context, AttributeSet attrs, int defStyleAttr) { 43 | super(context, attrs, defStyleAttr); 44 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.SecondaryScreenView); 45 | rate = array.getFloat(R.styleable.SecondaryScreenView_rate, rate); 46 | touchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); 47 | } 48 | 49 | @Override 50 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 51 | int count = getChildCount(); 52 | if (count > 2) { 53 | throw new RuntimeException("only can host 2 direct child view"); 54 | } 55 | int widthMode = MeasureSpec.getMode(widthMeasureSpec); 56 | int heightMode = MeasureSpec.getMode(heightMeasureSpec); 57 | int widthSize = MeasureSpec.getSize(widthMeasureSpec); 58 | int heightSize = MeasureSpec.getSize(heightMeasureSpec); 59 | int usedWidth = 0; 60 | int usedHeight = 0; 61 | for (int i = 0; i < getChildCount(); i++) { 62 | View childView = getChildAt(i); 63 | if (childView.getVisibility() != View.GONE) { 64 | SecondaryScreenView.LayoutParams params = (SecondaryScreenView.LayoutParams) childView.getLayoutParams(); 65 | int childWidthSpec = MeasureSpec.AT_MOST; 66 | int childHeightSpec = MeasureSpec.AT_MOST; 67 | switch (params.width) { 68 | case SecondaryScreenView.LayoutParams.MATCH_PARENT: 69 | if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) { 70 | childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); 71 | } else { 72 | childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 73 | } 74 | break; 75 | case SecondaryScreenView.LayoutParams.WRAP_CONTENT: 76 | if (widthMode == MeasureSpec.EXACTLY || widthMode == MeasureSpec.AT_MOST) { 77 | childWidthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST); 78 | } else { 79 | childWidthSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 80 | } 81 | break; 82 | default: 83 | childWidthSpec = MeasureSpec.makeMeasureSpec(params.width, MeasureSpec.EXACTLY); 84 | break; 85 | } 86 | usedWidth += MeasureSpec.getSize(childWidthSpec) + params.leftMargin + params.rightMargin; 87 | switch (params.height) { 88 | case SecondaryScreenView.LayoutParams.MATCH_PARENT: 89 | if (heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST) { 90 | childHeightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); 91 | } else { 92 | childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 93 | } 94 | break; 95 | case SecondaryScreenView.LayoutParams.WRAP_CONTENT: 96 | if (heightMode == MeasureSpec.EXACTLY || heightMode == MeasureSpec.AT_MOST) { 97 | childHeightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST); 98 | } else { 99 | childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 100 | } 101 | break; 102 | default: 103 | childHeightSpec = MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY); 104 | break; 105 | } 106 | usedHeight += MeasureSpec.getSize(childHeightSpec) + params.bottomMargin + params.topMargin; 107 | measureChild(childView, childWidthSpec, childHeightSpec); 108 | } 109 | } 110 | if (widthMode == MeasureSpec.UNSPECIFIED) { 111 | widthSize = usedWidth; 112 | } 113 | if (heightMode == MeasureSpec.UNSPECIFIED) { 114 | heightSize = usedHeight; 115 | } 116 | setMeasuredDimension(widthSize, heightSize); 117 | secondaryView = getChildAt(0); 118 | mainView = getChildAt(1); 119 | } 120 | 121 | @Override 122 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 123 | getAllViewPager(viewPagers, this); 124 | if (secondaryView != null) { 125 | secondaryView.layout(-secondaryView.getMeasuredWidth(), 0, 0, secondaryView.getMeasuredHeight()); 126 | } 127 | if (mainView != null) { 128 | mainView.layout(0, 0, mainView.getMeasuredWidth(), secondaryView.getMeasuredHeight()); 129 | } 130 | } 131 | 132 | private void getAllViewPager(ArrayList viewPagers, ViewGroup parent) { 133 | int childCount = parent.getChildCount(); 134 | for (int i = 0; i < childCount; i++) { 135 | View child = parent.getChildAt(i); 136 | if (child instanceof ViewPager) { 137 | viewPagers.add((ViewPager) child); 138 | } else if (child instanceof ViewGroup) { 139 | getAllViewPager(viewPagers, (ViewGroup) child); 140 | } 141 | } 142 | } 143 | 144 | @Override 145 | public boolean onInterceptTouchEvent(MotionEvent ev) { 146 | // 处理viewpager的事件冲突 147 | ViewPager pager = getTouchedViewPager(ev); 148 | if (pager != null && pager.getCurrentItem() != 0) { 149 | return super.onInterceptTouchEvent(ev); 150 | } 151 | switch (ev.getAction()) { 152 | case MotionEvent.ACTION_DOWN: 153 | downX = (int) ev.getRawX(); 154 | downY = (int) ev.getRawY(); 155 | break; 156 | case MotionEvent.ACTION_MOVE: 157 | float delX = ev.getRawX() - downX; 158 | float delY = ev.getRawY() - downY; 159 | if (Math.abs(delX) > touchSlop && Math.abs(delX) > Math.abs(delY) && pager != null && pager.getCurrentItem() == 0 && delX > 0) { 160 | return true; 161 | } 162 | // if(secondaryView.getX()==0f&& Math.abs(delX)>touchSlop&& Math.abs(delX)> Math.abs(delY)&&pager!=null&&pager.getCurrentItem()==pager.getChildCount()-1&&delX<0){ 163 | // return true; 164 | // } 165 | case MotionEvent.ACTION_UP: 166 | break; 167 | } 168 | 169 | return super.onInterceptTouchEvent(ev); 170 | } 171 | 172 | private ViewPager getTouchedViewPager(MotionEvent ev) { 173 | if (viewPagers == null || viewPagers.size() == 0) { 174 | return null; 175 | } 176 | Rect mRect = new Rect(); 177 | for (ViewPager viewPager : viewPagers) { 178 | viewPager.getHitRect(mRect); 179 | if (mRect.contains((int) ev.getX(), (int) ev.getY())) { 180 | return viewPager; 181 | } 182 | } 183 | return null; 184 | } 185 | 186 | @Override 187 | public boolean onTouchEvent(MotionEvent event) { 188 | switch (event.getAction()) { 189 | case MotionEvent.ACTION_DOWN: 190 | downX = (int) event.getRawX(); 191 | downY = (int) event.getRawY(); 192 | break; 193 | case MotionEvent.ACTION_MOVE: 194 | int moveX = (int) (event.getRawX() - downX); 195 | int moveY = (int) (event.getRawY() - downY); 196 | if (secondaryView.getX() < 0 && moveX > 0) { 197 | moveX *= rate; 198 | } 199 | if (moveX > 0) { 200 | isScrollerRight = true; 201 | } else { 202 | isScrollerRight = false; 203 | } 204 | int translateX_second = endX + moveX; 205 | int translateX_main = endX + moveX; 206 | if (translateX_second >= secondaryView.getWidth()) { 207 | translateX_second = secondaryView.getWidth(); 208 | translateX_main = mainView.getWidth(); 209 | } 210 | if (translateX_second <= 0) { 211 | translateX_second = 0; 212 | translateX_main = 0; 213 | } 214 | secondaryView.setTranslationX(translateX_second); 215 | mainView.setTranslationX(translateX_main); 216 | break; 217 | case MotionEvent.ACTION_UP: 218 | endX = (int) mainView.getTranslationX(); 219 | startTranslateAnim(); 220 | break; 221 | } 222 | return true; 223 | } 224 | 225 | public void translateToSecondaryView() { 226 | endX = secondaryView.getWidth(); 227 | isScrollerRight = true; 228 | startTranslateAnim(); 229 | } 230 | 231 | public void translateToMainView() { 232 | endX = mainView.getWidth() * 1 / 3; 233 | isScrollerRight = false; 234 | startTranslateAnim(); 235 | } 236 | 237 | public boolean isStillMainView() { 238 | return endX == 0 && mainView.getTranslationX() == 0; 239 | } 240 | 241 | private void startTranslateAnim() { 242 | float secondTranslationX = 0; 243 | float mainTranslationX = 0; 244 | if (isScrollerRight) {//右滑 245 | if (endX > secondaryView.getWidth() / 3) { 246 | secondTranslationX = secondaryView.getWidth(); 247 | mainTranslationX = mainView.getWidth(); 248 | isScrollerRight = false; 249 | } else { 250 | secondTranslationX = 0; 251 | mainTranslationX = 0; 252 | isScrollerRight = true; 253 | } 254 | } else { 255 | if (endX < mainView.getWidth() * 2 / 3) { 256 | secondTranslationX = 0; 257 | mainTranslationX = 0; 258 | isScrollerRight = true; 259 | } else { 260 | secondTranslationX = secondaryView.getWidth(); 261 | mainTranslationX = mainView.getWidth(); 262 | isScrollerRight = false; 263 | } 264 | } 265 | AnimatorSet animator = new AnimatorSet(); 266 | ObjectAnimator animator_secondaryView = ObjectAnimator.ofFloat(secondaryView, "translationX", secondTranslationX); 267 | ObjectAnimator animator_mainView = ObjectAnimator.ofFloat(mainView, "translationX", mainTranslationX); 268 | animator.setDuration(200); 269 | animator.setInterpolator(new LinearInterpolator()); 270 | animator.addListener(new Animator.AnimatorListener() { 271 | @Override 272 | public void onAnimationStart(Animator animation) { 273 | 274 | } 275 | 276 | @Override 277 | public void onAnimationEnd(Animator animation) { 278 | endX = (int) mainView.getTranslationX(); 279 | } 280 | 281 | @Override 282 | public void onAnimationCancel(Animator animation) { 283 | 284 | } 285 | 286 | @Override 287 | public void onAnimationRepeat(Animator animation) { 288 | 289 | } 290 | }); 291 | animator.play(animator_secondaryView).with(animator_mainView); 292 | animator.start(); 293 | 294 | } 295 | 296 | public static class LayoutParams extends MarginLayoutParams { 297 | 298 | public LayoutParams(Context c, AttributeSet attrs) { 299 | super(c, attrs); 300 | } 301 | 302 | public LayoutParams(int width, int height) { 303 | super(width, height); 304 | } 305 | 306 | public LayoutParams(ViewGroup.LayoutParams source) { 307 | super(source); 308 | } 309 | } 310 | 311 | @Override 312 | protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 313 | return new SecondaryScreenView.LayoutParams(p); 314 | } 315 | 316 | @Override 317 | protected ViewGroup.LayoutParams generateDefaultLayoutParams() { 318 | return new SecondaryScreenView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 319 | } 320 | 321 | @Override 322 | public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { 323 | return new SecondaryScreenView.LayoutParams(getContext(), attrs); 324 | } 325 | 326 | @Override 327 | protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 328 | return p instanceof SecondaryScreenView.LayoutParams; 329 | } 330 | } 331 | -------------------------------------------------------------------------------- /app/src/main/java/com/zhl/secondaryscreen/view/TagImageView.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen.view; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Path; 8 | import android.graphics.Rect; 9 | import android.util.AttributeSet; 10 | 11 | import com.zhl.secondaryscreen.R; 12 | 13 | 14 | /** 15 | * 描述: 16 | * Created by zhaohl on 2018-5-21. 17 | */ 18 | public class TagImageView extends android.support.v7.widget.AppCompatImageView { 19 | private Paint tagPaint; 20 | private Paint backgroundPaint; 21 | private int tagSize = 40; 22 | private String tag = "NEW"; 23 | private int tagBackgroud = 0XFFFB0C0C; 24 | private int textColor = 0XFFFFFFFF; 25 | private Location location = Location.ON_TOP_RIGHT; 26 | private boolean showTag = true; 27 | 28 | public enum Location{ 29 | ON_TOP_lEFT,ON_TOP_RIGHT 30 | } 31 | 32 | public TagImageView(Context context) { 33 | this(context,null); 34 | } 35 | 36 | public TagImageView(Context context, AttributeSet attrs) { 37 | this(context, attrs,-1); 38 | } 39 | 40 | public TagImageView(Context context, AttributeSet attrs, int defStyleAttr) { 41 | super(context, attrs, defStyleAttr); 42 | TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.TagImageAttr); 43 | if(array!=null&&array.length()>0){ 44 | textColor = array.getColor(R.styleable.TagImageAttr_tagTextColor,0XFFFFFFFF); 45 | tagSize = array.getInt(R.styleable.TagImageAttr_tagSize,40); 46 | tagBackgroud = array.getColor(R.styleable.TagImageAttr_tagBackgroud,0XFFFB0C0C); 47 | showTag = array.getBoolean(R.styleable.TagImageAttr_showTag,true); 48 | int loc = array.getInt(R.styleable.TagImageAttr_tagLocation,1); 49 | switch (loc){ 50 | case 0: 51 | location = Location.ON_TOP_lEFT; 52 | break; 53 | case 1: 54 | location = Location.ON_TOP_RIGHT; 55 | break; 56 | } 57 | array.recycle(); 58 | } 59 | tagPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 60 | backgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 61 | tagPaint.setColor(textColor); 62 | tagPaint.setFakeBoldText(true); 63 | backgroundPaint.setColor(tagBackgroud); 64 | tagPaint.setTextSize(tagSize); 65 | setScaleType(ScaleType.FIT_XY); 66 | } 67 | 68 | @Override 69 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 70 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 71 | } 72 | 73 | @Override 74 | protected void onDraw(Canvas canvas) { 75 | super.onDraw(canvas); 76 | if(showTag){ 77 | double sin45 = Math.sin(Math.toRadians(45)); 78 | // 先测出文字大小 79 | Paint.FontMetrics metrics = new Paint.FontMetrics(); 80 | tagPaint.getFontMetrics(metrics); 81 | 82 | Rect bounds = new Rect(); 83 | tagPaint.getTextBounds(tag,1,tag.length(),bounds); 84 | 85 | float textW = tagPaint.measureText(tag); 86 | float textH = metrics.bottom-metrics.top; 87 | 88 | float bgH = textH*1.2f; 89 | float offsetV = -(bgH-(bounds.bottom-bounds.top))/2; 90 | float unit = (float) (bgH/sin45); 91 | float wrapW = (float) (unit/sin45); 92 | float offsetH = bgH+((wrapW-textW)/2); 93 | 94 | switch (location){ 95 | case ON_TOP_lEFT: 96 | drawOnLeft(canvas,unit,offsetH,offsetV); 97 | break; 98 | case ON_TOP_RIGHT: 99 | drawOnRight(canvas,unit,offsetH,offsetV); 100 | break; 101 | } 102 | } 103 | } 104 | 105 | private void drawOnLeft(Canvas canvas, float unit, float offsetH, float offsetV) { 106 | Path path = new Path(); 107 | path.moveTo(unit,0); 108 | path.lineTo(2*unit,0); 109 | path.lineTo(0,2*unit); 110 | path.lineTo(0,unit); 111 | path.close(); 112 | canvas.drawPath(path,backgroundPaint); 113 | 114 | Path tagPath = new Path(); 115 | tagPath.moveTo(0,2*unit); 116 | tagPath.lineTo(2*unit,0); 117 | 118 | canvas.drawTextOnPath(tag,tagPath, offsetH,offsetV,tagPaint); 119 | } 120 | 121 | private void drawOnRight(Canvas canvas, float unit, float offsetH, float offsetV){ 122 | Path path = new Path(); 123 | path.moveTo(getMeasuredWidth()-2*unit,0); 124 | path.lineTo(getMeasuredWidth()-unit,0); 125 | path.lineTo(getMeasuredWidth(),unit); 126 | path.lineTo(getMeasuredWidth(),2*unit); 127 | path.close(); 128 | canvas.drawPath(path,backgroundPaint); 129 | 130 | Path tagPath = new Path(); 131 | tagPath.moveTo(getMeasuredWidth()-2*unit,0); 132 | tagPath.lineTo(getMeasuredWidth(),2*unit); 133 | 134 | canvas.drawTextOnPath(tag,tagPath, offsetH,offsetV,tagPaint); 135 | } 136 | 137 | public void setTagSize(int size){ 138 | if(size<=0||size>200){ 139 | return ; 140 | } 141 | tagSize = size; 142 | tagPaint.setTextSize(tagSize); 143 | invalidate(); 144 | } 145 | 146 | public void setTagBackgroud(int color){ 147 | tagBackgroud = color; 148 | backgroundPaint.setColor(tagBackgroud); 149 | invalidate(); 150 | } 151 | public void setTagTextColor(int color){ 152 | textColor = color; 153 | tagPaint.setColor(textColor); 154 | invalidate(); 155 | } 156 | 157 | public void setTagLocation(Location location){ 158 | this.location = location; 159 | invalidate(); 160 | } 161 | 162 | public void showTag(boolean show){ 163 | this.showTag = show; 164 | invalidate(); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/drawable_refresh_tv.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | 9 | 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_custom_progress_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 21 | 22 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_custom_refresh_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 16 | 17 | 32 | 33 | 34 | 35 | 36 | 40 | 41 | 44 | 45 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_custom_view_test.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 12 | 13 | 21 | 22 | 26 | 27 | 31 | 32 | 38 | 39 | 43 | 44 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_pull_secondview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/layout/custom_refresh_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 16 | 17 | 27 | 28 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /app/src/main/res/layout/fg_second_floor.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 13 | 14 | 18 | 19 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 46 | 47 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /app/src/main/res/layout/item_cardview.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/arrow_down.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/arrow_down.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/bg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/bg2.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/img_1.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/img_3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/img_3.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/progressbar_bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/progressbar_bg.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/second_floor_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/second_floor_main.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/secondary_screen.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/secondary_screen.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/top_right_search_black.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/top_right_search_black.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/v1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/v1.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/v2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/v2.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/v3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxhdpi/v3.jpg -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | #666666 7 | #33FF66 8 | #FF3333 9 | #55c8c6c6 10 | 11 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | SecondaryScreen 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/zhl/secondaryscreen/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.zhl.secondaryscreen; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | google() 6 | jcenter() 7 | maven { url "https://jitpack.io" } 8 | 9 | } 10 | dependencies { 11 | classpath 'com.android.tools.build:gradle:3.5.3' 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | maven { url "https://jitpack.io" } 23 | } 24 | } 25 | 26 | task clean(type: Delete) { 27 | delete rootProject.buildDir 28 | } 29 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Jun 26 10:34:38 CST 2019 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-5.4.1-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /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 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 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 Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /image/show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/image/show.gif -------------------------------------------------------------------------------- /image/show_video.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/image/show_video.jpg -------------------------------------------------------------------------------- /image/show_video.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/image/show_video.mp4 -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | -------------------------------------------------------------------------------- /show.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/show.gif -------------------------------------------------------------------------------- /show2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/show2.jpg -------------------------------------------------------------------------------- /show3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/show3.gif -------------------------------------------------------------------------------- /video_show_secondfloorview.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yilylong/SecondaryScreen/29aecc544c33043315acb9624a82db8b0a7b8ef5/video_show_secondfloorview.gif --------------------------------------------------------------------------------