├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── misc.xml
├── modules.xml
└── runConfigurations.xml
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── czm
│ │ └── main
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── czm
│ │ │ ├── main
│ │ │ ├── MainActivity.java
│ │ │ └── RecyclerViewListAdapter.java
│ │ │ ├── model
│ │ │ └── TabItem.java
│ │ │ ├── tablayout
│ │ │ ├── OnTabSelectListener.java
│ │ │ └── XCTabLayout.java
│ │ │ ├── uphidescrollview
│ │ │ ├── BaseListFragment.java
│ │ │ ├── ListFragment.java
│ │ │ ├── ObservableScrollView.java
│ │ │ ├── ScrollViewPager.java
│ │ │ ├── ScrollViewPagerAdapter.java
│ │ │ ├── ViewUtil.java
│ │ │ └── XCUpHideScrollView.java
│ │ │ └── utils
│ │ │ └── PhoneUtil.java
│ └── res
│ │ ├── drawable
│ │ ├── bg_msg_red_dot.9.png
│ │ └── icon_back_orange.png
│ │ ├── layout
│ │ ├── activity_main.xml
│ │ ├── fragment_viewpager_list.xml
│ │ ├── layout_list_item.xml
│ │ └── layout_tab.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── czm
│ └── main
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── screenshots
└── 01.gif
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 | .externalNativeBuild
10 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/copyright/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
17 |
18 |
--------------------------------------------------------------------------------
/.idea/misc.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 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # XCUpHideScrollView
2 | A UpHideScrollView which is some listviews inner scrollview
3 | 仿微博发现页面ScrollView 内嵌ListView 到顶吸顶 滚动ListView效果
4 |
5 | ## 效果演示图:
6 |
7 | 
8 |
9 |
10 | 如何使用项目:
11 | 首先打开 Project root 的 build.gradle,在 repositories 节点添加上
12 |
13 | maven { url "https://jitpack.io" }
14 |
15 |
16 | ,之后打开想依赖这个 library 的模块,比如这里我们是 app 这个 module,在 dependencies 节点添加上
17 |
18 |
19 |
20 | compile 'com.github.jczmdeveloper:XCUpHideScrollView:v1.0',
21 |
22 |
23 | Sync 一下 Gradle,这样就可以了
24 |
25 |
26 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 25
5 | buildToolsVersion "25.0.2"
6 | defaultConfig {
7 | applicationId "com.czm.main"
8 | minSdkVersion 14
9 | targetSdkVersion 25
10 | versionCode 1
11 | versionName "1.0"
12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
25 | exclude group: 'com.android.support', module: 'support-annotations'
26 | })
27 | compile 'com.android.support:appcompat-v7:25.2.0'
28 | compile 'com.android.support:recyclerview-v7:25.2.0'
29 | compile 'com.android.support.constraint:constraint-layout:1.0.0-alpha9'
30 | testCompile 'junit:junit:4.12'
31 | }
32 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Java\AndroidStudio\SDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/czm/main/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.czm.main;
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 | * Instrumentation 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() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.czm.main", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/main/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.czm.main;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.FragmentActivity;
5 | import android.support.v4.view.ViewPager;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.View;
8 |
9 | import com.czm.model.TabItem;
10 | import com.czm.tablayout.XCTabLayout;
11 | import com.czm.uphidescrollview.ObservableScrollView;
12 | import com.czm.uphidescrollview.ScrollViewPager;
13 | import com.czm.uphidescrollview.ScrollViewPagerAdapter;
14 | import com.czm.uphidescrollview.XCUpHideScrollView;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | public class MainActivity extends FragmentActivity {
20 |
21 | private View mRootView;
22 | private View mHeaderView;
23 | private ScrollViewPager mScrollViewPager;
24 | private ScrollViewPagerAdapter mScrollViewPagerAdapter;
25 | private XCTabLayout mTabLayout;
26 | private XCUpHideScrollView mScrollView;
27 | private int mCurPos = 0;
28 | private View mScrollBackView;
29 |
30 |
31 | private boolean mIsCeiling = false;//是否吸顶
32 |
33 | private String[] mTabArr = new String[]{
34 | "热点","推荐","财经","娱乐","NBA"
35 | };
36 |
37 | @Override
38 | protected void onCreate(Bundle savedInstanceState) {
39 | super.onCreate(savedInstanceState);
40 | setContentView(R.layout.activity_main);
41 | mRootView = findViewById(R.id.sv_root);
42 | mScrollView = (XCUpHideScrollView) mRootView.findViewById(R.id.sv_root);
43 | mScrollBackView = mRootView.findViewById(R.id.btn_back);
44 | mHeaderView = mRootView.findViewById(R.id.lay_header);
45 | mScrollView.setHeaderView(mHeaderView);
46 | mScrollView.setContentView(mRootView.findViewById(R.id.lay_content));
47 |
48 | mTabLayout = (XCTabLayout) mRootView.findViewById(R.id.tab_layout_vp);
49 |
50 | mScrollViewPager = (ScrollViewPager) mRootView.findViewById(R.id.vp_list);
51 |
52 |
53 | setListener();
54 | this.runOnUiThread(new Runnable() {
55 | @Override
56 | public void run() {
57 | List list = new ArrayList();
58 | for(int i = 0; i < mTabArr.length;i ++){
59 | TabItem item = new TabItem();
60 | item.setItemName(mTabArr[i]);
61 | list.add(item);
62 | }
63 | setTabView(list);
64 | }
65 | });
66 | }
67 | private void setListener() {
68 | mScrollView.setOnScrollListener(new ObservableScrollView.OnScrollChangedListener() {
69 | @Override
70 | public void onScrollChanged(int x, int y, int oldX, int oldY) {
71 | if(mHeaderView.getMeasuredHeight() >0
72 | && y >= mHeaderView.getMeasuredHeight()){
73 | if(!mIsCeiling){
74 | mScrollBackView.setVisibility(View.VISIBLE);
75 | mIsCeiling = true;
76 | }
77 |
78 | }else{
79 | if(mIsCeiling){
80 | mScrollBackView.setVisibility(View.GONE);
81 | mIsCeiling = false;
82 | }
83 | }
84 | }
85 | });
86 | mScrollBackView.setOnClickListener(new View.OnClickListener() {
87 | @Override
88 | public void onClick(View v) {
89 | mScrollBackView.setVisibility(View.GONE);
90 | mIsCeiling = false;
91 | mScrollView.smoothScrollToSlow(0,0,800);
92 | ((RecyclerView) mScrollViewPagerAdapter.getSlidableView(mCurPos)).scrollToPosition(0);
93 | }
94 | });
95 |
96 | mScrollViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
97 | @Override
98 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
99 |
100 | }
101 |
102 | @Override
103 | public void onPageSelected(int position) {
104 | mCurPos = position;
105 | mScrollView.setContentInnerScrollableView(mScrollViewPagerAdapter.getSlidableView(position));
106 | }
107 |
108 | @Override
109 | public void onPageScrollStateChanged(int state) {
110 |
111 | }
112 | });
113 | }
114 | public void setTabView(List data) {
115 | if(mScrollViewPagerAdapter == null){
116 | mScrollViewPagerAdapter = new ScrollViewPagerAdapter(this.getSupportFragmentManager());
117 | mScrollViewPagerAdapter.setTabLayoutData(data);
118 | mScrollViewPager.setAdapter(mScrollViewPagerAdapter);
119 | mTabLayout.setViewPager(mScrollViewPager);
120 | mScrollViewPagerAdapter.notifyDataSetChanged();
121 | }
122 |
123 | mScrollViewPager.postDelayed(new Runnable() {
124 | @Override
125 | public void run() {
126 | mScrollView.setContentInnerScrollableView(mScrollViewPagerAdapter.getSlidableView(0));
127 | mScrollViewPager.setHeight(mScrollView.getMeasuredHeight()-mTabLayout.getMeasuredHeight());
128 | }
129 | },100);
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/main/RecyclerViewListAdapter.java:
--------------------------------------------------------------------------------
1 | package com.czm.main;
2 |
3 | import android.content.Context;
4 | import android.support.v7.widget.RecyclerView;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.TextView;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | /**
14 | * Created by caizhiming on 2016/8/13.
15 | */
16 |
17 | public class RecyclerViewListAdapter extends RecyclerView.Adapter{
18 |
19 | private Context mContext;
20 | private List mData = new ArrayList<>();
21 | public RecyclerViewListAdapter(Context context){
22 | mContext =context;
23 | }
24 | public void setData(List data){
25 | mData.clear();
26 | mData.addAll(data);
27 | notifyDataSetChanged();
28 | }
29 |
30 | @Override
31 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
32 | LayoutInflater inflater = LayoutInflater.from(mContext);
33 | View view = inflater.inflate(R.layout.layout_list_item,parent,false);
34 | return new ItemViewHolder(view);
35 | }
36 |
37 | @Override
38 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
39 | if(holder instanceof ItemViewHolder){
40 | ((ItemViewHolder)holder).bindData(mData.get(position),position);
41 | }
42 | }
43 |
44 | @Override
45 | public int getItemCount() {
46 | return mData.size();
47 | }
48 |
49 | public class ItemViewHolder extends RecyclerView.ViewHolder{
50 |
51 | TextView item_text;
52 |
53 | public ItemViewHolder(View root){
54 | super(root);
55 | item_text = (TextView) root.findViewById(R.id.item_text);
56 | }
57 |
58 | public void bindData(final String data, final int pos) {
59 | item_text.setText(data);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/model/TabItem.java:
--------------------------------------------------------------------------------
1 | package com.czm.model;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * Created by caizhiming on 2017/4/13.
7 | */
8 |
9 | public class TabItem implements Serializable{
10 | private String itemName;
11 |
12 | public String getItemName() {
13 | return itemName;
14 | }
15 |
16 | public void setItemName(String itemName) {
17 | this.itemName = itemName;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/tablayout/OnTabSelectListener.java:
--------------------------------------------------------------------------------
1 | package com.czm.tablayout;
2 |
3 | public interface OnTabSelectListener {
4 | void onTabSelect(int position);
5 | void onTabReselect(int position);
6 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/tablayout/XCTabLayout.java:
--------------------------------------------------------------------------------
1 | package com.czm.tablayout;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Color;
7 | import android.graphics.Paint;
8 | import android.graphics.Path;
9 | import android.graphics.Rect;
10 | import android.graphics.drawable.GradientDrawable;
11 | import android.os.Bundle;
12 | import android.os.Parcelable;
13 | import android.support.v4.view.ViewPager;
14 | import android.util.AttributeSet;
15 | import android.util.TypedValue;
16 | import android.view.Gravity;
17 | import android.view.View;
18 | import android.view.ViewGroup;
19 | import android.widget.HorizontalScrollView;
20 | import android.widget.LinearLayout;
21 | import android.widget.TextView;
22 |
23 | import com.czm.main.R;
24 | import com.czm.utils.PhoneUtil;
25 |
26 | import java.util.ArrayList;
27 | import java.util.List;
28 |
29 | /**
30 | * Created by caizhiming on 2016/3/8.
31 | */
32 | public class XCTabLayout extends HorizontalScrollView implements ViewPager.OnPageChangeListener {
33 | private Context mContext;
34 | private ViewPager mViewPager;
35 | private String[] mTitles;
36 | private LinearLayout mTabsContainer;
37 | private int mCurrentTab;
38 | private float mCurrentPositionOffset;
39 | private int mTabCount;
40 | /** 用于绘制显示器 */
41 | private Rect mIndicatorRect = new Rect();
42 | /** 用于实现滚动居中 */
43 | private Rect mTabRect = new Rect();
44 | private GradientDrawable mIndicatorDrawable = new GradientDrawable();
45 |
46 | private Paint mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
47 | private Paint mDividerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
48 | private Paint mTrianglePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
49 | private Path mTrianglePath = new Path();
50 | private static final int STYLE_NORMAL = 0;
51 | private static final int STYLE_TRIANGLE = 1;
52 | private static final int STYLE_BLOCK = 2;
53 | private int mIndicatorStyle = STYLE_NORMAL;
54 |
55 | private float mTabPadding;
56 | private boolean mTabSpaceEqual;
57 | private float mTabWidth;
58 |
59 | /** indicator */
60 | private int mIndicatorColor;
61 | private float mIndicatorHeight;
62 | private float mIndicatorWidth;
63 | private float mIndicatorCornerRadius;
64 | private float mIndicatorMarginLeft;
65 | private float mIndicatorMarginTop;
66 | private float mIndicatorMarginRight;
67 | private float mIndicatorMarginBottom;
68 | private int mIndicatorGravity;
69 | private boolean mIndicatorWidthEqualTitle;
70 |
71 | /** underline */
72 | private int mUnderlineColor;
73 | private float mUnderlineHeight;
74 | private int mUnderlineGravity;
75 |
76 | /** divider */
77 | private int mDividerColor;
78 | private float mDividerWidth;
79 | private float mDividerPadding;
80 |
81 | /** title */
82 | private float mTextsize;
83 | private int mTextSelectColor;
84 | private int mTextUnselectColor;
85 | private boolean mTextBold;
86 | private boolean mTextAllCaps;
87 |
88 | private int mLastScrollX;
89 | private int mHeight;
90 | private boolean mShowRedDot = false;
91 | private List mDotList = new ArrayList<>();
92 | private List mDotDataList = new ArrayList<>();
93 | public void hideAllDot(){
94 | for (int i = 0; i < mDotList.size(); i++) {
95 | mDotList.get(i).setVisibility(GONE);
96 | }
97 | }
98 | public void subDotData(int pos){
99 | int old = mDotDataList.get(pos);
100 | int newNum = old -1 ;
101 | if(newNum <=0) newNum = 0;
102 | mDotDataList.set(pos,newNum);
103 | if(newNum > 0){
104 | mDotList.get(pos).setVisibility(VISIBLE);
105 | mDotList.get(pos).setText(String.valueOf(newNum));
106 | if(newNum > 99){
107 | mDotList.get(pos).setText("99+");
108 | int padding = PhoneUtil.dip2px(mContext,4);
109 | mDotList.get(pos).setPadding(padding,0,padding,0);
110 | mDotList.get(pos).requestLayout();
111 | }else{
112 | mDotList.get(pos).setText(String.valueOf(newNum));
113 | int padding = PhoneUtil.dip2px(mContext,0);
114 | mDotList.get(pos).setPadding(padding,0,padding,0);
115 | mDotList.get(pos).requestLayout();
116 |
117 | }
118 | }else{
119 | mDotList.get(pos).setVisibility(GONE);
120 | }
121 | }
122 | public void setDotDatas(List data){
123 | if(data.size() != (mDotList.size()+1))
124 | return;
125 | for (int i = 0; i < mDotList.size(); i++) {
126 | final TextView dot = mDotList.get(i);
127 | int num = data.get(i+1);
128 | mDotDataList.add(num);
129 | if(num > 0){
130 | dot.setVisibility(VISIBLE);
131 | if(num > 99){
132 | dot.setText("99+");
133 | int padding = PhoneUtil.dip2px(mContext,4);
134 | dot.setPadding(padding,0,padding,0);
135 | dot.requestLayout();
136 |
137 | }else{
138 | dot.setText(String.valueOf(num));
139 | int padding = PhoneUtil.dip2px(mContext,0);
140 | dot.setPadding(padding,0,padding,0);
141 | dot.requestLayout();
142 | }
143 | }else{
144 | dot.setVisibility(GONE);
145 | }
146 |
147 | }
148 | }
149 | public void showRedDot(boolean showRedDot){
150 | mShowRedDot = showRedDot;
151 | }
152 |
153 | public XCTabLayout(Context context) {
154 | this(context, null, 0);
155 | }
156 |
157 | public XCTabLayout(Context context, AttributeSet attrs) {
158 | this(context, attrs, 0);
159 | }
160 |
161 | public XCTabLayout(Context context, AttributeSet attrs, int defStyleAttr) {
162 | super(context, attrs, defStyleAttr);
163 | setFillViewport(true);//设置滚动视图是否可以伸缩其内容以填充视口
164 | setWillNotDraw(false);//重写onDraw方法,需要调用这个方法来清除flag
165 | setClipChildren(false);
166 | setClipToPadding(false);
167 |
168 | this.mContext = context;
169 | mTabsContainer = new LinearLayout(context);
170 |
171 |
172 | addView(mTabsContainer);
173 |
174 | obtainAttributes(context, attrs);
175 |
176 | //get layout_height
177 | String height = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "layout_height");
178 |
179 | //create ViewPager
180 | if (height.equals(ViewGroup.LayoutParams.MATCH_PARENT + "")) {
181 | } else if (height.equals(ViewGroup.LayoutParams.WRAP_CONTENT + "")) {
182 | } else {
183 | int[] systemAttrs = {android.R.attr.layout_height};
184 | TypedArray a = context.obtainStyledAttributes(attrs, systemAttrs);
185 | mHeight = a.getDimensionPixelSize(0, ViewGroup.LayoutParams.WRAP_CONTENT);
186 | a.recycle();
187 | }
188 | }
189 |
190 | private void obtainAttributes(Context context, AttributeSet attrs) {
191 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.SlidingTabLayout);
192 |
193 | mIndicatorStyle = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_style, STYLE_NORMAL);
194 | mIndicatorColor = ta.getColor(R.styleable.SlidingTabLayout_tl_indicator_color, Color.parseColor(mIndicatorStyle == STYLE_BLOCK ? "#4B6A87" : "#ffffff"));
195 | mIndicatorHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_height,
196 | dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 4 : (mIndicatorStyle == STYLE_BLOCK ? -1 : 2)));
197 | mIndicatorWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_width, dp2px(mIndicatorStyle == STYLE_TRIANGLE ? 10 : -1));
198 | mIndicatorCornerRadius = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_corner_radius, dp2px(mIndicatorStyle == STYLE_BLOCK ? -1 : 0));
199 | mIndicatorMarginLeft = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_left, dp2px(0));
200 | mIndicatorMarginTop = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_top, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
201 | mIndicatorMarginRight = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_right, dp2px(0));
202 | mIndicatorMarginBottom = ta.getDimension(R.styleable.SlidingTabLayout_tl_indicator_margin_bottom, dp2px(mIndicatorStyle == STYLE_BLOCK ? 7 : 0));
203 | mIndicatorGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_indicator_gravity, Gravity.BOTTOM);
204 | mIndicatorWidthEqualTitle = ta.getBoolean(R.styleable.SlidingTabLayout_tl_indicator_width_equal_title, false);
205 |
206 | mUnderlineColor = ta.getColor(R.styleable.SlidingTabLayout_tl_underline_color, Color.parseColor("#ffffff"));
207 | mUnderlineHeight = ta.getDimension(R.styleable.SlidingTabLayout_tl_underline_height, dp2px(0));
208 | mUnderlineGravity = ta.getInt(R.styleable.SlidingTabLayout_tl_underline_gravity, Gravity.BOTTOM);
209 |
210 | mDividerColor = ta.getColor(R.styleable.SlidingTabLayout_tl_divider_color, Color.parseColor("#ffffff"));
211 | mDividerWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_width, dp2px(0));
212 | mDividerPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_divider_padding, dp2px(12));
213 |
214 | mTextsize = ta.getDimension(R.styleable.SlidingTabLayout_tl_textsize, sp2px(14));
215 | mTextSelectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textSelectColor, Color.parseColor("#ffffff"));
216 | mTextUnselectColor = ta.getColor(R.styleable.SlidingTabLayout_tl_textUnselectColor, Color.parseColor("#AAffffff"));
217 | mTextBold = ta.getBoolean(R.styleable.SlidingTabLayout_tl_textBold, false);
218 | mTextAllCaps = ta.getBoolean(R.styleable.SlidingTabLayout_tl_textAllCaps, false);
219 |
220 | mTabSpaceEqual = ta.getBoolean(R.styleable.SlidingTabLayout_tl_tab_space_equal, false);
221 | mTabWidth = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_width, dp2px(-1));
222 | mTabPadding = ta.getDimension(R.styleable.SlidingTabLayout_tl_tab_padding, mTabSpaceEqual || mTabWidth > 0 ? dp2px(0) : dp2px(20));
223 |
224 | ta.recycle();
225 | }
226 |
227 | /** 关联ViewPager */
228 | public void setViewPager(ViewPager vp) {
229 | if (vp == null || vp.getAdapter() == null) {
230 | throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
231 | }
232 |
233 | this.mViewPager = vp;
234 |
235 | this.mViewPager.removeOnPageChangeListener(this);
236 | this.mViewPager.addOnPageChangeListener(this);
237 | notifyDataSetChanged();
238 | }
239 |
240 | /** 关联ViewPager,用于不想在ViewPager适配器中设置titles数据的情况 */
241 | public void setViewPager(ViewPager vp, String[] titles) {
242 | if (vp == null || vp.getAdapter() == null) {
243 | throw new IllegalStateException("ViewPager or ViewPager adapter can not be NULL !");
244 | }
245 |
246 | if (titles == null || titles.length == 0) {
247 | throw new IllegalStateException("Titles can not be EMPTY !");
248 | }
249 |
250 | if (titles.length != vp.getAdapter().getCount()) {
251 | throw new IllegalStateException("Titles length must be the same as the page count !");
252 | }
253 |
254 | this.mViewPager = vp;
255 | this.mTitles = titles;
256 |
257 | this.mViewPager.removeOnPageChangeListener(this);
258 | this.mViewPager.addOnPageChangeListener(this);
259 | notifyDataSetChanged();
260 | }
261 |
262 | // /** 关联ViewPager,用于连适配器都不想自己实例化的情况 */
263 | // public void setViewPager(ViewPager vp, String[] titles, FragmentActivity fa, ArrayList fragments) {
264 | // if (vp == null) {
265 | // throw new IllegalStateException("ViewPager can not be NULL !");
266 | // }
267 | //
268 | // if (titles == null || titles.length == 0) {
269 | // throw new IllegalStateException("Titles can not be EMPTY !");
270 | // }
271 | //
272 | // this.mViewPager = vp;
273 | // this.mViewPager.setAdapter(new InnerPagerAdapter(fa.getSupportFragmentManager(), fragments, titles));
274 | //
275 | // this.mViewPager.removeOnPageChangeListener(this);
276 | // this.mViewPager.addOnPageChangeListener(this);
277 | // notifyDataSetChanged();
278 | // }
279 |
280 | /** 更新数据 */
281 | public void notifyDataSetChanged() {
282 | mTabsContainer.removeAllViews();
283 | this.mTabCount = mTitles == null ? mViewPager.getAdapter().getCount() : mTitles.length;
284 | View tabView = null;
285 | for (int i = 0; i < mTabCount; i++) {
286 | if (mViewPager.getAdapter() instanceof CustomTabProvider) {
287 | tabView = ((CustomTabProvider) mViewPager.getAdapter()).getCustomTabView(this, i);
288 | } else {
289 | tabView = View.inflate(mContext, R.layout.layout_tab, null);
290 | }
291 | TextView dot = (TextView) tabView.findViewById(R.id.tv_reddot);
292 | mDotList.add(dot);
293 | // if(mShowRedDot){
294 | // dot.setVisibility(VISIBLE);
295 | // }else{
296 | // dot.setVisibility(GONE);
297 | // }
298 | CharSequence pageTitle = mTitles == null ? mViewPager.getAdapter().getPageTitle(i) : mTitles[i];
299 | addTab(i, pageTitle.toString(), tabView);
300 | }
301 |
302 | updateTabStyles();
303 | }
304 |
305 | /** 创建并添加tab */
306 | private void addTab(final int position, String title, View tabView) {
307 | TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
308 | if (tv_tab_title != null) {
309 | if (title != null) tv_tab_title.setText(title);
310 | }
311 |
312 | tabView.setOnClickListener(new OnClickListener() {
313 | @Override
314 | public void onClick(View v) {
315 | if (mViewPager.getCurrentItem() != position) {
316 | mViewPager.setCurrentItem(position);
317 | if (mListener != null) {
318 | mListener.onTabSelect(position);
319 | }
320 | } else {
321 | if (mListener != null) {
322 | mListener.onTabReselect(position);
323 | }
324 | }
325 | }
326 | });
327 |
328 | /** 每一个Tab的布局参数 */
329 | LinearLayout.LayoutParams lp_tab = mTabSpaceEqual ?
330 | new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1.0f) :
331 | new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
332 | if (mTabWidth > 0) {
333 | lp_tab = new LinearLayout.LayoutParams((int) mTabWidth, LayoutParams.MATCH_PARENT);
334 | }
335 | mTabsContainer.addView(tabView, position, lp_tab);
336 | }
337 |
338 | private void updateTabStyles() {
339 | for (int i = 0; i < mTabCount; i++) {
340 | View v = mTabsContainer.getChildAt(i);
341 | // v.setPadding((int) mTabPadding, v.getPaddingTop(), (int) mTabPadding, v.getPaddingBottom());
342 | TextView tv_tab_title = (TextView) v.findViewById(R.id.tv_tab_title);
343 | if (tv_tab_title != null) {
344 | tv_tab_title.setTextColor(i == mCurrentTab ? mTextSelectColor : mTextUnselectColor);
345 | tv_tab_title.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextsize);
346 | tv_tab_title.setPadding((int) mTabPadding, 0, (int) mTabPadding, 0);
347 | if (mTextAllCaps) {
348 | tv_tab_title.setText(tv_tab_title.getText().toString().toUpperCase());
349 | }
350 |
351 | if (mTextBold) {
352 | tv_tab_title.getPaint().setFakeBoldText(mTextBold);
353 | }
354 | }
355 | }
356 | }
357 |
358 | @Override
359 | public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
360 | /**
361 | * position:当前View的位置
362 | * mCurrentPositionOffset:当前View的偏移量比例.[0,1)
363 | */
364 | this.mCurrentTab = position;
365 | this.mCurrentPositionOffset = positionOffset;
366 | scrollToCurrentTab();
367 | invalidate();
368 | }
369 |
370 | @Override
371 | public void onPageSelected(int position) {
372 | updateTabSelection(position);
373 | }
374 |
375 | @Override
376 | public void onPageScrollStateChanged(int state) {
377 | }
378 |
379 | /** HorizontalScrollView滚到当前tab,并且居中显示 */
380 | private void scrollToCurrentTab() {
381 | if (mTabCount <= 0) {
382 | return;
383 | }
384 |
385 | int offset = (int) (mCurrentPositionOffset * mTabsContainer.getChildAt(mCurrentTab).getWidth());
386 | /**当前Tab的left+当前Tab的Width乘以positionOffset*/
387 | int newScrollX = mTabsContainer.getChildAt(mCurrentTab).getLeft() + offset;
388 |
389 | if (mCurrentTab > 0 || offset > 0) {
390 | /**HorizontalScrollView移动到当前tab,并居中*/
391 | newScrollX -= getWidth() / 2 - getPaddingLeft();
392 | calcIndicatorRect();
393 | newScrollX += ((mTabRect.right - mTabRect.left) / 2);
394 | }
395 |
396 | if (newScrollX != mLastScrollX) {
397 | mLastScrollX = newScrollX;
398 | /** scrollTo(int x,int y):x,y代表的不是坐标点,而是偏移量
399 | * x:表示离起始位置的x水平方向的偏移量
400 | * y:表示离起始位置的y垂直方向的偏移量
401 | */
402 | scrollTo(newScrollX, 0);
403 | }
404 | }
405 |
406 | private void updateTabSelection(int position) {
407 | for (int i = 0; i < mTabCount; ++i) {
408 | View tabView = mTabsContainer.getChildAt(i);
409 | final boolean isSelect = i == position;
410 | TextView tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
411 |
412 | if (tab_title != null) {
413 | tab_title.setTextColor(isSelect ? mTextSelectColor : mTextUnselectColor);
414 | }
415 |
416 | if (mViewPager.getAdapter() instanceof CustomTabProvider) {
417 | if (isSelect) {
418 | ((CustomTabProvider) mViewPager.getAdapter()).tabSelect(tabView);
419 | } else {
420 | ((CustomTabProvider) mViewPager.getAdapter()).tabUnselect(tabView);
421 | }
422 | }
423 | }
424 | }
425 |
426 | private float margin;
427 |
428 | private void calcIndicatorRect() {
429 | View currentTabView = mTabsContainer.getChildAt(this.mCurrentTab);
430 | float left = currentTabView.getLeft();
431 | float right = currentTabView.getRight();
432 |
433 | //for mIndicatorWidthEqualTitle
434 | if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
435 | TextView tab_title = (TextView) currentTabView.findViewById(R.id.tv_tab_title);
436 | mTextPaint.setTextSize(mTextsize);
437 | float textWidth = mTextPaint.measureText(tab_title.getText().toString());
438 | margin = (right - left - textWidth) / 2;
439 | }
440 |
441 | if (this.mCurrentTab < mTabCount - 1) {
442 | View nextTabView = mTabsContainer.getChildAt(this.mCurrentTab + 1);
443 | float nextTabLeft = nextTabView.getLeft();
444 | float nextTabRight = nextTabView.getRight();
445 |
446 | left = left + mCurrentPositionOffset * (nextTabLeft - left);
447 | right = right + mCurrentPositionOffset * (nextTabRight - right);
448 |
449 | //for mIndicatorWidthEqualTitle
450 | if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
451 | TextView next_tab_title = (TextView) nextTabView.findViewById(R.id.tv_tab_title);
452 | mTextPaint.setTextSize(mTextsize);
453 | float nextTextWidth = mTextPaint.measureText(next_tab_title.getText().toString());
454 | float nextMargin = (nextTabRight - nextTabLeft - nextTextWidth) / 2;
455 | margin = margin + mCurrentPositionOffset * (nextMargin - margin);
456 | }
457 | }
458 |
459 | mIndicatorRect.left = (int) left;
460 | mIndicatorRect.right = (int) right;
461 | //for mIndicatorWidthEqualTitle
462 | if (mIndicatorStyle == STYLE_NORMAL && mIndicatorWidthEqualTitle) {
463 | mIndicatorRect.left = (int) (left + margin - 1);
464 | mIndicatorRect.right = (int) (right - margin - 1);
465 | }
466 |
467 | mTabRect.left = (int) left;
468 | mTabRect.right = (int) right;
469 |
470 | if (mIndicatorWidth < 0) { //indicatorWidth小于0时,原jpardogo's PagerSlidingTabStrip
471 |
472 | } else {//indicatorWidth大于0时,圆角矩形以及三角形
473 | float indicatorLeft = currentTabView.getLeft() + (currentTabView.getWidth() - mIndicatorWidth) / 2;
474 |
475 | if (this.mCurrentTab < mTabCount - 1) {
476 | View nextTab = mTabsContainer.getChildAt(this.mCurrentTab + 1);
477 | indicatorLeft = indicatorLeft + mCurrentPositionOffset * (currentTabView.getWidth() / 2 + nextTab.getWidth() / 2);
478 | }
479 |
480 | mIndicatorRect.left = (int) indicatorLeft;
481 | mIndicatorRect.right = (int) (mIndicatorRect.left + mIndicatorWidth);
482 | }
483 | }
484 |
485 | @Override
486 | protected void onDraw(Canvas canvas) {
487 | super.onDraw(canvas);
488 |
489 | if (isInEditMode() || mTabCount <= 0) {
490 | return;
491 | }
492 |
493 | int height = getHeight();
494 | int paddingLeft = getPaddingLeft();
495 | // draw divider
496 | if (mDividerWidth > 0) {
497 | mDividerPaint.setStrokeWidth(mDividerWidth);
498 | mDividerPaint.setColor(mDividerColor);
499 | for (int i = 0; i < mTabCount - 1; i++) {
500 | View tab = mTabsContainer.getChildAt(i);
501 | canvas.drawLine(paddingLeft + tab.getRight(), mDividerPadding, paddingLeft + tab.getRight(), height - mDividerPadding, mDividerPaint);
502 | }
503 | }
504 |
505 | // draw underline
506 | if (mUnderlineHeight > 0) {
507 | mRectPaint.setColor(mUnderlineColor);
508 | if (mUnderlineGravity == Gravity.BOTTOM) {
509 | canvas.drawRect(paddingLeft, height - mUnderlineHeight, mTabsContainer.getWidth() + paddingLeft, height, mRectPaint);
510 | } else {
511 | canvas.drawRect(paddingLeft, 0, mTabsContainer.getWidth() + paddingLeft, mUnderlineHeight, mRectPaint);
512 | }
513 | }
514 |
515 | //draw indicator line
516 |
517 | calcIndicatorRect();
518 | if (mIndicatorStyle == STYLE_TRIANGLE) {
519 | if (mIndicatorHeight > 0) {
520 | mTrianglePaint.setColor(mIndicatorColor);
521 | mTrianglePath.reset();
522 | mTrianglePath.moveTo(paddingLeft + mIndicatorRect.left, height);
523 | mTrianglePath.lineTo(paddingLeft + mIndicatorRect.left / 2 + mIndicatorRect.right / 2, height - mIndicatorHeight);
524 | mTrianglePath.lineTo(paddingLeft + mIndicatorRect.right, height);
525 | mTrianglePath.close();
526 | canvas.drawPath(mTrianglePath, mTrianglePaint);
527 | }
528 | } else if (mIndicatorStyle == STYLE_BLOCK) {
529 | if (mIndicatorHeight < 0) {
530 | mIndicatorHeight = height - mIndicatorMarginTop - mIndicatorMarginBottom;
531 | } else {
532 |
533 | }
534 |
535 | if (mIndicatorHeight > 0) {
536 | if (mIndicatorCornerRadius < 0 || mIndicatorCornerRadius > mIndicatorHeight / 2) {
537 | mIndicatorCornerRadius = mIndicatorHeight / 2;
538 | }
539 |
540 | mIndicatorDrawable.setColor(mIndicatorColor);
541 | mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
542 | (int) mIndicatorMarginTop, (int) (paddingLeft + mIndicatorRect.right - mIndicatorMarginRight),
543 | (int) (mIndicatorMarginTop + mIndicatorHeight));
544 | mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
545 | mIndicatorDrawable.draw(canvas);
546 | }
547 | } else {
548 | /* mRectPaint.setColor(mIndicatorColor);
549 | calcIndicatorRect();
550 | canvas.drawRect(getPaddingLeft() + mIndicatorRect.left, getHeight() - mIndicatorHeight,
551 | mIndicatorRect.right + getPaddingLeft(), getHeight(), mRectPaint);*/
552 |
553 | if (mIndicatorHeight > 0) {
554 | mIndicatorDrawable.setColor(mIndicatorColor);
555 |
556 | if (mIndicatorGravity == Gravity.BOTTOM) {
557 | mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
558 | height - (int) mIndicatorHeight - (int) mIndicatorMarginBottom,
559 | paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
560 | height - (int) mIndicatorMarginBottom);
561 | } else {
562 | mIndicatorDrawable.setBounds(paddingLeft + (int) mIndicatorMarginLeft + mIndicatorRect.left,
563 | (int) mIndicatorMarginTop,
564 | paddingLeft + mIndicatorRect.right - (int) mIndicatorMarginRight,
565 | (int) mIndicatorHeight + (int) mIndicatorMarginTop);
566 | }
567 | mIndicatorDrawable.setCornerRadius(mIndicatorCornerRadius);
568 | mIndicatorDrawable.draw(canvas);
569 | }
570 | }
571 | }
572 |
573 | //setter and getter
574 | public void setCurrentTab(int currentTab) {
575 | this.mCurrentTab = currentTab;
576 | mViewPager.setCurrentItem(currentTab);
577 | }
578 |
579 | public void setIndicatorStyle(int indicatorStyle) {
580 | this.mIndicatorStyle = indicatorStyle;
581 | invalidate();
582 | }
583 |
584 | public void setTabPadding(float tabPadding) {
585 | this.mTabPadding = dp2px(tabPadding);
586 | updateTabStyles();
587 | }
588 |
589 | public void setTabSpaceEqual(boolean tabSpaceEqual) {
590 | this.mTabSpaceEqual = tabSpaceEqual;
591 | updateTabStyles();
592 | }
593 |
594 | public void setTabWidth(float tabWidth) {
595 | this.mTabWidth = dp2px(tabWidth);
596 | updateTabStyles();
597 | }
598 |
599 | public void setIndicatorColor(int indicatorColor) {
600 | this.mIndicatorColor = indicatorColor;
601 | invalidate();
602 | }
603 |
604 | public void setIndicatorHeight(float indicatorHeight) {
605 | this.mIndicatorHeight = dp2px(indicatorHeight);
606 | invalidate();
607 | }
608 |
609 | public void setIndicatorWidth(float indicatorWidth) {
610 | this.mIndicatorWidth = dp2px(indicatorWidth);
611 | invalidate();
612 | }
613 |
614 | public void setIndicatorCornerRadius(float indicatorCornerRadius) {
615 | this.mIndicatorCornerRadius = dp2px(indicatorCornerRadius);
616 | invalidate();
617 | }
618 |
619 | public void setIndicatorGravity(int indicatorGravity) {
620 | this.mIndicatorGravity = indicatorGravity;
621 | invalidate();
622 | }
623 |
624 | public void setIndicatorMargin(float indicatorMarginLeft, float indicatorMarginTop,
625 | float indicatorMarginRight, float indicatorMarginBottom) {
626 | this.mIndicatorMarginLeft = dp2px(indicatorMarginLeft);
627 | this.mIndicatorMarginTop = dp2px(indicatorMarginTop);
628 | this.mIndicatorMarginRight = dp2px(indicatorMarginRight);
629 | this.mIndicatorMarginBottom = dp2px(indicatorMarginBottom);
630 | invalidate();
631 | }
632 |
633 | public void setIndicatorWidthEqualTitle(boolean indicatorWidthEqualTitle) {
634 | this.mIndicatorWidthEqualTitle = indicatorWidthEqualTitle;
635 | invalidate();
636 | }
637 |
638 | public void setUnderlineColor(int underlineColor) {
639 | this.mUnderlineColor = underlineColor;
640 | invalidate();
641 | }
642 |
643 | public void setUnderlineHeight(float underlineHeight) {
644 | this.mUnderlineHeight = dp2px(underlineHeight);
645 | invalidate();
646 | }
647 |
648 | public void setUnderlineGravity(int underlineGravity) {
649 | this.mUnderlineGravity = underlineGravity;
650 | invalidate();
651 | }
652 |
653 | public void setDividerColor(int dividerColor) {
654 | this.mDividerColor = dividerColor;
655 | invalidate();
656 | }
657 |
658 | public void setDividerWidth(float dividerWidth) {
659 | this.mDividerWidth = dp2px(dividerWidth);
660 | invalidate();
661 | }
662 |
663 | public void setDividerPadding(float dividerPadding) {
664 | this.mDividerPadding = dp2px(dividerPadding);
665 | invalidate();
666 | }
667 |
668 | public void setTextsize(float textsize) {
669 | this.mTextsize = sp2px(textsize);
670 | updateTabStyles();
671 | }
672 |
673 | public void setTextSelectColor(int textSelectColor) {
674 | this.mTextSelectColor = textSelectColor;
675 | updateTabStyles();
676 | }
677 |
678 | public void setTextUnselectColor(int textUnselectColor) {
679 | this.mTextUnselectColor = textUnselectColor;
680 | updateTabStyles();
681 | }
682 |
683 | public void setTextBold(boolean textBold) {
684 | this.mTextBold = textBold;
685 | updateTabStyles();
686 | }
687 |
688 | public void setTextAllCaps(boolean textAllCaps) {
689 | this.mTextAllCaps = textAllCaps;
690 | updateTabStyles();
691 | }
692 |
693 |
694 | public int getTabCount() {
695 | return mTabCount;
696 | }
697 |
698 | public int getCurrentTab() {
699 | return mCurrentTab;
700 | }
701 |
702 | public int getIndicatorStyle() {
703 | return mIndicatorStyle;
704 | }
705 |
706 | public float getTabPadding() {
707 | return mTabPadding;
708 | }
709 |
710 | public boolean isTabSpaceEqual() {
711 | return mTabSpaceEqual;
712 | }
713 |
714 | public float getTabWidth() {
715 | return mTabWidth;
716 | }
717 |
718 | public int getIndicatorColor() {
719 | return mIndicatorColor;
720 | }
721 |
722 | public float getIndicatorHeight() {
723 | return mIndicatorHeight;
724 | }
725 |
726 | public float getIndicatorWidth() {
727 | return mIndicatorWidth;
728 | }
729 |
730 | public float getIndicatorCornerRadius() {
731 | return mIndicatorCornerRadius;
732 | }
733 |
734 | public float getIndicatorMarginLeft() {
735 | return mIndicatorMarginLeft;
736 | }
737 |
738 | public float getIndicatorMarginTop() {
739 | return mIndicatorMarginTop;
740 | }
741 |
742 | public float getIndicatorMarginRight() {
743 | return mIndicatorMarginRight;
744 | }
745 |
746 | public float getIndicatorMarginBottom() {
747 | return mIndicatorMarginBottom;
748 | }
749 |
750 | public int getUnderlineColor() {
751 | return mUnderlineColor;
752 | }
753 |
754 | public float getUnderlineHeight() {
755 | return mUnderlineHeight;
756 | }
757 |
758 | public int getDividerColor() {
759 | return mDividerColor;
760 | }
761 |
762 | public float getDividerWidth() {
763 | return mDividerWidth;
764 | }
765 |
766 | public float getDividerPadding() {
767 | return mDividerPadding;
768 | }
769 |
770 | public float getTextsize() {
771 | return mTextsize;
772 | }
773 |
774 | public int getTextSelectColor() {
775 | return mTextSelectColor;
776 | }
777 |
778 | public int getTextUnselectColor() {
779 | return mTextUnselectColor;
780 | }
781 |
782 | public boolean isTextBold() {
783 | return mTextBold;
784 | }
785 |
786 | public boolean isTextAllCaps() {
787 | return mTextAllCaps;
788 | }
789 |
790 | public TextView getTitleView(int tab) {
791 | View tabView = mTabsContainer.getChildAt(tab);
792 | TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title);
793 | return tv_tab_title;
794 | }
795 |
796 | //setter and getter
797 |
798 | // show MsgTipView
799 | private Paint mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
800 |
801 |
802 | private OnTabSelectListener mListener;
803 |
804 | public void setOnTabSelectListener(OnTabSelectListener listener) {
805 | this.mListener = listener;
806 | }
807 |
808 |
809 | public interface CustomTabProvider {
810 | View getCustomTabView(ViewGroup parent, int position);
811 |
812 | void tabSelect(View tab);
813 |
814 | void tabUnselect(View tab);
815 | }
816 |
817 | @Override
818 | protected Parcelable onSaveInstanceState() {
819 | Bundle bundle = new Bundle();
820 | bundle.putParcelable("instanceState", super.onSaveInstanceState());
821 | bundle.putInt("mCurrentTab", mCurrentTab);
822 | return bundle;
823 | }
824 |
825 | @Override
826 | protected void onRestoreInstanceState(Parcelable state) {
827 | if (state instanceof Bundle) {
828 | Bundle bundle = (Bundle) state;
829 | mCurrentTab = bundle.getInt("mCurrentTab");
830 | state = bundle.getParcelable("instanceState");
831 | if (mCurrentTab != 0 && mTabsContainer.getChildCount() > 0) {
832 | updateTabSelection(mCurrentTab);
833 | scrollToCurrentTab();
834 | }
835 | }
836 | super.onRestoreInstanceState(state);
837 | }
838 |
839 | protected int dp2px(float dp) {
840 | final float scale = mContext.getResources().getDisplayMetrics().density;
841 | return (int) (dp * scale + 0.5f);
842 | }
843 |
844 | protected int sp2px(float sp) {
845 | final float scale = this.mContext.getResources().getDisplayMetrics().scaledDensity;
846 | return (int) (sp * scale + 0.5f);
847 | }
848 | }
849 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/BaseListFragment.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.content.Context;
4 | import android.support.v4.app.Fragment;
5 | import android.view.View;
6 |
7 | /**
8 | * Created by caizhiming on 2016/11/14.
9 | */
10 | public abstract class BaseListFragment extends Fragment {
11 |
12 | protected Context mContext;
13 | abstract View getSlidableView();
14 |
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/ListFragment.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v7.widget.LinearLayoutManager;
7 | import android.support.v7.widget.RecyclerView;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.czm.main.R;
13 | import com.czm.main.RecyclerViewListAdapter;
14 | import com.czm.model.TabItem;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by caizhiming on 2016/11/14.
21 | */
22 | public class ListFragment extends BaseListFragment {
23 | protected RecyclerView mRecyclerView;
24 | private TabItem mTabItem;
25 | private View mRootView;
26 | private RecyclerViewListAdapter mListAdapter;
27 |
28 | @Override
29 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
30 | mTabItem = (TabItem) getArguments().getSerializable("tab_item");
31 | mRootView = inflater.inflate(R.layout.fragment_viewpager_list,null);
32 |
33 | return mRootView;
34 | }
35 |
36 | @Override
37 | public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
38 | super.onViewCreated(view, savedInstanceState);
39 | mContext = view.getContext();
40 | mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerview);
41 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
42 | mListAdapter = new RecyclerViewListAdapter(getContext());
43 | mRecyclerView.setAdapter(mListAdapter);
44 |
45 | //fix bug: recyclerView & scrollView
46 | //see http://stackoverflow.com/questions/38074949/recyclerview-inside-scrollview-some-items-are-not-shown
47 | mRecyclerView.setNestedScrollingEnabled(false);
48 |
49 | List data = new ArrayList<>();
50 | int i = 0;
51 | while (i < 30){
52 | data.add(new String(mTabItem.getItemName()+": Item list "+(i+1)));
53 | i++;
54 | }
55 | mListAdapter.setData(data);
56 | }
57 |
58 | private int mLoginMode = -1;
59 | @Override
60 | public void onResume() {
61 | super.onResume();
62 | }
63 |
64 | @Override
65 | View getSlidableView() {
66 | return mRecyclerView;
67 | }
68 |
69 |
70 | @Override
71 | public Context getContext(){
72 | return mContext;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/ObservableScrollView.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.ScrollView;
6 |
7 | /**
8 | * Created by caizhiming on 15/12/21.
9 | */
10 | public class ObservableScrollView extends ScrollView {
11 |
12 | public ObservableScrollView(Context context) {
13 | super(context);
14 | }
15 |
16 | public ObservableScrollView(Context context, AttributeSet attrs) {
17 | super(context, attrs);
18 | }
19 |
20 | public ObservableScrollView(Context context, AttributeSet attrs, int defStyle) {
21 | super(context, attrs, defStyle);
22 | }
23 |
24 | public interface OnScrollChangedListener {
25 | void onScrollChanged(int x, int y, int oldX, int oldY);
26 | }
27 |
28 | private OnScrollChangedListener onScrollChangedListener;
29 |
30 | public void setOnScrollListener(OnScrollChangedListener onScrollChangedListener) {
31 | this.onScrollChangedListener = onScrollChangedListener;
32 | }
33 |
34 | @Override
35 | protected void onScrollChanged(int x, int y, int oldX, int oldY) {
36 | super.onScrollChanged(x, y, oldX, oldY);
37 | if (onScrollChangedListener != null) {
38 | onScrollChangedListener.onScrollChanged(x, y, oldX, oldY);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/ScrollViewPager.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.content.Context;
4 | import android.support.v4.view.ViewPager;
5 | import android.util.AttributeSet;
6 |
7 | /**
8 | * Created by caizhiming on 2017/2/22.
9 | */
10 | public class ScrollViewPager extends ViewPager {
11 | public ScrollViewPager(Context context) {
12 | super(context);
13 | }
14 |
15 | public ScrollViewPager(Context context, AttributeSet attrs) {
16 | super(context, attrs);
17 | }
18 |
19 | private int mHeight;
20 |
21 | public void setHeight(int height) {
22 | mHeight = height;
23 | requestLayout();
24 | }
25 |
26 | @Override
27 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
28 | if (mHeight > 0) {
29 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(mHeight, MeasureSpec.EXACTLY);
30 | }
31 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/ScrollViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.os.Bundle;
4 | import android.support.v4.app.Fragment;
5 | import android.support.v4.app.FragmentManager;
6 | import android.support.v4.app.FragmentPagerAdapter;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import com.czm.model.TabItem;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | * Created by caizhiming on 2016/11/14.
17 | */
18 | public class ScrollViewPagerAdapter extends FragmentPagerAdapter {
19 | private List mFragmentList = new ArrayList<>();
20 | private List mTitleList = new ArrayList<>();
21 | public BaseListFragment getFragment(int pos){
22 | return mFragmentList.get(pos);
23 | }
24 | public void setTabLayoutData(List list){
25 | if(list != null && list.size() > 0){
26 | mTitleList.clear();
27 | mTitleList.addAll(list);
28 |
29 | mFragmentList.clear();
30 | for (int i = 0; i < mTitleList.size(); i++) {
31 | ListFragment item = new ListFragment();
32 | Bundle bundle = new Bundle();
33 | bundle.putSerializable("tab_item",mTitleList.get(i));
34 | item.setArguments(bundle);
35 | mFragmentList.add(item);
36 | }
37 | }
38 | }
39 | public ScrollViewPagerAdapter(FragmentManager fm) {
40 | super(fm);
41 |
42 | }
43 |
44 | public View getSlidableView (int index) {
45 | return mFragmentList.get(index).getSlidableView();
46 | }
47 |
48 | @Override
49 | public Fragment getItem(int position) {
50 | if(mFragmentList!= null && mFragmentList.size() > 0){
51 | return mFragmentList.get(position);
52 | }else{
53 | return null;
54 | }
55 | }
56 |
57 | @Override
58 | public void destroyItem(ViewGroup container, int position, Object object) {
59 | // super.destroyItem(container, position, object);
60 | }
61 |
62 | @Override
63 | public int getCount() {
64 | return mTitleList.size();
65 | }
66 |
67 | @Override
68 | public CharSequence getPageTitle(int position) {
69 | return mTitleList.get(position).getItemName();
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/uphidescrollview/ViewUtil.java:
--------------------------------------------------------------------------------
1 | package com.czm.uphidescrollview;
2 |
3 | import android.support.v7.widget.RecyclerView;
4 | import android.view.View;
5 | import android.view.ViewGroup;
6 | import android.widget.ListView;
7 | import android.widget.ScrollView;
8 |
9 | /**
10 | * Created by caizhiming on 16/11/16.
11 | */
12 |
13 | public class ViewUtil {
14 | public static boolean isScrollToTop(View view) {
15 | if (view instanceof ListView) {
16 | ListView listView = (ListView) view;
17 | int first = listView.getFirstVisiblePosition();
18 | return first == 0;
19 | } else if (view instanceof RecyclerView) {
20 | RecyclerView recyclerView = (RecyclerView) view;
21 | return !recyclerView.canScrollVertically(-1);
22 | } else if (view instanceof ScrollView) {
23 | ScrollView scrollView = (ScrollView) view;
24 | return scrollView.getScrollY() == 0;
25 | }
26 | return true;
27 | }
28 |
29 |
30 | public static void scrollToTop (View view) {
31 | if (view instanceof ScrollView) {
32 | ScrollView scrollView = (ScrollView) view;
33 | scrollView.smoothScrollTo(0,0);
34 | } else if (view instanceof ListView) {
35 | ListView listView = (ListView) view;
36 | listView.setSelection(0);
37 | }
38 | }
39 |
40 | public static T findView(View view, Class tClass) {
41 | if (view.getClass() == tClass) {
42 | return (T) view;
43 | } else if (view instanceof ViewGroup) {
44 | ViewGroup viewGroup = (ViewGroup) view;
45 | for (int i=0;i mFirstY;
106 | boolean isUp = mCurrentY < mFirstY;
107 |
108 | if (isUp) {
109 | if (getScrollY() >= maxMoveY) {
110 | isIntercept = true;
111 | event.transform(eventMatrix);
112 | return scrollableView.dispatchTouchEvent(event);
113 | }
114 | } else if (isDown) {
115 | if (!ViewUtil.isScrollToTop(scrollableView)) {
116 | isIntercept = true;
117 | event.transform(eventMatrix);
118 | return scrollableView.dispatchTouchEvent(event);
119 | }else{
120 | if(getScrollY()>=maxMoveY){
121 | isIntercept = true;
122 | return scrollableView.dispatchTouchEvent(event);
123 | }
124 | }
125 | }
126 | }
127 | break;
128 | case MotionEvent.ACTION_UP:
129 |
130 | break;
131 | }
132 | return super.dispatchTouchEvent(event);
133 | }
134 |
135 |
136 | private ObservableScrollView.OnScrollChangedListener onScrollChangedListener;
137 |
138 | public void setOnScrollListener(ObservableScrollView.OnScrollChangedListener onScrollChangedListener) {
139 | this.onScrollChangedListener = onScrollChangedListener;
140 | }
141 |
142 | @Override
143 | protected void onScrollChanged(int x, int y, int oldX, int oldY) {
144 | super.onScrollChanged(x, y, oldX, oldY);
145 | if (onScrollChangedListener != null) {
146 | onScrollChangedListener.onScrollChanged(x, y, oldX, oldY);
147 | }
148 | }
149 |
150 | private Scroller mScroller;
151 | //调用此方法滚动到目标位置 duration滚动时间
152 | public void smoothScrollToSlow(int fx, int fy, int duration) {
153 | int dx = fx - getScrollX();//mScroller.getFinalX(); 普通view使用这种方法
154 | int dy = fy - getScrollY(); //mScroller.getFinalY();
155 | smoothScrollBySlow(dx, dy, duration);
156 | }
157 |
158 | //调用此方法设置滚动的相对偏移
159 | public void smoothScrollBySlow(int dx, int dy,int duration) {
160 |
161 | //设置mScroller的滚动偏移量
162 | mScroller.startScroll(getScrollX(), getScrollY(), dx, dy,duration);//scrollView使用的方法(因为可以触摸拖动)
163 | // mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy, duration); //普通view使用的方法
164 | invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果
165 | }
166 |
167 | @Override
168 | public void computeScroll() {
169 |
170 | //先判断mScroller滚动是否完成
171 | if (mScroller.computeScrollOffset()) {
172 |
173 | //这里调用View的scrollTo()完成实际的滚动
174 | scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
175 |
176 | //必须调用该方法,否则不一定能看到滚动效果
177 | postInvalidate();
178 | }
179 | super.computeScroll();
180 | }
181 |
182 | }
183 |
--------------------------------------------------------------------------------
/app/src/main/java/com/czm/utils/PhoneUtil.java:
--------------------------------------------------------------------------------
1 | package com.czm.utils;
2 |
3 | import android.app.Activity;
4 | import android.app.ActivityManager;
5 | import android.content.Context;
6 | import android.content.pm.ConfigurationInfo;
7 | import android.opengl.EGL14;
8 | import android.opengl.EGLConfig;
9 | import android.opengl.EGLContext;
10 | import android.opengl.EGLDisplay;
11 | import android.opengl.EGLSurface;
12 | import android.opengl.GLES10;
13 | import android.opengl.GLES20;
14 | import android.os.Build;
15 | import android.support.v7.widget.RecyclerView;
16 | import android.util.DisplayMetrics;
17 | import android.view.Display;
18 | import android.view.View;
19 | import android.view.inputmethod.InputMethodManager;
20 |
21 | /**
22 | * Created by caizhiming on 15/12/18.
23 | */
24 | public class PhoneUtil {
25 | public static int TAB_BOTTOM_TYPE = 0;
26 | public static int TAB_TOP_TYPE = 0;
27 | private static boolean deviceDataInited = false;
28 | private static float displayMetricsDensity;
29 | private static int displayMetricsWidthPixels;
30 | private static int displayMetricsHeightPixels;
31 | private static int SCREEN_WIDTH_PX_CACHE = -1;
32 | private static int SCREEN_HEIGHT_PX_CACHE = -1;
33 | //android 5.0 以下
34 | private static final int DEFAULT_MAX_BITMAP_DIMENSION = 8196;
35 |
36 | public static void initDeviceData(Context context) {
37 | DisplayMetrics displayMetrics = null;
38 | if (context.getResources() != null && (displayMetrics = context.getResources().getDisplayMetrics()) != null) {
39 | displayMetricsDensity = displayMetrics.density;
40 | displayMetricsWidthPixels = displayMetrics.widthPixels;
41 | displayMetricsHeightPixels = displayMetrics.heightPixels;
42 | }
43 | deviceDataInited = true;
44 | }
45 |
46 | public static int dip2px(Context context, float dipValue) {
47 | if (!deviceDataInited) {
48 | initDeviceData(context);
49 | }
50 |
51 | return (int) (dipValue * displayMetricsDensity + 0.5f);
52 | }
53 |
54 | public static int px2dip(Context context, float pxValue) {
55 | if (!deviceDataInited) {
56 | initDeviceData(context);
57 | }
58 |
59 | return (int) (pxValue / displayMetricsDensity + 0.5f);
60 | }
61 |
62 | public static int getScreenWidthPx(Context context) {
63 | if (SCREEN_WIDTH_PX_CACHE < 0) {
64 | Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
65 | SCREEN_WIDTH_PX_CACHE = display.getWidth();
66 | }
67 |
68 | return SCREEN_WIDTH_PX_CACHE;
69 | }
70 |
71 | public static int getScreenHeightPx(Context context) {
72 | if (SCREEN_HEIGHT_PX_CACHE < 0) {
73 | Display display = ((Activity) context).getWindowManager().getDefaultDisplay();
74 | SCREEN_HEIGHT_PX_CACHE = display.getHeight();
75 | }
76 |
77 | return SCREEN_HEIGHT_PX_CACHE;
78 | }
79 |
80 |
81 | public static View getCenterXChild(RecyclerView recyclerView) {
82 | int childCount = recyclerView.getChildCount();
83 | if (childCount > 0) {
84 | for (int i = 0; i < childCount; ++i) {
85 | View child = recyclerView.getChildAt(i);
86 | if (isChildInCenterX(recyclerView, child)) {
87 | return child;
88 | }
89 | }
90 | }
91 |
92 | return null;
93 | }
94 |
95 | public static int getCenterXChildPosition(RecyclerView recyclerView) {
96 | int childCount = recyclerView.getChildCount();
97 | if (childCount > 0) {
98 | for (int i = 0; i < childCount; ++i) {
99 | View child = recyclerView.getChildAt(i);
100 | if (isChildInCenterX(recyclerView, child)) {
101 | return recyclerView.getChildAdapterPosition(child);
102 | }
103 | }
104 | }
105 |
106 | return childCount;
107 | }
108 |
109 | public static View getCenterYChild(RecyclerView recyclerView) {
110 | int childCount = recyclerView.getChildCount();
111 | if (childCount > 0) {
112 | for (int i = 0; i < childCount; ++i) {
113 | View child = recyclerView.getChildAt(i);
114 | if (isChildInCenterY(recyclerView, child)) {
115 | return child;
116 | }
117 | }
118 | }
119 |
120 | return null;
121 | }
122 |
123 | public static int getCenterYChildPosition(RecyclerView recyclerView) {
124 | int childCount = recyclerView.getChildCount();
125 | if (childCount > 0) {
126 | for (int i = 0; i < childCount; ++i) {
127 | View child = recyclerView.getChildAt(i);
128 | if (isChildInCenterY(recyclerView, child)) {
129 | return recyclerView.getChildAdapterPosition(child);
130 | }
131 | }
132 | }
133 |
134 | return childCount;
135 | }
136 |
137 | public static boolean isChildInCenterX(RecyclerView recyclerView, View view) {
138 | int childCount = recyclerView.getChildCount();
139 | int[] lvLocationOnScreen = new int[2];
140 | int[] vLocationOnScreen = new int[2];
141 | recyclerView.getLocationOnScreen(lvLocationOnScreen);
142 | int middleX = lvLocationOnScreen[0] + recyclerView.getWidth() / 2;
143 | if (childCount > 0) {
144 | view.getLocationOnScreen(vLocationOnScreen);
145 | if (vLocationOnScreen[0] <= middleX && vLocationOnScreen[0] + view.getWidth() >= middleX) {
146 | return true;
147 | }
148 | }
149 |
150 | return false;
151 | }
152 |
153 | public static boolean isChildInCenterY(RecyclerView recyclerView, View view) {
154 | int childCount = recyclerView.getChildCount();
155 | int[] lvLocationOnScreen = new int[2];
156 | int[] vLocationOnScreen = new int[2];
157 | recyclerView.getLocationOnScreen(lvLocationOnScreen);
158 | int middleY = lvLocationOnScreen[1] + recyclerView.getHeight() / 2;
159 | if (childCount > 0) {
160 | view.getLocationOnScreen(vLocationOnScreen);
161 | if (vLocationOnScreen[1] <= middleY && vLocationOnScreen[1] + view.getHeight() >= middleY) {
162 | return true;
163 | }
164 | }
165 |
166 | return false;
167 | }
168 |
169 | //隐藏键盘
170 | public static void hideSoftInput(Context context, View view) {
171 | // Log.e(TAG, Log.getStackTraceString(new Exception("hideSoftInput")));
172 |
173 | try {
174 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
175 | imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
176 | } catch (Exception e) {
177 | e.printStackTrace();
178 | }
179 | }
180 |
181 | //显示键盘
182 | public static void showSoftInput(Context context, View view) {
183 |
184 | try {
185 | InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
186 | // 如果输入法打开则关闭,如果没打开则打开
187 | imm.toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
188 | imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
189 | } catch (Exception e) {
190 | e.printStackTrace();
191 | }
192 | }
193 |
194 | /**
195 | * get the phone max textrure size (height)
196 | * caizhiming
197 | */
198 | public static int getMaxTextureSize(Context context, int maxHeight){
199 | if(maxHeight > 0 ){
200 | return maxHeight;
201 | }
202 | int[] maxSize = new int[1];
203 | try {
204 | ConfigurationInfo configurationInfo = ((ActivityManager)context.getSystemService(Context.ACTIVITY_SERVICE)).getDeviceConfigurationInfo();
205 | int glesVersion = configurationInfo.reqGlEsVersion;
206 | if(Build.VERSION.SDK_INT >= 21) {
207 | //configureEGLContext
208 | EGLDisplay mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
209 | if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
210 | throw new IllegalStateException("No EGL14 display");
211 | }
212 | int[] version = new int[2];
213 | if (!EGL14.eglInitialize(mEGLDisplay, version, /*offset*/ 0, version, /*offset*/ 1)) {
214 | throw new IllegalStateException("Cannot initialize EGL14");
215 | }
216 | int[] attribList = {
217 | EGL14.EGL_RED_SIZE, 8,
218 | EGL14.EGL_GREEN_SIZE, 8,
219 | EGL14.EGL_BLUE_SIZE, 8,
220 | EGL14.EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
221 | //EGL_RECORDABLE_ANDROID, 1,
222 | EGL14.EGL_SURFACE_TYPE, EGL14.EGL_PBUFFER_BIT | EGL14.EGL_WINDOW_BIT,
223 | EGL14.EGL_NONE
224 | };
225 | EGLConfig[] configs = new EGLConfig[1];
226 | int[] numConfigs = new int[1];
227 | EGL14.eglChooseConfig(mEGLDisplay, attribList, /*offset*/ 0, configs, /*offset*/ 0,
228 | configs.length, numConfigs, /*offset*/ 0);
229 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
230 | throw new IllegalStateException("eglCreateContext RGB888+recordable ES2" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
231 | }
232 | int[] attrib_list = {
233 | EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
234 | EGL14.EGL_NONE
235 | };
236 | EGLContext mEGLContext = EGL14.eglCreateContext(mEGLDisplay, configs[0], EGL14.EGL_NO_CONTEXT,
237 | attrib_list, /*offset*/ 0);
238 | if (EGL14.eglGetError() != EGL14.EGL_SUCCESS) {
239 | throw new IllegalStateException("eglCreateContext" + ": EGL error: 0x" + Integer.toHexString(EGL14.eglGetError()));
240 | }
241 | if (mEGLContext == EGL14.EGL_NO_CONTEXT) {
242 | throw new IllegalStateException("No EGLContext could be made");
243 | }
244 | int[] surfaceAttribs = {
245 | EGL14.EGL_WIDTH, 64,
246 | EGL14.EGL_HEIGHT, 64,
247 | EGL14.EGL_NONE
248 | };
249 | EGLSurface surface = EGL14.eglCreatePbufferSurface(mEGLDisplay, configs[0], surfaceAttribs, 0);
250 | EGL14.eglMakeCurrent(mEGLDisplay, surface, surface, mEGLContext);
251 | //getMaxTextureSize
252 | if(glesVersion >= 0x20000) {
253 | GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
254 | }else if(glesVersion >= 0x10000) {
255 | GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
256 | }
257 | //releaseEGLContext
258 | EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
259 | EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
260 | EGL14.eglReleaseThread();
261 | EGL14.eglTerminate(mEGLDisplay);
262 | }else {
263 | if(glesVersion >= 0x20000) {
264 | GLES20.glGetIntegerv(GLES20.GL_MAX_TEXTURE_SIZE, maxSize, 0);
265 | }else if(glesVersion >= 0x10000) {
266 | GLES10.glGetIntegerv(GLES10.GL_MAX_TEXTURE_SIZE, maxSize, 0);
267 | }
268 | }
269 | } catch (IllegalStateException e) {
270 | e.printStackTrace();
271 | }
272 | maxHeight = maxSize[0] > 0 ? maxSize[0] : DEFAULT_MAX_BITMAP_DIMENSION;
273 | return maxHeight;
274 | }
275 | }
276 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/bg_msg_red_dot.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/drawable/bg_msg_red_dot.9.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/icon_back_orange.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/drawable/icon_back_orange.png
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
14 |
15 |
20 |
21 |
29 |
30 |
31 |
32 |
38 |
39 |
43 |
52 |
65 |
66 |
67 |
72 |
73 |
74 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_viewpager_list.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_list_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_tab.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
16 |
29 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/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 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
231 |
232 |
233 |
234 |
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
264 |
265 |
266 |
267 |
268 |
269 |
270 |
271 |
272 |
273 |
274 |
279 |
280 |
281 |
282 |
283 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 |
295 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | XCUpHideScrollView
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/app/src/test/java/com/czm/main/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.czm.main;
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() throws Exception {
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 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.3.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
21 | task clean(type: Delete) {
22 | delete rootProject.buildDir
23 | }
24 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | org.gradle.jvmargs=-Xmx1536m
13 |
14 | # When configured, Gradle will run in incubating parallel mode.
15 | # This option should only be used with decoupled projects. More details, visit
16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
17 | # org.gradle.parallel=true
18 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu Apr 13 10:25:54 CST 2017
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-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/screenshots/01.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jczmdeveloper/XCUpHideScrollView/767dddf2f7fa9febe4bab078d3272cfdb9f02750/screenshots/01.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------