添加了自定义控件打星星

This commit is contained in:
linglongxin24
2016-06-01 18:50:25 +08:00
parent 359fe60678
commit 52e7d42ebe
17 changed files with 1001 additions and 53 deletions

View File

@@ -1,4 +1,4 @@
package com.kykj.inspection.adapter;
package com.kejiang.yuandl.adapter;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
@@ -18,7 +18,7 @@ public class FragmentTabAdapter implements OnCheckedChangeListener {
private FragmentActivity fragmentActivity; // Fragment所属的Activity
private int fragmentContentId; // Activity中所要被替换的区域的id
private int currentTab =0;// 当前Tab页面索引
private int currentTab = 0;// 当前Tab页面索引
private OnRgsExtraCheckedChangedListener onRgsExtraCheckedChangedListener; // 用于让调用者在切换tab时候增加新的功能
@@ -32,8 +32,8 @@ public class FragmentTabAdapter implements OnCheckedChangeListener {
FragmentTransaction ft = fragmentActivity.getSupportFragmentManager()
.beginTransaction();
ft.add(fragmentContentId, fragments.get(currentTab));
ft.commit();
if(rg!=null){
ft.commitAllowingStateLoss();
if (rg != null) {
rg.setOnCheckedChangeListener(this);
}
@@ -46,18 +46,21 @@ public class FragmentTabAdapter implements OnCheckedChangeListener {
if (rg.getChildAt(i).getId() == checkedId) {
Fragment fragment = fragments.get(i);
FragmentTransaction ft = obtainFragmentTransaction(i);
// getCurrentFragment().onPause(); // 暂停当前tab
// getCurrentFragment().onPause(); // 暂停当前tab
//getCurrentFragment().onStop(); // 暂停当前tab
if (fragment.isAdded()) {
// fragment.onStart(); // 启动目标tab的onStart()
currentTab=i;
fragment.onResume(); // 启动目标tab的onResume()
// fragment.onStart(); // 启动目标tab的onStart()
currentTab = i;
if (!fragment.isResumed()) {
fragment.onResume(); // 启动目标tab的onResume()
}
} else {
ft.add(fragmentContentId, fragment);
}
showTab(i); // 显示目标tab
ft.commit();
ft. commitAllowingStateLoss();
// 如果设置了切换tab额外功能功能接口
if (null != onRgsExtraCheckedChangedListener) {
@@ -85,7 +88,7 @@ public class FragmentTabAdapter implements OnCheckedChangeListener {
} else {
ft.hide(fragment);
}
ft.commit();
ft.commitAllowingStateLoss();
}
currentTab = idx; // 更新目标tab为当前tab
}

View File

@@ -20,6 +20,8 @@ import android.widget.ProgressBar;
import android.widget.RatingBar;
import android.widget.TextView;
import com.zhy.autolayout.utils.AutoUtils;
public class ViewHolder extends RecyclerView.ViewHolder {
private SparseArray<View> mViews;
private int mPosition;
@@ -37,6 +39,7 @@ public class ViewHolder extends RecyclerView.ViewHolder {
mConvertView = itemView;
mPosition = position;
mViews = new SparseArray<View>();
AutoUtils.autoSize(mConvertView);
mConvertView.setTag(this);
}

View File

@@ -12,6 +12,7 @@ import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.FrameLayout;
@@ -240,7 +241,7 @@ public abstract class BaseActivity extends AutoLayoutActivity implements View.On
* 提供是否显示提交按钮
*
* @param title 文字
* @param show true则显示
* @param show true则显示
*/
protected void showForwardView(CharSequence title, boolean show) {
if (mForwardButton != null) {
@@ -609,11 +610,22 @@ public abstract class BaseActivity extends AutoLayoutActivity implements View.On
listView.setEmptyView(emptyView);
}
protected void setEmptyView(ListView listView, String text) {
TextView emptyView = new TextView(context);
emptyView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
emptyView.setText(text);
emptyView.setGravity(Gravity.CENTER);
emptyView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
emptyView.setVisibility(View.GONE);
((ViewGroup) listView.getParent()).addView(emptyView);
listView.setEmptyView(emptyView);
}
@Override
protected void onDestroy() {
super.onDestroy();
mContentLayout.removeAllViews();
mContentLayout=null;
mContentLayout = null;
AppManager.getAppManager().finishActivity(this);
}

View File

@@ -31,6 +31,9 @@ public class AppManager {
return instance;
}
public Stack<Activity> getAllActivitys() {
return activityStack;
}
/**
* 栈中是否为空
*
@@ -69,6 +72,17 @@ public class AppManager {
}
return activityStack.get(activityStack.size() - 1);
}
/**
* 获取前一个activity便于返回
*
* @return
*/
public Activity previousActivity() {
if (activityStack.size() < 2) {
return null;
}
return activityStack.get(activityStack.size() - 2);
}
/**
* 结束当前Activity堆栈中最后一个压入的
@@ -158,6 +172,7 @@ public class AppManager {
}
}
}
/**
* 结束所有Activity保留登录界面
*/
@@ -167,13 +182,14 @@ public class AppManager {
for (int i = 0, size = activityList.size(); i < size; i++) {
Activity activity = activityList.get(i);
if (null != activityList.get(i)) {
if(!activityList.get(i).getClass().getSimpleName().equals("UserSetActivity")) {
if (!activityList.get(i).getClass().getSimpleName().equals("UserSetActivity")) {
activityList.get(i).finish();
activityStack.remove(activity);
}
}
}
}
/**
* 退出应用程序
*/
@@ -182,7 +198,7 @@ public class AppManager {
finishAllActivity();
// MyApplication.getInstance().unregisterReceiver();
/*
* ActivityManager activityMgr= (ActivityManager)
* ActivityManager activityMgr= (ActivityManager)
* context.getSystemService(Context.ACTIVITY_SERVICE);
* activityMgr.restartPackage(context.getPackageName());
*/

View File

@@ -1,6 +1,8 @@
package com.kejiang.yuandl.view;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.KeyEvent;
@@ -52,9 +54,18 @@ public class MyGallery extends Gallery implements OnItemSelectedListener {
private final Timer timer = new Timer();
private final TimerTask task = new TimerTask() {
public void run() {
mHandler.sendEmptyMessage(timerAnimation);
if (autoPlay) {
mHandler.sendEmptyMessage(timerAnimation);
} else {
timer.cancel();
}
}
};
private boolean autoPlay = true;
public void setAutoPlay(boolean autoPlay) {
this.autoPlay = autoPlay;
}
public MyGallery(Context paramContext) {
super(paramContext);
@@ -98,6 +109,7 @@ public class MyGallery extends Gallery implements OnItemSelectedListener {
private int count = 0;
private LinearLayout ll_focus_indicator_container;
public void init(int count, LinearLayout ll_focus_indicator_container) {
this.count = count;
this.ll_focus_indicator_container = ll_focus_indicator_container;
@@ -107,7 +119,7 @@ public class MyGallery extends Gallery implements OnItemSelectedListener {
private void InitFocusIndicatorContainer() {
ll_focus_indicator_container.removeAllViews();
if(count<=1){
if (count <= 1) {
return;
}
for (int i = 0; i < count; i++) {
@@ -116,10 +128,11 @@ public class MyGallery extends Gallery implements OnItemSelectedListener {
ImageView.ScaleType localScaleType = ImageView.ScaleType.FIT_XY;
localImageView.setScaleType(localScaleType);
LinearLayout.LayoutParams localLayoutParams = new LinearLayout.LayoutParams(
24, 24);
155, 11);
localLayoutParams.weight = 1;
localImageView.setLayoutParams(localLayoutParams);
localImageView.setPadding(5, 5, 5, 5);
localImageView.setImageResource(R.drawable.indicator_normal);
localImageView.setPadding(0, 0, 0, 0);
localImageView.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
ll_focus_indicator_container.addView(localImageView);
}
}
@@ -132,25 +145,24 @@ public class MyGallery extends Gallery implements OnItemSelectedListener {
@Override
public void onItemSelected(AdapterView<?> adapterView, View view, int selIndex, long l) {
//修改上一次选中项的背景
if(count==0){
if (count == 0) {
return;
}
selIndex = selIndex %count;
selIndex = selIndex % count;
ImageView preSelImg = (ImageView) ll_focus_indicator_container
.findViewById(preSelImgIndex);
if(preSelImg==null){
if (preSelImg == null) {
return;
}
preSelImg.setImageDrawable(getContext()
.getResources().getDrawable(R.drawable.indicator_normal));
preSelImg.setImageDrawable(new ColorDrawable(Color.TRANSPARENT));
//修改当前选中项的背景
ImageView curSelImg = (ImageView) ll_focus_indicator_container
.findViewById(selIndex);
curSelImg
.setImageDrawable(getContext()
.getResources().getDrawable(
R.drawable.indicator_focus));
R.drawable.dots_focus));
preSelImgIndex = selIndex;
}

View File

@@ -0,0 +1,40 @@
package com.kejiang.yuandl.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
/**
* File_name com.dy.logs.mp.ui.MyGridView
* @author linglongxin24 <br/>
* @date create at 2014-6-6下午2:07:04 <br/>
* @time update at 2014-6-6下午2:07:04
*/
/**
* 自定义gridview解决ListView中嵌套gridview显示不正常的问题1行半
*
* @author wangyx
* @version 1.0.0 2012-9-14
*/
public class MyGridView extends GridView {
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}

View File

@@ -0,0 +1,41 @@
/**
*
*/
package com.kejiang.yuandl.view;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ListView;
/**
* File_name com.dy.logs.mp.ui.MyListView
*
* @author linglongxin24 <br/>
* @date create at 2014-6-6<><36><EFBFBD><EFBFBD>2:09:42 <br/>
* @time update at 2014-6-6<><36><EFBFBD><EFBFBD>2:09:42
*/
public class MyListView extends ListView {
public MyListView(Context context) {
// TODO Auto-generated method stub
super(context);
}
public MyListView(Context context, AttributeSet attrs) {
// TODO Auto-generated method stub
super(context, attrs);
}
public MyListView(Context context, AttributeSet attrs, int defStyle) {
// TODO Auto-generated method stub
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, expandSpec);
}
}

View File

@@ -0,0 +1,226 @@
package com.kejiang.yuandl.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import com.kejiang.yuandl.R;
import com.orhanobut.logger.Logger;
import java.math.BigDecimal;
/**
* Created by hedge_hog on 2015/6/11.
* <p/>
* add halfstar show
* <p/>
* Correction clickEvent from Xml
*/
public class RatingBar extends LinearLayout {
private boolean mClickable;
private int starCount;
private OnRatingChangeListener onRatingChangeListener;
private float starImageSize;
private float starStep;
private Drawable starEmptyDrawable;
private Drawable starFillDrawable;
private Drawable starHalfDrawable;
public void setStarHalfDrawable(Drawable starHalfDrawable) {
this.starHalfDrawable = starHalfDrawable;
}
public void setOnRatingChangeListener(OnRatingChangeListener onRatingChangeListener) {
this.onRatingChangeListener = onRatingChangeListener;
}
public void setmClickable(boolean clickable) {
this.mClickable = clickable;
}
public void setStarFillDrawable(Drawable starFillDrawable) {
this.starFillDrawable = starFillDrawable;
}
public void setStarEmptyDrawable(Drawable starEmptyDrawable) {
this.starEmptyDrawable = starEmptyDrawable;
}
public void setStarImageSize(float starImageSize) {
this.starImageSize = starImageSize;
}
/**
* @param context
* @param attrs
*/
public RatingBar(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(LinearLayout.HORIZONTAL);
TypedArray mTypedArray = context.obtainStyledAttributes(attrs, R.styleable.RatingBar);
starImageSize = mTypedArray.getDimension(R.styleable.RatingBar_starImageSize, 20);
starStep = mTypedArray.getFloat(R.styleable.RatingBar_starStep, 1.0f);
starCount = mTypedArray.getInteger(R.styleable.RatingBar_starCount, 5);
starEmptyDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starEmpty);
starFillDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starFill);
starHalfDrawable = mTypedArray.getDrawable(R.styleable.RatingBar_starHalf);
mClickable = mTypedArray.getBoolean(R.styleable.RatingBar_clickable, true);
for (int i = 0; i < starCount; ++i) {
final ImageView imageView = getStarImageView(context, attrs);
imageView.setImageDrawable(starEmptyDrawable);
imageView.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
if (mClickable) {
//浮点数的整数部分
int fint = (int) starStep;
BigDecimal b1 = new BigDecimal(Float.toString(starStep));
BigDecimal b2 = new BigDecimal(Integer.toString(fint));
//浮点数的小数部分
float fPoint = b1.subtract(b2).floatValue();
if (fPoint == 0) {
fint -= 1;
}
if (indexOfChild(v) > fint) {
setStar(indexOfChild(v) + 0.5f);
} else if (indexOfChild(v) == fint) {
if (imageView.getDrawable().getCurrent().getConstantState().equals(starHalfDrawable.getConstantState())) {
setStar(indexOfChild(v) + 1);
} else {
setStar(indexOfChild(v) + 0.5f);
}
} else {
setStar(indexOfChild(v) + 1);
}
}
}
}
);
addView(imageView);
}
setStar(starStep);
}
/**
* @param context
* @param attrs
* @return
*/
private ImageView getStarImageView(Context context, AttributeSet attrs) {
ImageView imageView = new ImageView(context);
ViewGroup.LayoutParams para = new ViewGroup.LayoutParams(
Math.round(starImageSize),
Math.round(starImageSize)
);
imageView.setLayoutParams(para);
imageView.setPadding(0, 0, 5, 0);
imageView.setImageDrawable(starEmptyDrawable);
imageView.setMaxWidth(10);
imageView.setMaxHeight(10);
return imageView;
}
/**
* setting start
*
* @param rating
*/
public void setStar(float rating) {
if (onRatingChangeListener != null) {
onRatingChangeListener.onRatingChange(rating);
}
this.starStep = rating;
//浮点数的整数部分
int fint = (int) rating;
BigDecimal b1 = new BigDecimal(Float.toString(rating));
BigDecimal b2 = new BigDecimal(Integer.toString(fint));
//浮点数的小数部分
float fPoint = b1.subtract(b2).floatValue();
//drawfullstar
for (int i = 0; i < fint; ++i) {
((ImageView) getChildAt(i)).setImageDrawable(starFillDrawable);
}
for (int i = fint; i < starCount; i++) {
((ImageView) getChildAt(i)).setImageDrawable(starEmptyDrawable);
}
if (fPoint > 0) {
((ImageView) getChildAt(fint)).setImageDrawable(starHalfDrawable);
}
}
// /**
// * setting start
// *
// * @param starCount
// */
//
// public void setStar(float starCount) {
//
// //浮点数的整数部分
// int fint = (int) starCount;
// BigDecimal b1 = new BigDecimal(Float.toString(starCount));
// BigDecimal b2 = new BigDecimal(Integer.toString(fint));
// //浮点数的小数部分
// float fPoint = b1.subtract(b2).floatValue();
// Logger.d("fint=" + fint);
// Logger.d("fPoint=" + fPoint);
//
// starCount = fint > this.starCount ? this.starCount : fint;
// starCount = starCount < 0 ? 0 : starCount;
//
// //drawfullstar
// for (int i = 0; i < starCount; ++i) {
// ((ImageView) getChildAt(i)).setImageDrawable(starFillDrawable);
// }
//
// //drawhalfstar
// if (fPoint > 0) {
// ((ImageView) getChildAt(fint)).setImageDrawable(starHalfDrawable);
//
// //drawemptystar
// for (int i = this.starCount - 1; i >= starCount + 1; --i) {
// ((ImageView) getChildAt(i)).setImageDrawable(starEmptyDrawable);
// }
//
//
// } else {
// //drawemptystar
// for (int i = this.starCount - 1; i >= starCount; --i) {
// ((ImageView) getChildAt(i)).setImageDrawable(starEmptyDrawable);
// }
//
// }
//
//
// }
//
/**
* change stat listener
*/
public interface OnRatingChangeListener {
void onRatingChange(float RatingCount);
}
}

View File

@@ -0,0 +1,32 @@
package com.kejiang.yuandl.view.snapscrollview;
import android.content.Context;
import android.view.View;
public class McoyProductContentPage implements McoySnapPageLayout.McoySnapPage {
private Context context;
private View rootView = null;
public McoyProductContentPage(Context context,View rootView) {
this.context = context;
this.rootView = rootView;
}
@Override
public View getRootView() {
return rootView;
}
@Override
public boolean isAtTop() {
return true;
}
@Override
public boolean isAtBottom() {
return false;
}
}

View File

@@ -0,0 +1,44 @@
package com.kejiang.yuandl.view.snapscrollview;
import android.content.Context;
import android.view.View;
public class McoyProductDetailInfoPage implements McoySnapPageLayout.McoySnapPage{
private Context context;
private View rootView = null;
private McoyScrollView mcoyScrollView = null;
public McoyProductDetailInfoPage (Context context, View rootView,McoyScrollView mcoyScrollView) {
this.context = context;
this.rootView = rootView;
this.mcoyScrollView = mcoyScrollView;
// mcoyScrollView = (McoyScrollView) this.rootView
// .findViewById(R.id.product_scrollview);
}
@Override
public View getRootView() {
return rootView;
}
@Override
public boolean isAtTop() {
return true;
}
@Override
public boolean isAtBottom() {
int scrollY = mcoyScrollView.getScrollY();
int height = mcoyScrollView.getHeight();
int scrollViewMeasuredHeight = mcoyScrollView.getChildAt(0).getMeasuredHeight();
if ((scrollY + height) >= scrollViewMeasuredHeight) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,73 @@
package com.kejiang.yuandl.view.snapscrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
public class McoyScrollView extends ScrollView {
// 滑动距离及坐标
private float xDistance, yDistance, xLast, yLast;
public McoyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
Log.e("mcoy", "McoyScrollView--onInterceptTouchEvent");
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
xDistance = yDistance = 0f;
xLast = ev.getX();
yLast = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
final float curX = ev.getX();
final float curY = ev.getY();
xDistance += Math.abs(curX - xLast);
yDistance += Math.abs(curY - yLast);
xLast = curX;
yLast = curY;
if (xDistance > yDistance) {
return false;
}
}
boolean onIntercept = super.onInterceptTouchEvent(ev);
Log.e("mcoy", "McoyScrollView--onInterceptTouchEvent return " + onIntercept);
return onIntercept;
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean touchEvent = super.onTouchEvent(ev);
Log.e("mcoy", "McoyScrollView--onTouchEvent return " + touchEvent);
return touchEvent;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (onScrollListener != null) {
onScrollListener.onScroll(x, y, oldx, oldy);
}
}
private OnJDScrollListener onScrollListener;
public OnJDScrollListener getOnScrollListener() {
return onScrollListener;
}
public void setOnJDScrollListener(OnJDScrollListener onScrollListener) {
this.onScrollListener = onScrollListener;
}
public interface OnJDScrollListener {
void onScroll(int x, int y, int oldx, int oldy);
}
}

View File

@@ -0,0 +1,452 @@
package com.kejiang.yuandl.view.snapscrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* @author jiangxinxing---mcoy in English
*
* 了解此ViewGroup之前 有两点一定要做到心中有数
* 一个是对Scroller的使用 另一个是对onInterceptTouchEvent和onTouchEvent要做到很熟悉
* 以下几个网站可以做参考用
* http://blog.csdn.net/bigconvience/article/details/26697645
* http://blog.csdn.net/androiddevelop/article/details/8373782
* http://blog.csdn.net/xujainxing/article/details/8985063
*/
public class McoySnapPageLayout extends ViewGroup {
private final String TAG = "McoySnapPageLayout";
private final boolean MCOY_DEBUG = true;
private VelocityTracker mVelocityTracker;
private int mMaximumVelocity;
private static final int SNAP_VELOCITY = 1000;
public static final int FLIP_DIRECTION_CUR = 0;
public static final int FLIP_DIRECTION_UP = -1;
public static final int FLIP_DIRECTION_DOWN = 1;
private int mFlipDrection = FLIP_DIRECTION_CUR;
private int mDataIndex = 0; // 当前View中的数据在总数据所在位置
private int mCurrentScreen = 0;
private int mNextDataIndex = 0;
private float mLastMotionY;
// 记录触摸状态
private final static int TOUCH_STATE_REST = 0;
private final static int TOUCH_STATE_SCROLLING = 1;
private int mTouchState = TOUCH_STATE_REST;
private Scroller mScroller; //mcoy add view滑动的矢量 并没有真正滑动的功能
private McoySnapPage mPageTop, mPageBottom;
private PageSnapedListener mPageSnapedListener;
//这个值表示需要第一页和第二页之间的鸿沟
private int gapBetweenTopAndBottom;
public interface McoySnapPage {
/**
* 返回page根节点
*
* @return
*/
View getRootView();
/**
* 是否滑动到最顶端
* 第二页必须自己实现此方法,来判断是否已经滑动到第二页的顶部
* 并决定是否要继续滑动到第一页
*/
boolean isAtTop();
/**
* 是否滑动到最底部
* 第一页必须自己实现此方法,来判断是否已经滑动到第二页的底部
* 并决定是否要继续滑动到第二页
*/
boolean isAtBottom();
}
public interface PageSnapedListener {
/**
* @mcoy
* 当从某一页滑动到另一页完成时的回调函数
*/
void onSnapedCompleted(int derection);
}
public void setPageSnapListener(PageSnapedListener listener){
mPageSnapedListener = listener;
}
public McoySnapPageLayout(Context context, AttributeSet att) {
this(context, att, 0);
}
public McoySnapPageLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initViews();
}
private void initViews() {
mScroller = new Scroller(getContext());
gapBetweenTopAndBottom = ViewConfiguration.get(getContext()).getScaledTouchSlop();
mMaximumVelocity = ViewConfiguration.get(getContext()).getScaledMaximumFlingVelocity();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// The children are given the same width and height as the workspace
final int count = getChildCount();
for (int i = 0; i < count; i++) {
try {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
protected void onLayout(boolean arg0, int arg1, int arg2, int arg3, int arg4) {
int childTop = 0;
int count = getChildCount();
// DLog.i(TAG, "onLayout mDataIndex = " + mDataIndex);
// 设置布局,将子视图顺序竖屏排列
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != View.GONE) {
final int childWidth = child.getMeasuredWidth();
final int childHeight = child.getMeasuredHeight();
childTop = childHeight * i;
child.layout(0, childTop, childWidth,
childTop + childHeight);
}
}
if(count > 0){
snapToScreen(mDataIndex);
}
}
/**
* 设置上下页面
* @param pageTop
* @param pageBottom
*/
public void setSnapPages(McoySnapPage pageTop, McoySnapPage pageBottom) {
mPageTop = pageTop;
mPageBottom = pageBottom;
addPagesAndRefresh();
}
private void addPagesAndRefresh() {
// 设置页面id
mPageTop.getRootView().setId(0);
mPageBottom.getRootView().setId(1);
addView(mPageTop.getRootView());
addView(mPageBottom.getRootView());
postInvalidate();
}
/**
* @mcoy add
* computeScroll方法会调用postInvalidate()方法, 而postInvalidate()方法中系统
* 又会调用computeScroll方法 因此会一直在循环互相调用, 循环的终结点是在computeScrollOffset()
* 当computeScrollOffset这个方法返回false时说明已经结束滚动。
*
* 重要真正的实现此view的滚动是调用scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
*/
@Override
public void computeScroll() {
//先判断mScroller滚动是否完成
if (mScroller.computeScrollOffset()) {
if (mScroller.getCurrY() == (mScroller.getFinalY())) {
if (mNextDataIndex > mDataIndex) {
mFlipDrection = FLIP_DIRECTION_DOWN;
makePageToNext(mNextDataIndex);
} else if (mNextDataIndex < mDataIndex) {
mFlipDrection = FLIP_DIRECTION_UP;
makePageToPrev(mNextDataIndex);
}else{
mFlipDrection = FLIP_DIRECTION_CUR;
}
if(mPageSnapedListener != null){
mPageSnapedListener.onSnapedCompleted(mFlipDrection);
}
}
//这里调用View的scrollTo()完成实际的滚动
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
//必须调用该方法,否则不一定能看到滚动效果
postInvalidate();
}
}
private void makePageToNext(int dataIndex) {
mDataIndex = dataIndex;
mCurrentScreen = getCurrentScreen();
}
private void makePageToPrev(int dataIndex) {
mDataIndex = dataIndex;
mCurrentScreen = getCurrentScreen();
}
public int getCurrentScreen() {
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i).getId() == mDataIndex) {
return i;
}
}
return mCurrentScreen;
}
public View getCurrentView() {
for (int i = 0; i < getChildCount(); i++) {
if (getChildAt(i).getId() == mDataIndex) {
return getChildAt(i);
}
}
return null;
}
/*
* (non-Javadoc)
*
* @see
* android.view.ViewGroup#onInterceptTouchEvent(android.view.MotionEvent)
* 重写了父类的onInterceptTouchEvent()主要功能是在onTouchEvent()方法之前处理
* touch事件。包括down、up、move事件。
* 当onInterceptTouchEvent()返回true时进入onTouchEvent()。
*/
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
if ((action == MotionEvent.ACTION_MOVE)
&& (mTouchState != TOUCH_STATE_REST)) {
return true;
}
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_MOVE:
// 记录y与mLastMotionY差值的绝对值。
// yDiff大于gapBetweenTopAndBottom时就认为界面拖动了足够大的距离屏幕就可以移动了。
final int yDiff = (int)(y - mLastMotionY);
boolean yMoved = Math.abs(yDiff) > gapBetweenTopAndBottom;
if (yMoved) {
if(MCOY_DEBUG) {
Log.e(TAG, "yDiff is " + yDiff);
Log.e(TAG, "mPageTop.isFlipToBottom() is " + mPageTop.isAtBottom());
Log.e(TAG, "mCurrentScreen is " + mCurrentScreen);
Log.e(TAG, "mPageBottom.isFlipToTop() is " + mPageBottom.isAtTop());
}
if(yDiff < 0 && mPageTop.isAtBottom() && mCurrentScreen == 0
|| yDiff > 0 && mPageBottom.isAtTop() && mCurrentScreen == 1){
Log.e("mcoy", "121212121212121212121212");
mTouchState = TOUCH_STATE_SCROLLING;
}
}
break;
case MotionEvent.ACTION_DOWN:
// Remember location of down touch
mLastMotionY = y;
Log.e("mcoy", "mScroller.isFinished() is " + mScroller.isFinished());
mTouchState = mScroller.isFinished() ? TOUCH_STATE_REST
: TOUCH_STATE_SCROLLING;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// Release the drag
mTouchState = TOUCH_STATE_REST;
break;
}
boolean intercept = mTouchState != TOUCH_STATE_REST;
Log.e("mcoy", "McoySnapPageLayout---onInterceptTouchEvent return " + intercept);
return intercept;
}
/*
* (non-Javadoc)
*
* @see android.view.View#onTouchEvent(android.view.MotionEvent)
* 主要功能是处理onInterceptTouchEvent()返回值为true时传递过来的touch事件
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
Log.e("mcoy", "onTouchEvent--" + System.currentTimeMillis());
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(ev);
final int action = ev.getAction();
final float x = ev.getX();
final float y = ev.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
break;
case MotionEvent.ACTION_MOVE:
if(mTouchState != TOUCH_STATE_SCROLLING){
// 记录y与mLastMotionY差值的绝对值。
// yDiff大于gapBetweenTopAndBottom时就认为界面拖动了足够大的距离屏幕就可以移动了。
final int yDiff = (int) Math.abs(y - mLastMotionY);
boolean yMoved = yDiff > gapBetweenTopAndBottom;
if (yMoved) {
mTouchState = TOUCH_STATE_SCROLLING;
}
}
// 手指拖动屏幕的处理
if ((mTouchState == TOUCH_STATE_SCROLLING)) {
// Scroll to follow the motion event
final int deltaY = (int) (mLastMotionY - y);
mLastMotionY = y;
final int scrollY = getScrollY();
if(mCurrentScreen == 0){//显示第一页,只能上拉时使用
if(mPageTop != null && mPageTop.isAtBottom()){
scrollBy(0, Math.max(-1 * scrollY, deltaY));
}
}else{
if(mPageBottom != null && mPageBottom.isAtTop()){
scrollBy(0, deltaY);
}
}
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
// 弹起手指后,切换屏幕的处理
if (mTouchState == TOUCH_STATE_SCROLLING) {
final VelocityTracker velocityTracker = mVelocityTracker;
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int velocityY = (int) velocityTracker.getYVelocity();
if (Math.abs(velocityY) > SNAP_VELOCITY) {
if( velocityY > 0 && mCurrentScreen == 1 && mPageBottom.isAtTop()){
snapToScreen(mDataIndex-1);
}else if(velocityY < 0 && mCurrentScreen == 0){
snapToScreen(mDataIndex+1);
}else{
snapToScreen(mDataIndex);
}
} else {
snapToDestination();
}
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}else{
}
mTouchState = TOUCH_STATE_REST;
break;
default:
break;
}
return true;
}
private void clearOnTouchEvents(){
mTouchState = TOUCH_STATE_REST;
if (mVelocityTracker != null) {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
}
private void snapToDestination() {
// 计算应该去哪个屏
final int flipHeight = getHeight() / 8;
int whichScreen = -1;
final int topEdge = getCurrentView().getTop();
if(topEdge < getScrollY() && (getScrollY()-topEdge) >= flipHeight && mCurrentScreen == 0){
//向下滑动
whichScreen = mDataIndex + 1;
}else if(topEdge > getScrollY() && (topEdge - getScrollY()) >= flipHeight && mCurrentScreen == 1){
//向上滑动
whichScreen = mDataIndex - 1;
}else{
whichScreen = mDataIndex;
}
Log.e(TAG, "snapToDestination mDataIndex = " + mDataIndex);
Log.e(TAG, "snapToDestination whichScreen = " + whichScreen);
snapToScreen(whichScreen);
}
private void snapToScreen(int dataIndex) {
if (!mScroller.isFinished())
return;
final int direction = dataIndex - mDataIndex;
mNextDataIndex = dataIndex;
boolean changingScreens = dataIndex != mDataIndex;
View focusedChild = getFocusedChild();
if (focusedChild != null && changingScreens) {
focusedChild.clearFocus();
}
//在这里判断是否已到目标位置~
int newY = 0;
switch (direction) {
case 1: //需要滑动到第二页
Log.e(TAG, "the direction is 1");
newY = getCurrentView().getBottom(); // 最终停留的位置
break;
case -1: //需要滑动到第一页
Log.e(TAG, "the direction is -1");
Log.e(TAG, "getCurrentView().getTop() is "
+ getCurrentView().getTop() + " getHeight() is "
+ getHeight());
newY = getCurrentView().getTop() - getHeight(); // 最终停留的位置
break;
case 0: //滑动距离不够, 因此不造成换页,回到滑动之前的位置
Log.e(TAG, "the direction is 0");
newY = getCurrentView().getTop(); //第一页的top是0 第二页的top应该是第一页的高度
break;
default:
break;
}
final int cy = getScrollY(); // 启动的位置
Log.e(TAG, "the newY is " + newY + " cy is " + cy);
final int delta = newY - cy; // 滑动的距离,正值是往左滑<—,负值是往右滑—>
mScroller.startScroll(0, cy, 0, delta, Math.abs(delta));
invalidate();
}
public void snapToPrev(){
if(mCurrentScreen == 1){
snapToScreen(0);
}
}
public void snapToNext(){
if(mCurrentScreen == 0){
snapToScreen(1);
}
}
public void snapToCurrent(){
snapToScreen(mCurrentScreen);
clearOnTouchEvents();
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -12,6 +12,7 @@
<include layout="@layout/public_titlebar" />
<FrameLayout
android:background="#eeeeee"
android:id="@+id/layout_content"
android:layout_width="match_parent"
android:layout_height="match_parent"

View File

@@ -1,61 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_titlebar"
android:orientation="horizontal"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="152px"
android:background="#af895b">
android:layout_height="160px"
android:background="#FFFFFF"
android:fitsSystemWindows="true"
android:orientation="horizontal">
<ImageView
android:id="@+id/button_backward"
android:layout_width="100px"
android:layout_height="72px"
android:drawablePadding="6px"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:ellipsize="end"
android:layout_marginLeft="20px"
android:src="@drawable/arrow_back"
android:paddingLeft="33px"
android:paddingRight="33px"
android:paddingTop="48px"
android:paddingBottom="48px"
android:gravity="center"
android:onClick="onBackward"
android:paddingLeft="10px"
android:paddingRight="10px"
android:scaleType="centerCrop"
android:singleLine="true"
android:textColor="#ffffffff"
android:textSize="52px"
android:src="@drawable/arrow_back_red"
android:visibility="visible" />
<TextView
android:id="@+id/text_title"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="marquee"
android:gravity="center_horizontal|center"
android:singleLine="true"
android:text="标题栏"
android:layout_weight="1"
android:textColor="#ffffffff"
android:textSize="62px" />
android:textColor="#000000"
android:textSize="58px" />
<TextView
android:id="@+id/button_forward"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:paddingLeft="10px"
android:paddingRight="40px"
android:drawablePadding="6px"
android:ellipsize="end"
android:layout_gravity="center"
android:gravity="center"
android:onClick="onForward"
android:minEms="3"
android:paddingLeft="30px"
android:paddingRight="33px"
android:singleLine="true"
android:maxEms="4"
android:minWidth="100px"
android:text="提交"
android:textColor="#ffffffff"
android:textSize="48px"
android:textColor="#000000"
android:textSize="50px"
android:visibility="invisible" />
</LinearLayout>