在玩MM时看到里面的tab 很酷 就学着做了一个
效果如下:
上代码 现在我把他搞成了一个控件了 用法跟ListView 差不多
控件类:
package com.test.scrolltab.control;
import java.util.HashMap;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.test.scrolltab.R;
public class ScrcoolTab extends LinearLayout {
private int top,bottom; // 该布局的top与bottom
private LayoutInflater mInflater; // 控件xml 解析器
private OnItemClickListener clickListener; // 点击事件
private int defaultTab; // 默认选中第几个
private boolean move = false; //标识是否可以移动,主要为了实现一个项点击后,用户不能点击第二个
private HashMap<Integer, Integer []> childPointCache = new HashMap<Integer, Integer[]>();
int childWidth = 0; //因为要控件居中,所以计算出每个控件可以有多少宽度
private int gleft,currentwidth,currentleft; // 上一个选中项的左坐标 当前点击的控件的宽度 当前点击的控件的左坐标
private Integer [] current = {0,0}; //tab 背景的坐标
private Drawable tabpictrue; //tab 移动的背景图片
private int tabpicpadding ; //tab 背景图片大于控件多少
private int moveunit; // tab图片第次移动多少
private int duration;//移动速度
public ScrcoolTab(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ScrcoolTab);
final int N = a.getIndexCount();
for (int i = 0; i < N; i++) {
int attr = a.getIndex(i);
switch (attr) {
case R.styleable.ScrcoolTab_tabpictrue:
tabpictrue = (Drawable) a.getDrawable(i);
break;
case R.styleable.ScrcoolTab_tabpicpadding:
tabpicpadding = a.getDimensionPixelSize(i, 5);
break;
case R.styleable.ScrcoolTab_moveunit:
moveunit = a.getDimensionPixelSize(i, 5);
break;
case R.styleable.ScrcoolTab_duration:
duration = a.getInt(i, 100);
break;
}
}
Log.i("ScrcoolTab", "construt");
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if( ! isDrawItem()) return;
tabpictrue.setBounds(current[0] -tabpicpadding ,top , current[0] + currentwidth + tabpicpadding , bottom);
tabpictrue.draw(canvas);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.i("ScrcoolTab", "onLayout");
super.onLayout(changed, l, t, r, b);
top = t;
bottom = b;
int count = getChildCount();
if(0 == count) return;
int w = r- l;
childWidth = w / count;
View v =null;
Integer [] points = null;
for(int i = 0;i < count;i++){
v = getChildAt(i);
points = scalcChildPoint(v, i);
v.layout(points[0] ,((bottom - top) - v.getHeight()) /2 , points[1], ((bottom - top) - v.getHeight()) /2 + v.getHeight());
v.setTag(new Integer(i));
v.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if( !move ){
move = true;
itemOnclick(v ,((Integer)v.getTag()).intValue() );
}
}
});
}
//set default tab
View mDefaultTab = getChildAt(defaultTab);
if(null != mDefaultTab){
itemOnclick(v , defaultTab);
}
}
public synchronized void update(View v ,int position){
Log.i("ScrcoolTab", "update");
current = childPointCache.get(new Integer(position));
currentleft = current [0];
currentwidth = v.getWidth(); // 得到当前点击的控件的宽度
//如果重复点一个项,则不会移动
if(gleft == current [0]) {
move = false; //下一个点击可以移动
return ;
}
clickListener.onItemClickListener(v, ((Integer)v.getTag()).intValue());//通知设置监听
Log.i("ScrcoolTab", "tab moved");
defaultTab = position;
final boolean pathleft = gleft > current[0] ? true : false;//判断是向左还是向右
final int num = Math.abs((gleft - current[0]) / moveunit);
int i = 0;
while( i < num){
if( pathleft ){
gleft = gleft - moveunit;
current [0] = gleft;
}else{
gleft = gleft + moveunit;
current [0] = gleft;
}
try {
Thread.sleep(duration);
} catch (InterruptedException e) {
e.printStackTrace();
}
Log.i("ScrcoolTab", "Thread: left"+current[0]);
postInvalidate();
i++;
}
//校正 因为除数可能有精度损失
if(gleft != currentleft){
current [0] = currentleft;
postInvalidate();
}
gleft = current[0];
move = false;
}
/**
* 当点击一项时,移动背景坐标
* @param v
*/
public synchronized void itemOnclick(final View v ,final int position){
Log.i("ScrcoolTab", "itemOnclick position:" + position);
new Thread( new Runnable() {
@Override
public void run() {
update (v , position);
}
}).start();
}
/**
* 设置数据适配器
* @param adapter
*/
public void setAdapter(ScrcoolTabAdapter adapter){
Log.i("ScrcoolTab", "setAdapter");
if(null != adapter && 0 != adapter.getResource() && null != adapter.getData()){
View view = null;
for(String str : adapter.getData()){
view = mInflater.inflate(adapter.getResource(),this ,false);
if(view instanceof TextView) ((TextView)view).setText(str);
this.addView(view);
}
}
}
/**
* 计算每个子控件的坐标
* @param view
* @param position
* @return
*/
public Integer [] scalcChildPoint(View view ,int position){
Integer[] points = new Integer [2];
points [0] = childWidth * position + (childWidth - view.getWidth())/2;
points [1] = points [0] + view.getWidth();
Log.i("ScrcoolTab", "scalcChildPoint position :" + position + "left:" + points [0] + "right:" + points [1]);
childPointCache.put(new Integer(position), points);
return points;
}
/**
* 是否画背景图片taab
* @return
*/
private boolean isDrawItem(){
if(current [0] > 0 ) return true;
else return false;
}
/**
* 设置默认选中
* @param tab
*/
public void setDefaultTab(int tab){
Log.i("ScrcoolTab", "setDefaultTab");
this.defaultTab = tab;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.i("ScrcoolTab", "onAttachedToWindow");
}
/**
* 得到当前选中的项
* @return
*/
public int getFocus() {
return defaultTab;
}
/**
* 当点一项时 调用事件
* @param clickListener
*/
public void setOnItemClickListener(OnItemClickListener clickListener){
this.clickListener = clickListener;
}
/**
* 事件接口
*
*/
public interface OnItemClickListener {
void onItemClickListener(View v , int position);
}
}
控件适配器类:
package com.test.scrolltab.control;
public class ScrcoolTabAdapter {
private int resource;
private String[] data;
public int getResource() {
return resource;
}
public void setResource(int resource) {
this.resource = resource;
}
public String[] getData() {
return data;
}
public void setData(String[] data) {
this.data = data;
}
public ScrcoolTabAdapter(int resource, String[] data) {
super();
this.resource = resource;
this.data = data;
}
}
用法:
xml 布局文件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:control="http://schemas.android.com/apk/res/com.test.scrolltab"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.test.scrolltab.control.ScrcoolTab
android:id="@+id/scrcoolTab" android:layout_height="wrap_content"
android:layout_width="fill_parent" android:gravity="center_vertical"
control:tabpictrue="@drawable/bg_item_t" android:background="@drawable/bg_t"
control:tabpicpadding="5dip" control:moveunit="15dip" control:duration="50">
</com.test.scrolltab.control.ScrcoolTab>
</LinearLayout>
一个tab的布局:
<?xml version="1.0" encoding="utf-8"?>
<TextView android:layout_width="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content" style="@style/text_style"
android:onClick="itemOnclick" />
activity调用代码:
package com.test.scrolltab;
import android.app.Activity;
import android.os.Bundle;
import android.os.Process;
import android.view.View;
import android.view.ViewParent;
import com.test.scrolltab.control.ScrcoolTab;
import com.test.scrolltab.control.ScrcoolTabAdapter;
import com.test.scrolltab.control.ScrcoolTab.OnItemClickListener;
public class ScrollTabActivity extends Activity {
private ScrcoolTab scrcoolTab;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
scrcoolTab = (ScrcoolTab) findViewById(R.id.scrcoolTab);
scrcoolTab.setAdapter(new ScrcoolTabAdapter(R.layout.tab_item,new String []{"进入首页","用户调研","下载中心","联系我们"}));
scrcoolTab.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClickListener(View v, int position) {
// Toast.makeText(ScrollTabActivity.this, "点击了" + position, Toast.LENGTH_SHORT).show();
}
});
// scrcoolTab.setDefaultTab(1);
}
public void itemOnclick(View v){
ViewParent parent = v.getParent().getParent();
if(parent instanceof ScrcoolTab){
ScrcoolTab tab = (ScrcoolTab) parent;
tab.postInvalidate();
}
System.out.println(parent);
}
@Override
public void finish() {
super.finish();
Process.killProcess(Process.myPid());
}
}
有兴趣的可以看下 写的不好 不要见怪哦!!!
分享到:
相关推荐
HTML实现的Tab切换效果,点击滑动和触控滑动(SlideTouch插件),资源里面是源码!
tab滑动效果
Bootstrap Ace模板 美化了tab页css,bootstrap-tab.js为标签页宽度超限时是左右滑动效果
像新浪微博的Tab,qq2012的Tab滑动效果。我们可以手势滑动,也可以点击上面的头标进行切换。与此同方式, 白色横条会移动到相应的页卡头标下。这是一个动画效果,白条是缓慢滑动过去的。
移动端滑动时切换tab页,类似于Android版本的微信和新浪微博发现页面中的滑动切换效果,我分别使用了基于swipe插件和zepto插件的两种方法,均可完美实现;
自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动TAB效果.rar自动滑动...
Android 高仿华为Tab页的滑动导航功能.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
VB.NET读取ini文件,有窗体Tab标签,滑动效果,界面美化等效果,集成在了一个程序中。本人新手,学习vb.net不久,前几天写了一个程序,觉得还可以,让新手借鉴,老手请直接飘过... (vb.net 2008 速成版编写,低...
逆战tab切换,带滑动效果
类似QQ的tab的滑动效果的原理代码,导入可运行,非常漂亮..
插件描述:适合手机、pad等移动终端的tab响应式切换效果.
运用jquery实现的网页TAB 点击切换内容,带有线条滑动效果,测试时要注意ie11会弹出提示请求允许脚本运行,否则本效果会失效,jQuery请勿版本太高。在单击TAB切换时,内容淡入淡出风格显示,类似Flash的效果。
仿微信左右滑动的tab实现,安卓源码。完美运行。
支持移动浏览器(手机、ipad等)左右滑动切换tab标签
jQuery点击tab标签滑动选项卡切换效果
PagerSlidingTab抽取出来的 类,实现tab的滑动
tab切换并且底部横线跟随点击选中目标滑动。
jQuery简洁蓝色的tab选项卡 支持滑动效果,鼠标悬停于TAB上时,TAB的蓝色背景会滑过来,内容紧跟着切换变化,如果需要选项卡,点击鼠标切换那种,本效果也可以实现。
jQuery 移动式的Tab滑动门菜单 jQuery 移动式的Tab滑动门菜单