红色为关键代码。
1,textview设置:
<TextView
android:id="@+id/tvAutoScroll"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="1222222222222222222233333333335566"
android:singleLine="true"
android:scrollHorizontally="true"
android:ellipsize="marquee"
android:marqueeRepeatLimit="marquee_forever"
android:layout_alignParentTop="true"
/>
2,代码中触发滚动:
tvAutoScroll = (TextView) findViewById(R.id.tvAutoScroll);
tvAutoScroll.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
tvAutoScroll.setSelected(true);
}
});
二,一个简单的TabGroup控件,效果类似微信底部的tab。
package com.commonlib.ui;
import java.util.List;
import java.util.Locale;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class TabGroup extends HorizontalScrollView {
private LinearLayout.LayoutParams defaultTabLayoutParams;
private LinearLayout.LayoutParams expandedTabLayoutParams;
private LinearLayout tabsContainer;
private int tabCount;
private int currentPosition = -1;
private float currentPositionOffset = 0f;
private boolean shouldExpand = true;
private int scrollOffset = 52;
private int lastScrollX = 0;
private Locale locale;
private Paint rectPaint;
public TabGroup(Context context) {
this(context, null);
}
public TabGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TabGroup(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
rectPaint = new Paint();
rectPaint.setAntiAlias(true);
rectPaint.setStyle(Style.FILL);
setFillViewport(true);
setWillNotDraw(false);
tabsContainer = new LinearLayout(context);
tabsContainer.setOrientation(LinearLayout.HORIZONTAL);
tabsContainer.setLayoutParams(new LayoutParams(
LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
addView(tabsContainer);
DisplayMetrics dm = getResources().getDisplayMetrics();
/**
* convert dip to pix.default.
*/
scrollOffset = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, scrollOffset, dm);
defaultTabLayoutParams = new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
defaultTabLayoutParams.gravity = Gravity.CENTER_VERTICAL;
//
expandedTabLayoutParams = new LinearLayout.LayoutParams(0,
LayoutParams.MATCH_PARENT, 1.0f);
expandedTabLayoutParams.gravity = Gravity.CENTER_VERTICAL;
if (locale == null) {
locale = getResources().getConfiguration().locale;
}
}
public static interface OnTabItemClickListener {
void OnTabItemClick(int index);
}
private OnTabItemClickListener mOnTabItemClickListener;
private int indicatorColor = Color.BLACK;
private int indicatorHeight = 10;
private boolean isShowIndicator = false;
private int underlineHeight = 5;
public int getUnderlineHeight() {
return underlineHeight;
}
public void setUnderlineHeight(int underlineHeight) {
this.underlineHeight = underlineHeight;
invalidate();
}
public int getIndicatorColor() {
return indicatorColor;
}
public void setIndicatorColor(int indicatorColor) {
this.indicatorColor = indicatorColor;
invalidate();
}
public int getIndicatorHeight() {
return indicatorHeight;
}
public void setIndicatorHeight(int indicatorHeight) {
this.indicatorHeight = indicatorHeight;
invalidate();
}
public boolean isShowIndicator() {
return isShowIndicator;
}
public void setShowIndicator(boolean isShowIndicator) {
this.isShowIndicator = isShowIndicator;
invalidate();
}
public void setOnItemClickListener(
OnTabItemClickListener pOnTabItemClickListener) {
mOnTabItemClickListener = pOnTabItemClickListener;
}
/**
* note:all property set must call before this method.other wise,your
* property set will not be effect.
*
* @param tabItems
*/
public void setTabItems(List<TabItem> tabItems) {
if (tabItems == null || tabItems.isEmpty()) {
throw new IllegalArgumentException("tab items cannot be empty!!");
}
tabsContainer.removeAllViews();
tabCount = tabItems.size();
for (int i = 0; i < tabCount; i++) {
final TabItem item = tabItems.get(i);
final int j = i;
item.view().setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mOnTabItemClickListener != null) {
mOnTabItemClickListener.OnTabItemClick(j);
}
}
});
addTab(i, item.view());
}
getViewTreeObserver().addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
scrollToChild(currentPosition, 0);
}
});
}
private void unSelectItem(int index) {
TabItem item = (TabItem) tabsContainer.getChildAt(index);
item.unselect();
}
public void selectItem(int index) {
int childcounts = tabsContainer.getChildCount();
if (index < 0 || index >= childcounts) {
return;
}
// must unselect all first.
for (int i = 0; i < childcounts; i++) {
unSelectItem(i);
}
TabItem item = (TabItem) tabsContainer.getChildAt(index);
item.select();
//
currentPosition = index;
scrollToChild(
currentPosition,
(int) (currentPositionOffset * tabsContainer.getChildAt(
currentPosition).getWidth()));
invalidate();
}
private void addTab(final int position, View tab) {
tab.setFocusable(true);
tabsContainer
.addView(tab, position, shouldExpand ? expandedTabLayoutParams
: defaultTabLayoutParams);
}
private void scrollToChild(int position, int offset) {
if (tabCount == 0) {
return;
}
int newScrollX = tabsContainer.getChildAt(position).getLeft() + offset;
if (position > 0 || offset > 0) {
newScrollX -= scrollOffset;
}
if (newScrollX != lastScrollX) {
lastScrollX = newScrollX;
scrollTo(newScrollX, 0);
}
}
public void setScrollOffset(int scrollOffsetPx) {
this.scrollOffset = scrollOffsetPx;
}
public void setShouldExpand(boolean shouldExpand) {
this.shouldExpand = shouldExpand;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
SavedState savedState = (SavedState) state;
super.onRestoreInstanceState(savedState.getSuperState());
currentPosition = savedState.currentPosition;
requestLayout();
}
@Override
public Parcelable onSaveInstanceState() {
Parcelable superState = super.onSaveInstanceState();
SavedState savedState = new SavedState(superState);
savedState.currentPosition = currentPosition;
return savedState;
}
static class SavedState extends BaseSavedState {
int currentPosition;
public SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
currentPosition = in.readInt();
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
dest.writeInt(currentPosition);
}
public static final Creator<SavedState> CREATOR = new Creator<SavedState>() {
@Override
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
@Override
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (!isShowIndicator) {
return;
}
final int height = getHeight();
// draw underline
rectPaint.setColor(indicatorColor);
canvas.drawRect(0, height - underlineHeight, tabsContainer.getWidth(),
height, rectPaint);
// draw indicator line
rectPaint.setColor(indicatorColor);
// default: line below current tab
View currentTab = tabsContainer.getChildAt(currentPosition);
float lineLeft = currentTab.getLeft();
float lineRight = currentTab.getRight();
// if there is an offset, start interpolating left and right coordinates
// between current and next tab
if (currentPositionOffset > 0f && currentPosition < tabCount - 1) {
View nextTab = tabsContainer.getChildAt(currentPosition + 1);
final float nextTabLeft = nextTab.getLeft();
final float nextTabRight = nextTab.getRight();
lineLeft = (currentPositionOffset * nextTabLeft + (1f - currentPositionOffset)
* lineLeft);
lineRight = (currentPositionOffset * nextTabRight + (1f - currentPositionOffset)
* lineRight);
}
canvas.drawRect(lineLeft, height - indicatorHeight, lineRight, height,
rectPaint);
}
/**
* this just use for viewpager.
*
* @param position
* @param positionOffset
* @param positionOffsetPixels
*/
public void onPageScrolled(int position, float positionOffset,
int positionOffsetPixels) {
currentPosition = position;
currentPositionOffset = positionOffset;
scrollToChild(position, (int) (positionOffset * tabsContainer
.getChildAt(position).getWidth()));
invalidate();
}
/**
* this just use for viewpager.
*
* @param state
*/
public void onPageScrollStateChanged(int state) {
final int SCROLL_STATE_IDLE = 0;
if (state == SCROLL_STATE_IDLE) {
scrollToChild(currentPosition, 0);
}
}
}
package com.commonlib.ui;
import android.view.View;
public interface TabItem {
void select();
void unselect();
View view();
}
使用示例:
tabs = (TabGroup) findViewById(R.id.main_tab_bottombar);
tabs.setOnItemClickListener(this);
List<TabItem> tabitems = new ArrayList<TabItem>();
TabItem tabIndex = new TabItemView(this, "index",
R.drawable.ic_launcher, Color.BLACK, Color.BLUE,
R.drawable.ic_launcher);
//
TabItem tabCat = new TabItemView(this, "category",
R.drawable.ic_launcher, Color.BLACK, Color.BLUE,
R.drawable.ic_launcher);
//
TabItem tabUser = new TabItemView(this, "user", R.drawable.ic_launcher,
Color.BLACK, Color.BLUE, R.drawable.ic_launcher);
//
TabItem tabSetting = new TabItemView(this, "setting",
R.drawable.ic_launcher, Color.BLACK, Color.BLUE,
R.drawable.ic_launcher);
//
tabitems.add(tabIndex);
tabitems.add(tabCat);
tabitems.add(tabUser);
tabitems.add(tabSetting);
tabs.setTabItems(tabitems);