`
ouyangfeng521
  • 浏览: 248765 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

模仿移动MM Tab 点击 背景 滑动效果

阅读更多

在玩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());
	}
    
}
 

有兴趣的可以看下 写的不好 不要见怪哦!!!

 

 

2
0
分享到:
评论

相关推荐

    上下滚动tab标题跟随联动效果,点击tab滚动切换模块

    在这个场景下,横向的tab(标签)与内容区域实现了联动,当用户在内容区域上滑动时,tab标题会随之移动,保持在可视区域内。同时,当用户手指悬停在tab上时,内容区域会自动滚动到相应的模块,这样用户就能快速定位...

    模仿百度风云榜TAB标签切换效果

    "模仿百度风云榜TAB标签切换效果"是指在网页中实现与百度风云榜类似的,通过点击或滑动在不同内容区块之间切换的功能。这种效果能够帮助用户更有效地浏览和组织大量信息,使得网页布局更加清晰,操作更加便捷。 ...

    Android模仿飞信Tab

    3. **PagerTabStrip / PagerTitleStrip**:结合ViewPager,可以创建滑动Tab效果。这两个控件是专为与ViewPager配合使用而设计的,当用户在ViewPager的不同页面间滑动时,Tab会自动更新。 4. **TabLayout**:自...

    新建tab页-网页左右滑动效果-划过图片其他图片变暗

    本项目以"新建tab页-网页左右滑动效果-划过图片其他图片变暗"为主题,旨在模仿360极速浏览器的新建页面标签功能,通过实现一种动态、美观的切换效果来吸引用户。这个效果的核心在于利用HTML、CSS和JavaScript技术来...

    jquery mobile 网易新闻tab滑动导航网页

    标题中的"jQuery Mobile 网易新闻tab滑动导航网页"指的是使用jQuery Mobile来实现类似网易新闻那样具有滑动导航功能的网页。这种设计模式常见于新闻类应用,它允许用户通过滑动屏幕在不同的新闻分类之间切换。 **...

    JS滑动门_JS tab标签页效果大合集(新浪腾讯雅虎)

    3. **CSS样式控制**:JS可以改变元素的CSS样式,如宽度、高度、位置等,实现视觉上的滑动效果。 4. **动画效果**:利用CSS3的transition或JS库(如jQuery)的动画功能,使元素的移动更平滑自然。 5. **封装和模块化*...

    顶部导航栏可滑动可点击,仿微信仿豆瓣

    在这个示例中,ViewPager被用来创建顶部导航栏下方的页面滑动效果。每个页面通常对应一个Fragment或Activity,这样可以方便地实现多个内容区域的切换。 2. **自定义布局**:为了实现可点击的顶部导航栏,开发者可能...

    新版人人滑动效果

    在Android开发中,"新版人人滑动效果"指的是模仿社交应用人人网的新版界面中,实现的左右滑动切换页面的交互设计。这种滑动效果是现代移动应用中常见的导航方式,它通常用于展示多个视图或者不同类型的卡片内容,为...

    TabLayout的Tab滑块

    本文将深入探讨如何实现"TabLayout的Tab滑块"这一特性,包括自定义滑块效果、与Fragment的无缝配合以及滑块的横向移动。 首先,我们要理解TabLayout的基本用法。TabLayout通常配合ViewPager使用,通过设置TabLayout...

    Winform 高仿 Chrome 的 Tab页控件

    5. **其他高级特性**:除了基本功能外,可能还包括鼠标悬停效果、滑动切换标签、最小化标签、预览功能等。开发者需要编写代码来处理这些复杂的交互,以增强用户体验。 实现这样的控件通常需要深入理解.NET ...

    jq仿京东商城商品分类滑动切换效果

    "jq仿京东商城商品分类滑动切换效果"是一个基于jQuery实现的网页动态效果,它模仿了京东商城的商品分类展示方式,让用户在浏览商品时能便捷地切换不同的类别。这种效果使得网站更加直观、易用,增加了用户对网站的...

    ViewPager实现Tab

    在Android应用开发中,`ViewPager` 是一个非常重要的组件,常用于实现页面滑动效果,尤其是在构建Tab切换功能时。`Tab` 则是界面设计中常见的一种元素,用于展示多个可切换的视图。本篇文章将深入讲解如何在Eclipse...

    仿网易新闻客户端

    【标题】"仿网易新闻客户端"是一个项目,旨在模仿知名新闻平台网易新闻的移动客户端界面和功能。这个项目主要关注首页的设计,特别是标签选项卡和滑动效果的实现,为用户提供类似网易新闻客户端的浏览体验。 【描述...

    模仿新版手Q底部TabView

    本文将深入探讨如何模仿新版手Q(腾讯QQ)底部的TabView,尤其是其独特的icon跟随手指移动的效果。 首先,我们要理解TabView的基本原理。TabView通常由一组底部标签构成,每个标签对应应用的一个主要功能页面。当...

    微信小程序实现滴滴导航tab切换效果

    通过以上知识点的结合,微信小程序可以实现类似滴滴导航的tab切换效果,用户在顶部导航栏滑动或点击选择不同的服务类型,中间的内容区会相应地切换展示对应的服务页面。这样的设计既提供了良好的交互体验,又有效地...

    从相机获取图片以及微信界面的模仿UI特效

    在IT行业中,尤其是在移动应用开发领域,模仿知名应用如微信的UI(用户界面)特效是一种常见的学习和设计方法。微信作为全球广泛使用的社交应用,其界面设计和用户体验被许多开发者视为参考标准。本文将深入探讨如何...

    模仿微信UI

    通常,它用于实现类似滑动Tab的效果,用户可以通过左右滑动来切换不同的页面。在微信应用中,`ViewPage`可能被用在“发现”、“聊天”、“我”等不同功能模块之间的切换,让用户能够流畅地在各个功能之间进行浏览。 ...

    Android应用源码之DWinterTabDemo(左右滑动菜单特效)-IT计算机-毕业设计.zip

    3. **Gesture Detector**:为了实现滑动效果,开发者通常会使用GestureDetector类来检测用户的滑动操作。它可以监听到ACTION_DOWN、ACTION_MOVE和ACTION_UP等事件,从而判断是否触发滑动菜单的开关。 4. **...

    AndroidDemo.rar

    通过这个项目,开发者不仅可以学习到如何创建一个具有底部Tab切换和滑动页面的应用,还能了解到如何自定义UI元素以实现特定的动画效果,从而提升应用的视觉吸引力和用户体验。同时,这也是一个很好的实践案例,帮助...

Global site tag (gtag.js) - Google Analytics