diff --git a/.gitignore b/.gitignore
deleted file mode 100644
index ae946ad..0000000
--- a/.gitignore
+++ /dev/null
@@ -1,42 +0,0 @@
-### Android template
-# Built application files
-*.apk
-*.ap_
-
-# Files for the Dalvik VM
-*.dex
-
-# Java class files
-*.class
-
-# Generated files
-bin/
-gen/
-
-# Gradle files
-.gradle/
-build/
-
-# Local configuration file (sdk path, etc)
-local.properties
-
-# Proguard folder generated by Eclipse
-proguard/
-
-# Log Files
-*.log
-
-# Android Studio Navigation editor temp files
-.navigation/
-
-/.gitignore
-.gradle
-/local.properties
-/.idea/workspace.xml
-/.idea/libraries
-.DS_Store
-/build
-/captures
-/.idea
-*.iml
-.idea
diff --git a/app/build.gradle b/app/build.gradle
index cf2fb9f..ffd7cbb 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -35,4 +35,8 @@ dependencies {
compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.lsjwzh:materialloadingprogressbar:0.5.8-RELEASE'
compile 'com.github.Aspsine:FragmentNavigator:1.0.2'
+
+ compile 'com.android.support:cardview-v7:25.1.0'
+ compile 'com.jakewharton:butterknife:8.4.0'
+ annotationProcessor 'com.jakewharton:butterknife-compiler:8.4.0'
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index dec8147..24115e6 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -21,6 +21,9 @@
+
+
+
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/MainActivity.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/MainActivity.java
index 5a860b8..44d2afa 100644
--- a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/MainActivity.java
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/MainActivity.java
@@ -1,90 +1,42 @@
package com.aspsine.swipetoloadlayout.demo;
-
import android.content.Intent;
import android.os.Bundle;
-import android.support.design.widget.NavigationView;
-import android.support.v4.view.GravityCompat;
-import android.support.v4.widget.DrawerLayout;
+import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
-import android.view.MenuItem;
-
-import com.aspsine.fragmentnavigator.FragmentNavigator;
-import com.aspsine.swipetoloadlayout.demo.fragment.BaseToolbarFragment;
-
-import java.util.Arrays;
-import java.util.List;
-
-public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener
- , BaseToolbarFragment.ToggleDrawerCallBack {
-
- private static final Integer ID_ARRAY[] = {
- R.id.nav_Twitter_style,
- R.id.nav_google_style,
- R.id.nav_yalantis_style,
- R.id.nav_jd_style,
- R.id.nav_set_header_footer_via_code
- };
-
- private static final List IDS = Arrays.asList(ID_ARRAY);
+import android.view.View;
- private static final int DEFAULT_POSITION = 0;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
- private DrawerLayout drawerLayout;
+/**
+ * Created by wang
+ * on 2017/1/22
+ */
- /**
- * https://github.com/Aspsine/FragmentNavigator
- */
- private FragmentNavigator mFragmentNavigator;
+public class MainActivity extends AppCompatActivity {
@Override
- protected void onCreate(Bundle savedInstanceState) {
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
- mFragmentNavigator = new FragmentNavigator(getSupportFragmentManager(), new MainFragmentAdapter(), R.id.container);
-
- mFragmentNavigator.setDefaultPosition(DEFAULT_POSITION);
-
- mFragmentNavigator.onCreate(savedInstanceState);
-
setContentView(R.layout.activity_main);
-
- drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
-
- NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
-
- navigationView.setNavigationItemSelectedListener(this);
-
- navigationView.setCheckedItem(IDS.get(DEFAULT_POSITION));
-
- mFragmentNavigator.showFragment(mFragmentNavigator.getCurrentPosition());
+ ButterKnife.bind(this);
}
- @Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- mFragmentNavigator.onSaveInstanceState(outState);
- }
-
- @Override
- public void openDrawer() {
- drawerLayout.openDrawer(GravityCompat.START);
- }
-
- @Override
- public boolean onNavigationItemSelected(final MenuItem menuItem) {
- drawerLayout.closeDrawer(GravityCompat.START);
- drawerLayout.postDelayed(new Runnable() {
- @Override
- public void run() {
- int itemId = menuItem.getItemId();
- if (itemId == R.id.nav_about) {
- startActivity(new Intent(MainActivity.this, AboutActivity.class));
- } else {
- mFragmentNavigator.showFragment(IDS.indexOf(itemId));
- }
- }
- }, 200);
- return true;
+ @OnClick({R.id.recycler_btn, R.id.pager_btn, R.id.ver_btn})
+ public void onClick(View view) {
+ Intent intent = new Intent();
+ switch (view.getId()) {
+ case R.id.ver_btn:
+ intent.setClass(this, VerActivity.class);
+ break;
+ case R.id.recycler_btn:
+ intent.setClass(this, RecyclerActivity.class);
+ break;
+ case R.id.pager_btn:
+ intent.setClass(this, ViewPagerActivity.class);
+ break;
+ }
+ startActivity(intent);
}
}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/OnRecyclerClickListener.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/OnRecyclerClickListener.java
new file mode 100644
index 0000000..efab5b6
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/OnRecyclerClickListener.java
@@ -0,0 +1,12 @@
+package com.aspsine.swipetoloadlayout.demo;
+
+/**
+ * Created by wang
+ * on 2017/1/22
+ */
+
+public interface OnRecyclerClickListener {
+
+ void onClick(int position);
+
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/RecyclerActivity.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/RecyclerActivity.java
new file mode 100644
index 0000000..6054bfd
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/RecyclerActivity.java
@@ -0,0 +1,68 @@
+package com.aspsine.swipetoloadlayout.demo;
+
+import android.os.Bundle;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.widget.Toast;
+
+import com.aspsine.swipetoloadlayout.OnLoadMoreListener;
+import com.aspsine.swipetoloadlayout.OnRefreshListener;
+import com.aspsine.swipetoloadlayout.SwipeToLoadLayout;
+import com.aspsine.swipetoloadlayout.demo.adapter.RecyclerAdapter;
+
+import java.util.ArrayList;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+public class RecyclerActivity extends AppCompatActivity implements OnRefreshListener, OnLoadMoreListener, OnRecyclerClickListener {
+
+ @BindView(R.id.swipe_target)
+ RecyclerView mRecyclerView;
+ @BindView(R.id.load_layout)
+ SwipeToLoadLayout mLoadLayout;
+
+ private ArrayList mNames;
+ private int mName;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_recycler);
+ ButterKnife.bind(this);
+ mLoadLayout.setOnRefreshListener(this);
+ mLoadLayout.setOnLoadMoreListener(this);
+ mNames = new ArrayList<>();
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false));
+ mRecyclerView.setAdapter(new RecyclerAdapter(mNames, this));
+ onRefresh();
+ }
+
+ @Override
+ public void onRefresh() {
+ mNames.clear();
+ mName = 0;
+ for (int i = 0; i < 3; i++) {
+ mNames.add("name: " + mName);
+ mName ++;
+ }
+ mRecyclerView.getAdapter().notifyDataSetChanged();
+ mLoadLayout.setRefreshing(false);
+ }
+
+ @Override
+ public void onLoadMore() {
+ for (int i = 0; i < 3; i++) {
+ mNames.add("name: " + mName);
+ mName ++;
+ }
+ mRecyclerView.getAdapter().notifyDataSetChanged();
+ mLoadLayout.setLoadingMore(false);
+ }
+
+ @Override
+ public void onClick(int position) {
+ Toast.makeText(this, mNames.get(position), Toast.LENGTH_SHORT).show();
+ }
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/VerActivity.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/VerActivity.java
new file mode 100644
index 0000000..a0fdcca
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/VerActivity.java
@@ -0,0 +1,90 @@
+package com.aspsine.swipetoloadlayout.demo;
+
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.design.widget.NavigationView;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v7.app.AppCompatActivity;
+import android.view.MenuItem;
+
+import com.aspsine.fragmentnavigator.FragmentNavigator;
+import com.aspsine.swipetoloadlayout.demo.fragment.BaseToolbarFragment;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class VerActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener
+ , BaseToolbarFragment.ToggleDrawerCallBack {
+
+ private static final Integer ID_ARRAY[] = {
+ R.id.nav_Twitter_style,
+ R.id.nav_google_style,
+ R.id.nav_yalantis_style,
+ R.id.nav_jd_style,
+ R.id.nav_set_header_footer_via_code
+ };
+
+ private static final List IDS = Arrays.asList(ID_ARRAY);
+
+ private static final int DEFAULT_POSITION = 0;
+
+ private DrawerLayout drawerLayout;
+
+ /**
+ * https://github.com/Aspsine/FragmentNavigator
+ */
+ private FragmentNavigator mFragmentNavigator;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mFragmentNavigator = new FragmentNavigator(getSupportFragmentManager(), new MainFragmentAdapter(), R.id.container);
+
+ mFragmentNavigator.setDefaultPosition(DEFAULT_POSITION);
+
+ mFragmentNavigator.onCreate(savedInstanceState);
+
+ setContentView(R.layout.activity_ver);
+
+ drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
+
+ NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
+
+ navigationView.setNavigationItemSelectedListener(this);
+
+ navigationView.setCheckedItem(IDS.get(DEFAULT_POSITION));
+
+ mFragmentNavigator.showFragment(mFragmentNavigator.getCurrentPosition());
+ }
+
+ @Override
+ protected void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ mFragmentNavigator.onSaveInstanceState(outState);
+ }
+
+ @Override
+ public void openDrawer() {
+ drawerLayout.openDrawer(GravityCompat.START);
+ }
+
+ @Override
+ public boolean onNavigationItemSelected(final MenuItem menuItem) {
+ drawerLayout.closeDrawer(GravityCompat.START);
+ drawerLayout.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ int itemId = menuItem.getItemId();
+ if (itemId == R.id.nav_about) {
+ startActivity(new Intent(VerActivity.this, AboutActivity.class));
+ } else {
+ mFragmentNavigator.showFragment(IDS.indexOf(itemId));
+ }
+ }
+ }, 200);
+ return true;
+ }
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/ViewPagerActivity.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/ViewPagerActivity.java
new file mode 100644
index 0000000..65fb288
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/ViewPagerActivity.java
@@ -0,0 +1,75 @@
+package com.aspsine.swipetoloadlayout.demo;
+
+import android.os.Bundle;
+import android.support.annotation.Nullable;
+import android.support.v4.view.ViewPager;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.Toast;
+
+import com.aspsine.swipetoloadlayout.OnLoadMoreListener;
+import com.aspsine.swipetoloadlayout.OnRefreshListener;
+import com.aspsine.swipetoloadlayout.SwipeToLoadLayout;
+import com.aspsine.swipetoloadlayout.demo.adapter.ViewPagerAdapter;
+
+import java.util.ArrayList;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * Created by wang
+ * on 2017/1/22
+ */
+
+public class ViewPagerActivity extends AppCompatActivity implements OnRefreshListener, OnLoadMoreListener, OnRecyclerClickListener {
+
+ @BindView(R.id.swipe_target)
+ ViewPager mViewPager;
+ @BindView(R.id.load_layout)
+ SwipeToLoadLayout mLoadLayout;
+
+ private ArrayList mNames;
+
+ private int mName;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_viewpager);
+ ButterKnife.bind(this);
+ mLoadLayout.setOnRefreshListener(this);
+ mLoadLayout.setOnLoadMoreListener(this);
+ mNames = new ArrayList<>();
+ mViewPager.setAdapter(new ViewPagerAdapter(mNames, this));
+ onRefresh();
+ }
+
+ @Override
+ public void onRefresh() {
+ mNames.clear();
+ mName = 0;
+ for (int i = 0; i < 3; i++) {
+ mNames.add("name: " + mName);
+ mName ++;
+ }
+ mViewPager.getAdapter().notifyDataSetChanged();
+ mLoadLayout.setRefreshing(false);
+ }
+
+ @Override
+ public void onLoadMore() {
+ for (int i = 0; i < 3; i++) {
+ mNames.add("name: " + mName);
+ mName ++;
+ }
+ mViewPager.getAdapter().notifyDataSetChanged();
+ mLoadLayout.setLoadingMore(false);
+ }
+
+ @Override
+ public void onClick(int position) {
+ Toast.makeText(this, mNames.get(position), Toast.LENGTH_SHORT).show();
+ }
+
+
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/RecyclerAdapter.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/RecyclerAdapter.java
new file mode 100644
index 0000000..b28d8da
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/RecyclerAdapter.java
@@ -0,0 +1,65 @@
+package com.aspsine.swipetoloadlayout.demo.adapter;
+
+import android.support.v7.widget.AppCompatTextView;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.aspsine.swipetoloadlayout.demo.OnRecyclerClickListener;
+import com.aspsine.swipetoloadlayout.demo.R;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+
+/**
+ * Created by wang
+ * on 2017/1/22
+ */
+
+public class RecyclerAdapter extends RecyclerView.Adapter {
+
+ private List mNames;
+
+ private OnRecyclerClickListener mListener;
+
+ public RecyclerAdapter(List names, OnRecyclerClickListener listener) {
+ mNames = names;
+ mListener = listener;
+ }
+
+ @Override
+ public TextViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_text, parent, false);
+ return new TextViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(TextViewHolder holder, int position) {
+ holder.mNameTv.setText(mNames.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return mNames.size();
+ }
+
+ class TextViewHolder extends RecyclerView.ViewHolder {
+
+ @BindView(R.id.name_tv)
+ AppCompatTextView mNameTv;
+
+ public TextViewHolder(View itemView) {
+ super(itemView);
+ ButterKnife.bind(this, itemView);
+ itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mListener.onClick(getAdapterPosition());
+ }
+ });
+ }
+ }
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/ViewPagerAdapter.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/ViewPagerAdapter.java
new file mode 100644
index 0000000..69604f8
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/adapter/ViewPagerAdapter.java
@@ -0,0 +1,96 @@
+package com.aspsine.swipetoloadlayout.demo.adapter;
+
+import android.support.v4.view.PagerAdapter;
+import android.support.v7.widget.AppCompatTextView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.aspsine.swipetoloadlayout.demo.OnRecyclerClickListener;
+import com.aspsine.swipetoloadlayout.demo.R;
+
+import java.util.List;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+
+/**
+ * Created by wang
+ * on 2017/1/22
+ */
+
+public class ViewPagerAdapter extends PagerAdapter {
+
+ private List mName;
+ private OnRecyclerClickListener mListener;
+
+ public ViewPagerAdapter(List name, OnRecyclerClickListener listener) {
+ mName = name;
+ mListener = listener;
+ }
+
+ public ViewPagerAdapter(List name) {
+ mName = name;
+ }
+
+ public List getName() {
+ return mName;
+ }
+
+ @Override
+ public int getCount() {
+ return mName.size();
+ }
+
+ @Override
+ public boolean isViewFromObject(View view, Object object) {
+ return view == ((ViewHolder) object).itemView;
+ }
+
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ View convertView = LayoutInflater.from(container.getContext()).inflate(R.layout.item_pager_text, container, false);
+ container.addView(convertView);
+ return new ViewHolder(convertView, position);
+ }
+
+ @Override
+ public void destroyItem(ViewGroup container, int position, Object object) {
+ container.removeView(((ViewHolder) object).itemView);
+ }
+
+ @Override
+ public int getItemPosition(Object object) {
+ return POSITION_NONE;
+ }
+
+
+ class ViewHolder {
+
+ @BindView(R.id.name_tv)
+ AppCompatTextView mNameTv;
+
+ View itemView;
+
+ private int mPosition;
+
+ public ViewHolder(View view, int position) {
+ itemView = view;
+ mPosition = position;
+ ButterKnife.bind(this, view);
+ onBindView(mName.get(position));
+ }
+
+ @OnClick(R.id.name_tv)
+ public void onClick() {
+ if (mListener != null) {
+ mListener.onClick(mPosition);
+ }
+ }
+
+ private void onBindView(String name) {
+ mNameTv.setText(name);
+ }
+ }
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/VerticalTextView2.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/VerticalTextView2.java
new file mode 100644
index 0000000..3ae693f
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/VerticalTextView2.java
@@ -0,0 +1,244 @@
+package com.aspsine.swipetoloadlayout.demo.view;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+import android.view.View;
+
+import com.aspsine.swipetoloadlayout.demo.R;
+
+/**
+ * Created on 2016/10/31.
+ * Author: wang
+ */
+
+public class VerticalTextView2 extends View {
+
+ public static enum StartAlign {
+
+ LEFT(0x0),
+ RIGHT(0x1);
+
+ private int value;
+
+ StartAlign(int value) {
+ this.value = value;
+ }
+
+ public int getValue() {
+ return value;
+ }
+ }
+
+ /**
+ * 需要绘制的文字
+ */
+ private String mText = "";
+ /**
+ * 文本的颜色
+ */
+ private int mTextColor = Color.BLACK;
+ /**
+ * 文本的大小
+ */
+ private float mTextSize = 40;
+
+ /**
+ * 每列最多显示数量
+ */
+ private int vTextNum = -1;
+
+
+ /**
+ * 字体高度
+ */
+ private float mFontHeight;
+ private float mFontBaseLine;
+
+ // 列宽度
+ private int mLineWidth = 0;
+ // 列间距
+ private int mLineSpacing = 20;
+
+ private int specHeight;
+ private int specWidth;
+ //能够显示文本的最大高度
+
+ // 绘制字体的默认方向
+ private StartAlign textStartAlign = StartAlign.LEFT;
+
+ /**
+ * 绘制时控制文本绘制的范围
+ */
+ private Paint mPaint;
+
+ private boolean isMeasure;
+
+ public VerticalTextView2(Context context) {
+ this(context, null);
+ }
+
+ public VerticalTextView2(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public VerticalTextView2(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ if (attrs != null) {
+ //获取自定义属性的值
+ TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.VerticalTextView2, defStyleAttr, 0);
+ try {
+ mText = a.getString(R.styleable.VerticalTextView2_ver_text);
+ mTextColor = a.getColor(R.styleable.VerticalTextView2_ver_textColor, Color.BLACK);
+ mTextSize = a.getDimensionPixelSize(R.styleable.VerticalTextView2_ver_textSize, 40);
+ vTextNum = a.getInt(R.styleable.VerticalTextView2_ver_textNum, -1);
+ mLineSpacing = a.getDimensionPixelOffset(R.styleable.VerticalTextView2_ver_lineSpacing, 20);
+ int align = a.getInt(R.styleable.VerticalTextView2_ver_textStartAlign, StartAlign.RIGHT.getValue());
+ if (StartAlign.LEFT.getValue() == align) {
+ textStartAlign = StartAlign.LEFT;
+ } else {
+ textStartAlign = StartAlign.RIGHT;
+ }
+ } finally {
+ a.recycle();
+ }
+ }
+ mPaint = new Paint();
+ mPaint.setTextSize(mTextSize);
+ mPaint.setColor(mTextColor);
+ // 文字居中
+ mPaint.setTextAlign(Paint.Align.CENTER);
+ // 平滑处理
+ mPaint.setAntiAlias(true);
+
+ }
+
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ //绘制文字
+ char StringItem;
+ boolean isRight = StartAlign.RIGHT == textStartAlign;
+ float textHeight = mFontHeight;
+ int viewHeight = specHeight;
+ float mTextPosY = mFontBaseLine;
+ float mTextPosX = isRight ? getWidth() : 0;
+ mTextPosX += isRight ? -mLineWidth >> 1 : mLineWidth >> 1;//字体居住绘制 x起始位置-mLineWidth>>1
+ int textLength = mText.length();
+ for (int i = 0; i < textLength; i++) {
+ StringItem = mText.charAt(i);
+ if (mTextPosY > viewHeight) {
+ mTextPosY = mFontBaseLine;
+ mTextPosX += isRight ? -mLineWidth : mLineWidth;
+ if (mTextPosX > specWidth) {
+ return;
+ }
+ }
+ canvas.drawText(String.valueOf(StringItem), mTextPosX, mTextPosY, mPaint);
+ mTextPosY += textHeight;
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+
+ //onMeasure方法会调用多次,为了避免重复分段,做判断
+
+ if (!isMeasure) {
+ isMeasure = true;
+ //计算字体高度大小
+ measureTextSize();
+ }
+ measureWH(heightMeasureSpec);
+ //保存测量宽度和测量高度
+ setMeasuredDimension(specWidth, specHeight);
+ }
+
+
+
+ private void measureWH(int heightMeasureSpec) {
+ int heightMode = MeasureSpec.getMode(heightMeasureSpec); //获取高的模式
+ int heightSize = MeasureSpec.getSize(heightMeasureSpec); //获取高的尺寸
+
+ int textHeight = (int) mFontHeight;
+ int textLength = null == mText ? 0 : mText.length();
+
+ //高度
+ //match_parent或者具体的值
+ if (heightMode == MeasureSpec.EXACTLY) {
+ specHeight = heightSize;
+ } else {
+ //wrap_content
+ float tempHeight = Math.min(textHeight * textLength, heightSize);
+ if (vTextNum != -1) {
+ tempHeight = vTextNum * textHeight;
+ }
+ specHeight = (int) (getPaddingTop() + tempHeight + getPaddingBottom());
+ }
+
+ float lineNum = textHeight * textLength / specHeight;
+
+ int textWidth = (int) (Math.ceil(lineNum) * mLineWidth);
+ specWidth = getPaddingLeft() + textWidth + getPaddingRight();
+ }
+
+ public String getText() {
+ return mText;
+ }
+
+ public void setText(String mText) {
+ this.mText = mText;
+ resetMeasure();
+ }
+
+ public int getTextColor() {
+ return mTextColor;
+ }
+
+ public void setTextColor(int mTextColor) {
+ this.mTextColor = mTextColor;
+ mPaint.setColor(mTextColor);
+ }
+
+ public float getTextSize() {
+ return mTextSize;
+ }
+
+ public void setTextSize(float mTextSize) {
+ this.mTextSize = mTextSize;
+ mPaint.setTextSize(mTextSize);
+ resetMeasure();
+ }
+
+ private void resetMeasure() {
+ isMeasure = false;
+ requestLayout();
+ }
+
+ /**
+ * 计算文字大小高度
+ */
+ private void measureTextSize() {
+
+ mPaint.setTextSize(mTextSize);
+ // 获得行宽包括间隔
+ if (mLineWidth == 0) {
+ float[] widths = new float[1];
+ // 获取单个汉字的宽度
+ mPaint.getTextWidths("汉", widths);
+
+ mLineWidth = mLineSpacing + (int) widths[0];
+ }
+
+ Paint.FontMetrics fm = mPaint.getFontMetrics();
+
+ // 获得字体高度
+ mFontHeight = fm.bottom - fm.top;
+ mFontBaseLine = - fm.top;
+
+ }
+
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/footer/WRefreshFooterView.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/footer/WRefreshFooterView.java
new file mode 100644
index 0000000..ade1651
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/footer/WRefreshFooterView.java
@@ -0,0 +1,96 @@
+package com.aspsine.swipetoloadlayout.demo.view.footer;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.util.AttributeSet;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.aspsine.swipetoloadlayout.SwipeLoadMoreTrigger;
+import com.aspsine.swipetoloadlayout.SwipeTrigger;
+import com.aspsine.swipetoloadlayout.demo.R;
+import com.aspsine.swipetoloadlayout.demo.view.VerticalTextView2;
+
+
+/**
+ * Created on 2016/1/14.
+ * Author: wang
+ */
+public class WRefreshFooterView extends LinearLayout implements SwipeTrigger, SwipeLoadMoreTrigger {
+
+ private ImageView mLoadingImg;
+
+ private VerticalTextView2 mLoadMoreTV;
+
+ private AnimationDrawable mAnimDrawable;
+
+ private int mFooterHeight;
+
+
+ public WRefreshFooterView(Context context) {
+ super(context);
+ mFooterHeight = getResources().getDimensionPixelOffset(R.dimen.refresh_footer_height);
+ }
+
+ public WRefreshFooterView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ mFooterHeight = getResources().getDimensionPixelOffset(R.dimen.refresh_footer_height);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ mLoadingImg = (ImageView) findViewById(R.id.loading_img);
+ mLoadMoreTV = (VerticalTextView2) findViewById(R.id.load_more_tv);
+ mAnimDrawable = (AnimationDrawable) mLoadingImg.getDrawable();
+ }
+
+
+ @Override
+ public void onPrepare() {
+
+ }
+
+ @Override
+ public void onMove(int y, boolean isComplete, boolean automatic) {
+ if (!isComplete) {
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ mLoadMoreTV.setVisibility(VISIBLE);
+ if (-y >= mFooterHeight) {
+ mLoadMoreTV.setText("释放加载更多");
+ } else {
+ mLoadMoreTV.setText("左滑加载更多");
+ }
+ }
+ }
+
+ @Override
+ public void onRelease() {
+
+ }
+
+ @Override
+ public void onLoadMore() {
+ mLoadMoreTV.setVisibility(GONE);
+ mLoadingImg.setVisibility(VISIBLE);
+ mAnimDrawable.start();
+ }
+
+ @Override
+ public void onComplete() {
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ mLoadMoreTV.setVisibility(VISIBLE);
+ mLoadMoreTV.setText("加载完成");
+ }
+
+ @Override
+ public void onReset() {
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ mLoadMoreTV.setVisibility(VISIBLE);
+ mLoadMoreTV.setText("左滑加载更多");
+ }
+
+}
diff --git a/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/header/WRefreshHeaderView.java b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/header/WRefreshHeaderView.java
new file mode 100644
index 0000000..e9ba271
--- /dev/null
+++ b/app/src/main/java/com/aspsine/swipetoloadlayout/demo/view/header/WRefreshHeaderView.java
@@ -0,0 +1,132 @@
+package com.aspsine.swipetoloadlayout.demo.view.header;
+
+import android.content.Context;
+import android.graphics.drawable.AnimationDrawable;
+import android.util.AttributeSet;
+import android.view.animation.Animation;
+import android.view.animation.AnimationUtils;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import com.aspsine.swipetoloadlayout.SwipeRefreshTrigger;
+import com.aspsine.swipetoloadlayout.SwipeTrigger;
+import com.aspsine.swipetoloadlayout.demo.R;
+import com.aspsine.swipetoloadlayout.demo.view.VerticalTextView2;
+
+/**
+ * Created on 2016/9/20.
+ * Author: wang
+ */
+public class WRefreshHeaderView extends LinearLayout implements SwipeTrigger, SwipeRefreshTrigger {
+
+ private ImageView mArrowImg;
+
+ private ImageView mLoadingImg;
+
+ private ImageView mSuccessImg;
+
+ private VerticalTextView2 mRefreshTV;
+
+ private AnimationDrawable mAnimDrawable;
+
+ private int mHeaderHeight;
+
+ private Animation rotateUp;
+
+ private Animation rotateDown;
+
+ private boolean rotated = false;
+
+ public WRefreshHeaderView(Context context) {
+ this(context, null);
+ }
+
+ public WRefreshHeaderView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public WRefreshHeaderView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ mHeaderHeight = getResources().getDimensionPixelOffset(R.dimen.refresh_header_height);
+ rotateUp = AnimationUtils.loadAnimation(context, R.anim.rotate_up);
+ rotateDown = AnimationUtils.loadAnimation(context, R.anim.rotate_down);
+ }
+
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+
+ mRefreshTV = (VerticalTextView2) findViewById(R.id.refresh_tv);
+ mArrowImg = (ImageView) findViewById(R.id.arrow_img);
+ mSuccessImg = (ImageView) findViewById(R.id.success_img);
+ mLoadingImg = (ImageView) findViewById(R.id.loading_img);
+ mAnimDrawable = (AnimationDrawable) mLoadingImg.getDrawable();
+ }
+
+ @Override
+ public void onRefresh() {
+ mSuccessImg.setVisibility(GONE);
+ mArrowImg.clearAnimation();
+ mArrowImg.setVisibility(GONE);
+ mLoadingImg.setVisibility(VISIBLE);
+ mAnimDrawable.start();
+ mRefreshTV.setText("加载中...");
+ }
+
+ @Override
+ public void onPrepare() {
+
+ }
+
+ @Override
+ public void onMove(int y, boolean isComplete, boolean automatic) {
+ if (!isComplete) {
+ mArrowImg.setVisibility(VISIBLE);
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ mSuccessImg.setVisibility(GONE);
+ if (y > mHeaderHeight) {
+ mRefreshTV.setText("释放刷新");
+ if (!rotated) {
+ mArrowImg.clearAnimation();
+ mArrowImg.startAnimation(rotateUp);
+ rotated = true;
+ }
+ } else if (y < mHeaderHeight) {
+ if (rotated) {
+ mArrowImg.clearAnimation();
+ mArrowImg.startAnimation(rotateDown);
+ rotated = false;
+ }
+ mRefreshTV.setText("右滑刷新");
+ }
+ }
+ }
+
+ @Override
+ public void onRelease() {
+
+ }
+
+ @Override
+ public void onComplete() {
+ rotated = false;
+ mSuccessImg.setVisibility(VISIBLE);
+ mArrowImg.clearAnimation();
+ mArrowImg.setVisibility(GONE);
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ mRefreshTV.setText("刷新完成");
+ }
+
+ @Override
+ public void onReset() {
+ rotated = false;
+ mSuccessImg.setVisibility(GONE);
+ mArrowImg.clearAnimation();
+ mArrowImg.setVisibility(VISIBLE);
+ mAnimDrawable.stop();
+ mLoadingImg.setVisibility(GONE);
+ }
+
+}
diff --git a/app/src/main/res/drawable/refresh_loading.xml b/app/src/main/res/drawable/refresh_loading.xml
new file mode 100644
index 0000000..8b18765
--- /dev/null
+++ b/app/src/main/res/drawable/refresh_loading.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 10d525e..db5d8f1 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,24 +1,33 @@
-
+ android:layout_height="match_parent"
+ android:orientation="vertical">
-
+ android:layout_height="wrap_content"
+ android:text="下拉刷新 上拉加载更多"
+ android:layout_marginTop="64dp"
+ android:layout_marginStart="16dp"
+ android:layout_marginEnd="16dp"/>
-
+
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_recycler.xml b/app/src/main/res/layout/activity_recycler.xml
new file mode 100644
index 0000000..6113f2d
--- /dev/null
+++ b/app/src/main/res/layout/activity_recycler.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_ver.xml b/app/src/main/res/layout/activity_ver.xml
new file mode 100644
index 0000000..10d525e
--- /dev/null
+++ b/app/src/main/res/layout/activity_ver.xml
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_viewpager.xml b/app/src/main/res/layout/activity_viewpager.xml
new file mode 100644
index 0000000..192a47f
--- /dev/null
+++ b/app/src/main/res/layout/activity_viewpager.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_pager_text.xml b/app/src/main/res/layout/item_pager_text.xml
new file mode 100644
index 0000000..ecb30c1
--- /dev/null
+++ b/app/src/main/res/layout/item_pager_text.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_text.xml b/app/src/main/res/layout/item_text.xml
new file mode 100644
index 0000000..72290ef
--- /dev/null
+++ b/app/src/main/res/layout/item_text.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_refresh_footer_hor_view.xml b/app/src/main/res/layout/layout_refresh_footer_hor_view.xml
new file mode 100644
index 0000000..0d98fdb
--- /dev/null
+++ b/app/src/main/res/layout/layout_refresh_footer_hor_view.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/layout_refresh_header_hor_view.xml b/app/src/main/res/layout/layout_refresh_header_hor_view.xml
new file mode 100644
index 0000000..a3828c6
--- /dev/null
+++ b/app/src/main/res/layout/layout_refresh_header_hor_view.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/recycler_view_head_foot.xml b/app/src/main/res/layout/recycler_view_head_foot.xml
new file mode 100644
index 0000000..e35a0bf
--- /dev/null
+++ b/app/src/main/res/layout/recycler_view_head_foot.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index cd75729..1c66ea0 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -1,6 +1,6 @@
diff --git a/app/src/main/res/mipmap-hdpi/refresh_head_arrow.png b/app/src/main/res/mipmap-hdpi/refresh_head_arrow.png
new file mode 100644
index 0000000..701605b
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_head_arrow.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading01.png b/app/src/main/res/mipmap-hdpi/refresh_loading01.png
new file mode 100644
index 0000000..1c190a9
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading01.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading02.png b/app/src/main/res/mipmap-hdpi/refresh_loading02.png
new file mode 100644
index 0000000..bc930f2
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading02.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading03.png b/app/src/main/res/mipmap-hdpi/refresh_loading03.png
new file mode 100644
index 0000000..e461335
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading03.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading04.png b/app/src/main/res/mipmap-hdpi/refresh_loading04.png
new file mode 100644
index 0000000..071af1e
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading04.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading05.png b/app/src/main/res/mipmap-hdpi/refresh_loading05.png
new file mode 100644
index 0000000..43ba85f
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading05.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading06.png b/app/src/main/res/mipmap-hdpi/refresh_loading06.png
new file mode 100644
index 0000000..67c6faa
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading06.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading07.png b/app/src/main/res/mipmap-hdpi/refresh_loading07.png
new file mode 100644
index 0000000..797c5d8
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading07.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading08.png b/app/src/main/res/mipmap-hdpi/refresh_loading08.png
new file mode 100644
index 0000000..bbeecf2
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading08.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading09.png b/app/src/main/res/mipmap-hdpi/refresh_loading09.png
new file mode 100644
index 0000000..397c08d
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading09.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading10.png b/app/src/main/res/mipmap-hdpi/refresh_loading10.png
new file mode 100644
index 0000000..2c4c58b
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading10.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading11.png b/app/src/main/res/mipmap-hdpi/refresh_loading11.png
new file mode 100644
index 0000000..587c1df
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading11.png differ
diff --git a/app/src/main/res/mipmap-hdpi/refresh_loading12.png b/app/src/main/res/mipmap-hdpi/refresh_loading12.png
new file mode 100644
index 0000000..162ffd4
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/refresh_loading12.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/refresh_success.png b/app/src/main/res/mipmap-xhdpi/refresh_success.png
new file mode 100644
index 0000000..0584ace
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/refresh_success.png differ
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index 0715ea3..60cce0d 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -24,4 +24,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
index 31c3c12..dafe89d 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -32,4 +32,8 @@
100dp
+
+ 40dp
+ 40dp
+
diff --git a/art/demo.apk b/art/demo.apk
deleted file mode 100644
index 10c29fa..0000000
Binary files a/art/demo.apk and /dev/null differ
diff --git a/build.gradle b/build.gradle
index 74b2ab0..1ea4bd0 100644
--- a/build.gradle
+++ b/build.gradle
@@ -5,7 +5,7 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:2.2.3'
+ classpath 'com.android.tools.build:gradle:2.3.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 3e1c843..22afba8 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Jan 04 00:31:07 CST 2017
+#Fri Mar 10 17:10:42 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
diff --git a/library/build.gradle b/library/build.gradle
index 62bd761..8055fb2 100644
--- a/library/build.gradle
+++ b/library/build.gradle
@@ -22,4 +22,5 @@ dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
testCompile 'junit:junit:4.12'
compile 'com.android.support:support-compat:25.1.0'
+ compile 'com.android.support:appcompat-v7:25.1.0'
}
diff --git a/library/src/main/java/com/aspsine/swipetoloadlayout/SwipeToLoadLayout.java b/library/src/main/java/com/aspsine/swipetoloadlayout/SwipeToLoadLayout.java
index 6802d40..a2f0c6e 100644
--- a/library/src/main/java/com/aspsine/swipetoloadlayout/SwipeToLoadLayout.java
+++ b/library/src/main/java/com/aspsine/swipetoloadlayout/SwipeToLoadLayout.java
@@ -4,6 +4,7 @@
import android.content.res.TypedArray;
import android.support.v4.view.MotionEventCompat;
import android.support.v4.view.ViewCompat;
+import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -61,9 +62,9 @@ public class SwipeToLoadLayout extends ViewGroup {
private View mFooterView;
- private int mHeaderHeight;
+ private int mHeaderLength;
- private int mFooterHeight;
+ private int mFooterLength;
private boolean mHasHeaderView;
@@ -235,6 +236,11 @@ public class SwipeToLoadLayout extends ViewGroup {
*/
private int mDefaultToLoadingMoreScrollingDuration = DEFAULT_DEFAULT_TO_LOADING_MORE_SCROLLING_DURATION;
+ /**
+ * true : the target is vertically scroll
+ */
+ private boolean mIsVertically = true;
+
/**
* the style enum
*/
@@ -313,7 +319,8 @@ public SwipeToLoadLayout(Context context, AttributeSet attrs, int defStyleAttr)
} else if (attr == R.styleable.SwipeToLoadLayout_default_to_loading_more_scrolling_duration) {
setDefaultToLoadingMoreScrollingDuration(a.getInt(attr, DEFAULT_DEFAULT_TO_LOADING_MORE_SCROLLING_DURATION));
-
+ } else if (attr == R.styleable.SwipeToLoadLayout_swipe_vertically) {
+ mIsVertically = a.getBoolean(attr, mIsVertically);
}
}
} finally {
@@ -358,9 +365,9 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View headerView = mHeaderView;
measureChildWithMargins(headerView, widthMeasureSpec, 0, heightMeasureSpec, 0);
MarginLayoutParams lp = ((MarginLayoutParams) headerView.getLayoutParams());
- mHeaderHeight = headerView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
- if (mRefreshTriggerOffset < mHeaderHeight) {
- mRefreshTriggerOffset = mHeaderHeight;
+ mHeaderLength = mIsVertically ? (headerView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin) : (headerView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
+ if (mRefreshTriggerOffset < mHeaderLength) {
+ mRefreshTriggerOffset = mHeaderLength;
}
}
// target
@@ -373,16 +380,20 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final View footerView = mFooterView;
measureChildWithMargins(footerView, widthMeasureSpec, 0, heightMeasureSpec, 0);
MarginLayoutParams lp = ((MarginLayoutParams) footerView.getLayoutParams());
- mFooterHeight = footerView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
- if (mLoadMoreTriggerOffset < mFooterHeight) {
- mLoadMoreTriggerOffset = mFooterHeight;
+ mFooterLength = mIsVertically ? (footerView.getMeasuredHeight() + lp.topMargin + lp.bottomMargin) : (footerView.getMeasuredWidth() + lp.leftMargin + lp.rightMargin);
+ if (mLoadMoreTriggerOffset < mFooterLength) {
+ mLoadMoreTriggerOffset = mFooterLength;
}
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
- layoutChildren();
+ if (mIsVertically) {
+ layoutVerChildren();
+ }else {
+ layoutHorChildren();
+ }
mHasHeaderView = (mHeaderView != null);
mHasFooterView = (mFooterView != null);
@@ -498,8 +509,15 @@ public boolean onInterceptTouchEvent(MotionEvent event) {
}
float y = getMotionEventY(event, mActivePointerId);
float x = getMotionEventX(event, mActivePointerId);
- final float yInitDiff = y - mInitDownY;
- final float xInitDiff = x - mInitDownX;
+ final float yInitDiff;
+ final float xInitDiff;
+ if (mIsVertically) {
+ yInitDiff = y - mInitDownY;
+ xInitDiff = x - mInitDownX;
+ } else {
+ yInitDiff = x - mInitDownX;
+ xInitDiff = y - mInitDownY;
+ }
mLastY = y;
mLastX = x;
boolean moved = Math.abs(yInitDiff) > Math.abs(xInitDiff)
@@ -544,8 +562,15 @@ public boolean onTouchEvent(MotionEvent event) {
final float y = getMotionEventY(event, mActivePointerId);
final float x = getMotionEventX(event, mActivePointerId);
- final float yDiff = y - mLastY;
- final float xDiff = x - mLastX;
+ final float yDiff;
+ final float xDiff;
+ if (mIsVertically) {
+ yDiff = y - mLastY;
+ xDiff = x - mLastX;
+ } else {
+ yDiff = x - mLastX;
+ xDiff = y - mLastY;
+ }
mLastY = y;
mLastX = x;
@@ -738,6 +763,11 @@ public void setSwipeStyle(int style) {
requestLayout();
}
+ public void setVertically(boolean vertically) {
+ mIsVertically = vertically;
+ requestLayout();
+ }
+
/**
* set how hard to drag. bigger easier, smaller harder;
*
@@ -749,9 +779,9 @@ public void setDragRatio(float dragRatio) {
/**
* set the value of {@link #mRefreshTriggerOffset}.
- * Default value is the refresh header view height {@link #mHeaderHeight}
- * If the offset you set is smaller than {@link #mHeaderHeight} or not set,
- * using {@link #mHeaderHeight} as default value
+ * Default value is the refresh header view height {@link #mHeaderLength}
+ * If the offset you set is smaller than {@link #mHeaderLength} or not set,
+ * using {@link #mHeaderLength} as default value
*
* @param offset
*/
@@ -761,9 +791,9 @@ public void setRefreshTriggerOffset(int offset) {
/**
* set the value of {@link #mLoadMoreTriggerOffset}.
- * Default value is the load more footer view height {@link #mFooterHeight}
- * If the offset you set is smaller than {@link #mFooterHeight} or not set,
- * using {@link #mFooterHeight} as default value
+ * Default value is the load more footer view height {@link #mFooterLength}
+ * If the offset you set is smaller than {@link #mFooterLength} or not set,
+ * using {@link #mFooterLength} as default value
*
* @param offset
*/
@@ -964,17 +994,34 @@ public void run() {
* scroll up. Override this if the child view is a custom view.
*/
protected boolean canChildScrollUp() {
- if (android.os.Build.VERSION.SDK_INT < 14) {
+ if (mTargetView instanceof ViewPager) {
+ ViewPager pager = (ViewPager) mTargetView;
+ return pager.getCurrentItem() > 0;
+ } else if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTargetView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTargetView;
- return absListView.getChildCount() > 0
- && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
- .getTop() < absListView.getPaddingTop());
+ if (mIsVertically) {
+ return absListView.getChildCount() > 0
+ && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
+ .getTop() < absListView.getPaddingTop());
+ } else {
+ return absListView.getChildCount() > 0
+ && (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
+ .getLeft() < absListView.getPaddingLeft());
+ }
} else {
- return ViewCompat.canScrollVertically(mTargetView, -1) || mTargetView.getScrollY() > 0;
+ if (mIsVertically) {
+ return ViewCompat.canScrollVertically(mTargetView, -1) || mTargetView.getScrollY() > 0;
+ } else {
+ return ViewCompat.canScrollHorizontally(mTargetView, -1) || mTargetView.getScrollX() > 0;
+ }
}
} else {
- return ViewCompat.canScrollVertically(mTargetView, -1);
+ if (mIsVertically) {
+ return ViewCompat.canScrollVertically(mTargetView, -1);
+ } else {
+ return ViewCompat.canScrollHorizontally(mTargetView, -1);
+ }
}
}
@@ -985,24 +1032,41 @@ protected boolean canChildScrollUp() {
* @return
*/
protected boolean canChildScrollDown() {
- if (android.os.Build.VERSION.SDK_INT < 14) {
+ if (mTargetView instanceof ViewPager) {
+ ViewPager pager = (ViewPager) mTargetView;
+ return pager.getCurrentItem() < pager.getAdapter().getCount() - 1;
+ } else if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTargetView instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTargetView;
- return absListView.getChildCount() > 0
- && (absListView.getLastVisiblePosition() < absListView.getChildCount() - 1
- || absListView.getChildAt(absListView.getChildCount() - 1).getBottom() > absListView.getPaddingBottom());
+ if (mIsVertically) {
+ return absListView.getChildCount() > 0
+ && (absListView.getLastVisiblePosition() < absListView.getChildCount() - 1
+ || absListView.getChildAt(absListView.getChildCount() - 1).getBottom() > absListView.getPaddingBottom());
+ } else {
+ return absListView.getChildCount() > 0
+ && (absListView.getLastVisiblePosition() < absListView.getChildCount() - 1
+ || absListView.getChildAt(absListView.getChildCount() - 1).getRight() > absListView.getPaddingRight());
+ }
} else {
- return ViewCompat.canScrollVertically(mTargetView, 1) || mTargetView.getScrollY() < 0;
+ if (mIsVertically) {
+ return ViewCompat.canScrollVertically(mTargetView, 1) || mTargetView.getScrollY() < 0;
+ } else {
+ return ViewCompat.canScrollHorizontally(mTargetView, 1) || mTargetView.getScrollX() < 0;
+ }
}
} else {
- return ViewCompat.canScrollVertically(mTargetView, 1);
+ if (mIsVertically) {
+ return ViewCompat.canScrollVertically(mTargetView, 1);
+ } else {
+ return ViewCompat.canScrollHorizontally(mTargetView, 1);
+ }
}
}
/**
* @see #onLayout(boolean, int, int, int, int)
*/
- private void layoutChildren() {
+ private void layoutVerChildren() {
final int width = getMeasuredWidth();
final int height = getMeasuredHeight();
@@ -1024,11 +1088,11 @@ private void layoutChildren() {
switch (mStyle) {
case STYLE.CLASSIC:
// classic
- headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
+ headerTop = paddingTop + lp.topMargin - mHeaderLength + mHeaderOffset;
break;
case STYLE.ABOVE:
// classic
- headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
+ headerTop = paddingTop + lp.topMargin - mHeaderLength + mHeaderOffset;
break;
case STYLE.BLEW:
// blew
@@ -1036,11 +1100,11 @@ private void layoutChildren() {
break;
case STYLE.SCALE:
// scale
- headerTop = paddingTop + lp.topMargin - mHeaderHeight / 2 + mHeaderOffset / 2;
+ headerTop = paddingTop + lp.topMargin - mHeaderLength / 2 + mHeaderOffset / 2;
break;
default:
// classic
- headerTop = paddingTop + lp.topMargin - mHeaderHeight + mHeaderOffset;
+ headerTop = paddingTop + lp.topMargin - mHeaderLength + mHeaderOffset;
break;
}
final int headerRight = headerLeft + headerView.getMeasuredWidth();
@@ -1092,11 +1156,11 @@ private void layoutChildren() {
switch (mStyle) {
case STYLE.CLASSIC:
// classic
- footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
+ footerBottom = height - paddingBottom - lp.bottomMargin + mFooterLength + mFooterOffset;
break;
case STYLE.ABOVE:
// classic
- footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
+ footerBottom = height - paddingBottom - lp.bottomMargin + mFooterLength + mFooterOffset;
break;
case STYLE.BLEW:
// blew
@@ -1104,11 +1168,11 @@ private void layoutChildren() {
break;
case STYLE.SCALE:
// scale
- footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight / 2 + mFooterOffset / 2;
+ footerBottom = height - paddingBottom - lp.bottomMargin + mFooterLength / 2 + mFooterOffset / 2;
break;
default:
// classic
- footerBottom = height - paddingBottom - lp.bottomMargin + mFooterHeight + mFooterOffset;
+ footerBottom = height - paddingBottom - lp.bottomMargin + mFooterLength + mFooterOffset;
break;
}
final int footerTop = footerBottom - footerView.getMeasuredHeight();
@@ -1132,24 +1196,169 @@ private void layoutChildren() {
}
}
+ /**
+ * @see #onLayout(boolean, int, int, int, int)
+ */
+ private void layoutHorChildren() {
+ final int width = getMeasuredWidth();
+ final int height = getMeasuredHeight();
+
+ final int paddingLeft = getPaddingLeft();
+ final int paddingTop = getPaddingTop();
+ final int paddingRight = getPaddingRight();
+ final int paddingBottom = getPaddingBottom();
+
+ if (mTargetView == null) {
+ return;
+ }
+
+ // layout header
+ if (mHeaderView != null) {
+ final View headerView = mHeaderView;
+ MarginLayoutParams lp = (MarginLayoutParams) headerView.getLayoutParams();
+ final int headerLeft;
+ final int headerTop = paddingTop + lp.topMargin;
+ switch (mStyle) {
+ case STYLE.CLASSIC:
+ // classic
+ headerLeft = paddingLeft + lp.leftMargin - mHeaderLength + mHeaderOffset;
+ break;
+ case STYLE.ABOVE:
+ // classic
+ headerLeft = paddingLeft + lp.leftMargin - mHeaderLength + mHeaderOffset;
+ break;
+ case STYLE.BLEW:
+ // blew
+ headerLeft = paddingLeft + lp.leftMargin;
+ break;
+ case STYLE.SCALE:
+ // scale
+ headerLeft = paddingLeft + lp.leftMargin - mHeaderLength / 2 + mHeaderOffset / 2;
+ break;
+ default:
+ // classic
+ headerLeft = paddingLeft + lp.leftMargin - mHeaderLength + mHeaderOffset;
+ break;
+ }
+ final int headerRight = headerLeft + headerView.getMeasuredWidth();
+ final int headerBottom = headerTop + headerView.getMeasuredHeight();
+ headerView.layout(headerLeft, headerTop, headerRight, headerBottom);
+ }
+
+
+ // layout target
+ if (mTargetView != null) {
+ final View targetView = mTargetView;
+ MarginLayoutParams lp = (MarginLayoutParams) targetView.getLayoutParams();
+ final int targetLeft;
+ final int targetTop = paddingTop + lp.topMargin;
+
+ switch (mStyle) {
+ case STYLE.CLASSIC:
+ // classic
+ targetLeft = paddingLeft + lp.leftMargin + mTargetOffset;
+ break;
+ case STYLE.ABOVE:
+ // above
+ targetLeft = paddingLeft + lp.leftMargin;
+ break;
+ case STYLE.BLEW:
+ // classic
+ targetLeft = paddingLeft + lp.leftMargin + mTargetOffset;
+ break;
+ case STYLE.SCALE:
+ // classic
+ targetLeft = paddingLeft + lp.leftMargin + mTargetOffset;
+ break;
+ default:
+ // classic
+ targetLeft = paddingLeft + lp.leftMargin + mTargetOffset;
+ break;
+ }
+ final int targetRight = targetLeft + targetView.getMeasuredWidth();
+ final int targetBottom = targetTop + targetView.getMeasuredHeight();
+ targetView.layout(targetLeft, targetTop, targetRight, targetBottom);
+ }
+
+ // layout footer
+ if (mFooterView != null) {
+ final View footerView = mFooterView;
+ MarginLayoutParams lp = (MarginLayoutParams) footerView.getLayoutParams();
+ final int footerRight;
+ final int footerTop = paddingTop + lp.topMargin;
+ switch (mStyle) {
+ case STYLE.CLASSIC:
+ // classic
+ footerRight = width - paddingRight - lp.rightMargin + mHeaderLength + mFooterOffset;
+ break;
+ case STYLE.ABOVE:
+ // classic
+ footerRight = width - paddingRight - lp.rightMargin + mHeaderLength + mFooterOffset;
+ break;
+ case STYLE.BLEW:
+ // blew
+ footerRight = width - paddingRight - lp.rightMargin;
+ break;
+ case STYLE.SCALE:
+ // scale
+ footerRight = width - paddingRight - lp.rightMargin + mHeaderLength / 2 + mFooterOffset / 2;
+ break;
+ default:
+ // classic
+ footerRight = width - paddingRight - lp.rightMargin + mHeaderLength + mFooterOffset;
+ break;
+ }
+ final int footerLeft = footerRight - footerView.getMeasuredWidth();
+ final int footerBottom = footerTop + footerView.getMeasuredHeight();
+
+ footerView.layout(footerLeft, footerTop, footerRight, footerBottom);
+ }
+
+ if (mStyle == STYLE.CLASSIC
+ || mStyle == STYLE.ABOVE) {
+ if (mHeaderView != null) {
+ mHeaderView.bringToFront();
+ }
+ if (mFooterView != null) {
+ mFooterView.bringToFront();
+ }
+ } else if (mStyle == STYLE.BLEW || mStyle == STYLE.SCALE) {
+ if (mTargetView != null) {
+ mTargetView.bringToFront();
+ }
+ }
+ }
+
private void fixCurrentStatusLayout() {
if (STATUS.isRefreshing(mStatus)) {
mTargetOffset = (int) (mRefreshTriggerOffset + 0.5f);
mHeaderOffset = mTargetOffset;
mFooterOffset = 0;
- layoutChildren();
+ if (mIsVertically) {
+ layoutVerChildren();
+ }else {
+ layoutHorChildren();
+ }
invalidate();
} else if (STATUS.isStatusDefault(mStatus)) {
mTargetOffset = 0;
mHeaderOffset = 0;
mFooterOffset = 0;
- layoutChildren();
+ if (mIsVertically) {
+ layoutVerChildren();
+ }else {
+ layoutHorChildren();
+ }
invalidate();
} else if (STATUS.isLoadingMore(mStatus)) {
mTargetOffset = -(int) (mLoadMoreTriggerOffset + 0.5f);
mHeaderOffset = 0;
mFooterOffset = mTargetOffset;
- layoutChildren();
+ if (mIsVertically) {
+ layoutVerChildren();
+ }else {
+ layoutHorChildren();
+ }
invalidate();
}
}
@@ -1231,7 +1440,11 @@ private void updateScroll(final float yScrolled) {
if (mDebug) {
Log.i(TAG, "mTargetOffset = " + mTargetOffset);
}
- layoutChildren();
+ if (mIsVertically) {
+ layoutVerChildren();
+ }else {
+ layoutHorChildren();
+ }
invalidate();
}
@@ -1293,11 +1506,11 @@ private void scrollSwipingToLoadMoreToDefault() {
}
private void scrollReleaseToRefreshToRefreshing() {
- mAutoScroller.autoScroll(mHeaderHeight - mHeaderOffset, mReleaseToRefreshToRefreshingScrollingDuration);
+ mAutoScroller.autoScroll(mHeaderLength - mHeaderOffset, mReleaseToRefreshToRefreshingScrollingDuration);
}
private void scrollReleaseToLoadMoreToLoadingMore() {
- mAutoScroller.autoScroll(-mFooterOffset - mFooterHeight, mReleaseToLoadMoreToLoadingMoreScrollingDuration);
+ mAutoScroller.autoScroll(-mFooterOffset - mFooterLength, mReleaseToLoadMoreToLoadingMoreScrollingDuration);
}
private void scrollRefreshingToDefault() {
@@ -1526,7 +1739,7 @@ private class AutoScroller implements Runnable {
private Scroller mScroller;
- private int mmLastY;
+ private int mmLastPoint;
private boolean mRunning = false;
@@ -1539,13 +1752,13 @@ public AutoScroller() {
@Override
public void run() {
boolean finish = !mScroller.computeScrollOffset() || mScroller.isFinished();
- int currY = mScroller.getCurrY();
- int yDiff = currY - mmLastY;
+ int currPoint = mIsVertically ? mScroller.getCurrY() : mScroller.getCurrX();
+ int diff = currPoint - mmLastPoint;
if (finish) {
finish();
} else {
- mmLastY = currY;
- SwipeToLoadLayout.this.autoScroll(yDiff);
+ mmLastPoint = currPoint;
+ SwipeToLoadLayout.this.autoScroll(diff);
post(this);
}
}
@@ -1554,7 +1767,7 @@ public void run() {
* remove the post callbacks and reset default values
*/
private void finish() {
- mmLastY = 0;
+ mmLastPoint = 0;
mRunning = false;
removeCallbacks(this);
// if abort by user, don't call
@@ -1582,16 +1795,20 @@ public void abortIfRunning() {
* It's just like the yScrolled param in the
* {@link #updateScroll(float yScrolled)}
*
- * @param yScrolled
+ * @param scrolled
* @param duration
*/
- private void autoScroll(int yScrolled, int duration) {
+ private void autoScroll(int scrolled, int duration) {
removeCallbacks(this);
- mmLastY = 0;
+ mmLastPoint = 0;
if (!mScroller.isFinished()) {
mScroller.forceFinished(true);
}
- mScroller.startScroll(0, 0, 0, yScrolled, duration);
+ if (mIsVertically) {
+ mScroller.startScroll(0, 0, 0, scrolled, duration);
+ } else {
+ mScroller.startScroll(0, 0, scrolled, 0, duration);
+ }
post(this);
mRunning = true;
}
diff --git a/library/src/main/res/values/attrs.xml b/library/src/main/res/values/attrs.xml
index bf0a634..82153b2 100644
--- a/library/src/main/res/values/attrs.xml
+++ b/library/src/main/res/values/attrs.xml
@@ -27,5 +27,7 @@
+
-
\ No newline at end of file
+
+
\ No newline at end of file