核心类
public class ModeSwitchView extends LinearLayout implements View.OnClickListener {
private ModeScroller mCameraScroller;
private TextView document;
private TextView idcard;
private TextView whiteboard;
private TextView paperwork;
public static final int MODE_DOCUMENT = 0;
public static final int MODE_IDCARD = 1;
public static final int MODE_WHITEBOARD = 2;
public static final int MODE_PAPERWORK = 3;
private List<Integer> mModeList = new ArrayList<>();
private int mCurrentSelectedIndex = 0;
public void setCurrentSelectedIndex(int index) {
mCurrentSelectedIndex = index;
}
public int getCurrentSelectedIndex() {
return mCurrentSelectedIndex;
}
private OnStateChangeListener mListener;
public interface OnStateChangeListener {
void onStateChange(int state);
}
public void setOnStateChangeListener(OnStateChangeListener mListener) {
this.mListener = mListener;
}
public ModeSwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
mModeList.add(MODE_DOCUMENT);
mModeList.add(MODE_IDCARD);
mModeList.add(MODE_WHITEBOARD);
mModeList.add(MODE_PAPERWORK);
LayoutInflater.from(context).inflate(R.layout.argus_mode_scroller_layout, this, true);
mCameraScroller = (ModeScroller) findViewById(R.id.camera_scroller);
mCameraScroller.setCallback(new ModeScroller.Callback() {
@Override
public int getSelectedIndex() {
return getCurrentSelectedIndex();
}
});
document = (TextView) mCameraScroller.findViewById(R.id.document);
idcard = (TextView) mCameraScroller.findViewById(R.id.idcard);
whiteboard = (TextView) mCameraScroller.findViewById(R.id.whiteboard);
paperwork = (TextView) mCameraScroller.findViewById(R.id.paperwork);
document.setOnClickListener(this);
idcard.setOnClickListener(this);
whiteboard.setOnClickListener(this);
paperwork.setOnClickListener(this);
}
public void moveLeft() {
if (getCurrentSelectedIndex() <= 0) {
return;
}
mCameraScroller.leftIndex = getCurrentSelectedIndex() - 1;
mCameraScroller.rightIndex = getCurrentSelectedIndex();
int dx = Math.round((mCameraScroller.getChildAt(mCameraScroller.leftIndex).getWidth() + mCameraScroller.getChildAt(mCameraScroller.rightIndex).getWidth()) / 2.0F);
if (!mCameraScroller.mScroller.isFinished()) {
return;
}
mCameraScroller.mScroller.startScroll(mCameraScroller.getScrollX(), 0, -dx, 0, mCameraScroller.duration);
mCameraScroller.scrollToNext(mCameraScroller.rightIndex, mCameraScroller.leftIndex);
setCurrentSelectedIndex(getCurrentSelectedIndex() - 1);
mCameraScroller.invalidate();
notifyUI(getCurrentSelectedIndex());
}
public void moveRight() {
if (getCurrentSelectedIndex() >= mModeList.size() - 1) {
return;
}
mCameraScroller.leftIndex = getCurrentSelectedIndex();
mCameraScroller.rightIndex = getCurrentSelectedIndex() + 1;
int dx = Math.round((mCameraScroller.getChildAt(mCameraScroller.leftIndex).getWidth() + mCameraScroller.getChildAt(mCameraScroller.rightIndex).getWidth()) / 2.0F);
if (!mCameraScroller.mScroller.isFinished()) {
return;
}
mCameraScroller.mScroller.startScroll(mCameraScroller.getScrollX(), 0, dx, 0, mCameraScroller.duration);
mCameraScroller.scrollToNext(mCameraScroller.leftIndex, mCameraScroller.rightIndex);
setCurrentSelectedIndex(getCurrentSelectedIndex() + 1);
mCameraScroller.invalidate();
notifyUI(getCurrentSelectedIndex());
}
public void moveTo(int index) {
int selectedIndex = getCurrentSelectedIndex();
View selectView = mCameraScroller.getChildAt(selectedIndex);
View dstView = mCameraScroller.getChildAt(index);
int dx = Math.abs((int) ((selectView.getRight() - selectView.getWidth() / 2f) - (dstView.getRight() - dstView.getWidth() / 2f)));
if (index < selectedIndex) {
dx = -dx;
}
if (!mCameraScroller.mScroller.isFinished()) {
return;
}
mCameraScroller.mScroller.startScroll(mCameraScroller.getScrollX(), 0, dx, 0, mCameraScroller.duration);
mCameraScroller.scrollToNext(selectedIndex, index);
setCurrentSelectedIndex(index);
mCameraScroller.invalidate();
notifyUI(index);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.document:
moveTo(MODE_DOCUMENT);
break;
case R.id.idcard:
moveTo(MODE_IDCARD);
break;
case R.id.whiteboard:
moveTo(MODE_WHITEBOARD);
break;
case R.id.paperwork:
moveTo(MODE_PAPERWORK);
break;
}
}
public void setCurrentMode(int index) {
if (index > mModeList.size() - 1 || index < 0) {
return;
}
moveTo(index);
}
private void notifyUI(int index) {
if (mListener != null) {
mListener.onStateChange(index);
}
}
private boolean mScrolling;
private float touchDownX;
private float touchDownY;
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDownX = event.getX();
touchDownY = event.getY();
mScrolling = false;
break;
case MotionEvent.ACTION_MOVE:
int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
if (Math.abs(touchDownX - event.getX()) >= slop || Math.abs(touchDownY - event.getY()) >= slop) {
mScrolling = true;
} else {
mScrolling = false;
}
break;
case MotionEvent.ACTION_UP:
mScrolling = false;
break;
}
return mScrolling;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_UP:
if (this.getVisibility() == View.VISIBLE) {
int deltaX = (int) (event.getX() - touchDownX);
int deltaY = (int) (event.getY() - touchDownY);
int slop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
if (Math.abs(deltaX) > slop) {
// swipe left
if (deltaX < -Math.abs(deltaY) * 2) {
moveRight();
}
// swipe right
if (deltaX >= Math.abs(deltaY) * 2) {
moveLeft();
}
}
}
break;
}
return super.onTouchEvent(event);
}
}
public class ModeScroller extends ViewGroup {
public Scroller mScroller;
public int leftIndex;
public int rightIndex;
public int duration = 250;
public ModeScroller(Context context, AttributeSet attrs) {
super(context, attrs);
mScroller = new Scroller(context);
}
public interface Callback {
int getSelectedIndex();
}
private Callback mCallback;
public void setCallback(Callback callback) {
mCallback = callback;
}
public final void scrollToNext(int preIndex, int nextIndex) {
TextView selectedText = (TextView) getChildAt(preIndex);
if (selectedText != null) {
selectedText.setTextColor(getResources().getColor(android.R.color.white));
}
selectedText = (TextView) getChildAt(nextIndex);
if (selectedText != null) {
selectedText.setTextColor(getResources().getColor(R.color.chosen_color_yellow));
}
}
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
invalidate();
}
super.computeScroll();
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildren(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
}
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
int cCount = getChildCount();
int selectedMode = mCallback.getSelectedIndex();
Log.d("wyl", "selectedMode = " + selectedMode);
int widthOffset = 0;
for (int i = 0; i < cCount; i++) {
View childView = getChildAt(i);
if (i < selectedMode) {
widthOffset += childView.getMeasuredWidth();
}
}
int childLeft = 0;
int childRight = 0;
for (int i = 0; i < cCount; i++) {
View childView = getChildAt(i);
if (i != 0) {
View preView = getChildAt(i - 1);
childLeft = preView.getRight();
childRight = childLeft + childView.getMeasuredWidth();
} else {
childLeft = (getWidth() - getChildAt(selectedMode).getMeasuredWidth()) / 2 - widthOffset + mScroller.getFinalX();
childRight = childLeft + childView.getMeasuredWidth();
}
childView.layout(childLeft, top, childRight, bottom);
}
TextView indexText = (TextView) getChildAt(selectedMode);
indexText.setTextColor(getResources().getColor(R.color.chosen_color_yellow));
}
}
布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="3.0dip"
android:background="@drawable/camera_mode_index_icon_point" />
<com.xxx.xxx.ModeScroller
android:id="@+id/camera_scroller"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:layout_marginTop="-3dp">
<TextView
android:id="@+id/document"
style="@style/ModeScrollerBar"
android:text="@string/argus_text_document" />
<TextView
android:id="@+id/idcard"
style="@style/ModeScrollerBar"
android:text="@string/argus_text_idcard" />
<TextView
android:id="@+id/whiteboard"
style="@style/ModeScrollerBar"
android:text="@string/argus_text_whiteboard" />
<TextView
android:id="@+id/paperwork"
style="@style/ModeScrollerBar"
android:text="@string/argus_text_paperwork" />
</com.xxx.xxx.ModeScroller>
</LinearLayout>
style
<style name="ModeScrollerBar">
<item name="android:textSize">13sp</item>
<item name="android:textColor">@android:color/white</item>
<item name="android:gravity">center</item>
<item name="android:paddingLeft">10dp</item>
<item name="android:paddingRight">10dp</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
</style>