SlideSwitch
//SlideSwitch.java
- package com.example.hellojni;
- import android.content.Context;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.BitmapFactory;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Rect;
- import android.graphics.Typeface;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.ViewGroup.LayoutParams;
- /**
- * SlideSwitch 仿iphone滑动开关组件,仿百度魔图滑动开关组件
- * 组件分为三种状态:打开、关闭、正在滑动<br/>
- * 使用方法:
- * <pre>SlideSwitch slideSwitch = new SlideSwitch(this);
- *slideSwitch.setOnSwitchChangedListener(onSwitchChangedListener);
- *linearLayout.addView(slideSwitch);
- </pre>
- 注:也可以加载在xml里面使用
- * @author scott
- *
- */
- public class SlideSwitch extends View
- {
- public static final String TAG = "SlideSwitch";
- public static final int SWITCH_OFF = 0;//关闭状态
- public static final int SWITCH_ON = 1;//打开状态
- public static final int SWITCH_SCROLING = 2;//滚动状态
- //用于显示的文本
- private String mOnText = "打开";
- private String mOffText = "关闭";
- private int mSwitchStatus = SWITCH_OFF;
- private boolean mHasScrolled = false;//表示是否发生过滚动
- private int mSrcX = 0, mDstX = 0;
- private int mBmpWidth = 0;
- private int mBmpHeight = 0;
- private int mThumbWidth = 0;
- private Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
- private OnSwitchChangedListener mOnSwitchChangedListener = null;
- //开关状态图
- Bitmap mSwitch_off, mSwitch_on, mSwitch_thumb;
- public SlideSwitch(Context context)
- {
- this(context, null);
- }
- public SlideSwitch(Context context, AttributeSet attrs)
- {
- super(context, attrs);
- init();
- }
- public SlideSwitch(Context context, AttributeSet attrs, int defStyle)
- {
- super(context, attrs, defStyle);
- init();
- }
- //初始化三幅图片
- private void init()
- {
- Resources res = getResources();
- mSwitch_off = BitmapFactory.decodeResource(res, R.drawable.bg_switch_off);
- mSwitch_on = BitmapFactory.decodeResource(res, R.drawable.bg_switch_on);
- mSwitch_thumb = BitmapFactory.decodeResource(res, R.drawable.switch_thumb);
- mBmpWidth = mSwitch_on.getWidth();
- mBmpHeight = mSwitch_on.getHeight();
- mThumbWidth = mSwitch_thumb.getWidth();
- }
- @Override
- public void setLayoutParams(LayoutParams params)
- {
- params.width = mBmpWidth;
- params.height = mBmpHeight;
- super.setLayoutParams(params);
- }
- /**
- * 为开关控件设置状态改变监听函数
- * @param onSwitchChangedListener 参见 {@link OnSwitchChangedListener}
- */
- public void setOnSwitchChangedListener(OnSwitchChangedListener onSwitchChangedListener)
- {
- mOnSwitchChangedListener = onSwitchChangedListener;
- }
- /**
- * 设置开关上面的文本
- * @param onText 控件打开时要显示的文本
- * @param offText 控件关闭时要显示的文本
- */
- public void setText(final String onText, final String offText)
- {
- mOnText = onText;
- mOffText =offText;
- invalidate();
- }
- /**
- * 设置开关的状态
- * @param on 是否打开开关 打开为true 关闭为false
- */
- public void setStatus(boolean on)
- {
- mSwitchStatus = ( on ? SWITCH_ON : SWITCH_OFF);
- }
- @Override
- public boolean onTouchEvent(MotionEvent event)
- {
- int action = event.getAction();
- Log.d(TAG, "onTouchEvent x=" + event.getX());
- switch (action) {
- case MotionEvent.ACTION_DOWN:
- mSrcX = (int) event.getX();
- break;
- case MotionEvent.ACTION_MOVE:
- mDstX = Math.max( (int) event.getX(), 10);
- mDstX = Math.min( mDstX, 62);
- if(mSrcX == mDstX)
- return true;
- mHasScrolled = true;
- AnimationTransRunnable aTransRunnable = new AnimationTransRunnable(mSrcX, mDstX, 0);
- new Thread(aTransRunnable).start();
- mSrcX = mDstX;
- break;
- case MotionEvent.ACTION_UP:
- if(mHasScrolled == false)//如果没有发生过滑动,就意味着这是一次单击过程
- {
- mSwitchStatus = Math.abs(mSwitchStatus-1);
- int xFrom = 10, xTo = 62;
- if(mSwitchStatus == SWITCH_OFF)
- {
- xFrom = 62;
- xTo = 10;
- }
- AnimationTransRunnable runnable = new AnimationTransRunnable(xFrom, xTo, 1);
- new Thread(runnable).start();
- }
- else
- {
- invalidate();
- mHasScrolled = false;
- }
- //状态改变的时候 回调事件函数
- if(mOnSwitchChangedListener != null)
- {
- mOnSwitchChangedListener.onSwitchChanged(this, mSwitchStatus);
- }
- break;
- default:
- break;
- }
- return true;
- }
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh)
- {
- super.onSizeChanged(w, h, oldw, oldh);
- }
- @Override
- protected void onDraw(Canvas canvas)
- {
- super.onDraw(canvas);
- //绘图的时候 内部用到了一些数值的硬编码,其实不太好,
- //主要是考虑到图片的原因,图片周围有透明边界,所以要有一定的偏移
- //硬编码的数值只要看懂了代码,其实可以理解其含义,可以做相应改进。
- mPaint.setTextSize(14);
- mPaint.setTypeface(Typeface.DEFAULT_BOLD);
- if(mSwitchStatus == SWITCH_OFF)
- {
- drawBitmap(canvas, null, null, mSwitch_off);
- drawBitmap(canvas, null, null, mSwitch_thumb);
- mPaint.setColor(Color.rgb(105, 105, 105));
- canvas.translate(mSwitch_thumb.getWidth(), 0);
- canvas.drawText(mOffText, 0, 20, mPaint);
- }
- else if(mSwitchStatus == SWITCH_ON)
- {
- drawBitmap(canvas, null, null, mSwitch_on);
- int count = canvas.save();
- canvas.translate(mSwitch_on.getWidth() - mSwitch_thumb.getWidth(), 0);
- drawBitmap(canvas, null, null, mSwitch_thumb);
- mPaint.setColor(Color.WHITE);
- canvas.restoreToCount(count);
- canvas.drawText(mOnText, 17, 20, mPaint);
- }
- else //SWITCH_SCROLING
- {
- mSwitchStatus = mDstX > 35 ? SWITCH_ON : SWITCH_OFF;
- drawBitmap(canvas, new Rect(0, 0, mDstX, mBmpHeight), new Rect(0, 0, (int)mDstX, mBmpHeight), mSwitch_on);
- mPaint.setColor(Color.WHITE);
- canvas.drawText(mOnText, 17, 20, mPaint);
- int count = canvas.save();
- canvas.translate(mDstX, 0);
- drawBitmap(canvas, new Rect(mDstX, 0, mBmpWidth, mBmpHeight),
- new Rect(0, 0, mBmpWidth - mDstX, mBmpHeight), mSwitch_off);
- canvas.restoreToCount(count);
- count = canvas.save();
- canvas.clipRect(mDstX, 0, mBmpWidth, mBmpHeight);
- canvas.translate(mThumbWidth, 0);
- mPaint.setColor(Color.rgb(105, 105, 105));
- canvas.drawText(mOffText, 0, 20, mPaint);
- canvas.restoreToCount(count);
- count = canvas.save();
- canvas.translate(mDstX - mThumbWidth / 2, 0);
- drawBitmap(canvas, null, null, mSwitch_thumb);
- canvas.restoreToCount(count);
- }
- }
- public void drawBitmap(Canvas canvas, Rect src, Rect dst, Bitmap bitmap)
- {
- dst = (dst == null ? new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()) : dst);
- Paint paint = new Paint();
- canvas.drawBitmap(bitmap, src, dst, paint);
- }
- /**
- * AnimationTransRunnable 做滑动动画所使用的线程
- */
- private class AnimationTransRunnable implements Runnable
- {
- private int srcX, dstX;
- private int duration;
- /**
- * 滑动动画
- * @param srcX 滑动起始点
- * @param dstX 滑动终止点
- * @param duration 是否采用动画,1采用,0不采用
- */
- public AnimationTransRunnable(float srcX, float dstX, final int duration)
- {
- this.srcX = (int)srcX;
- this.dstX = (int)dstX;
- this.duration = duration;
- }
- @Override
- public void run()
- {
- final int patch = (dstX > srcX ? 5 : -5);
- if(duration == 0)
- {
- SlideSwitch.this.mSwitchStatus = SWITCH_SCROLING;
- SlideSwitch.this.postInvalidate();
- }
- else
- {
- Log.d(TAG, "start Animation: [ " + srcX + " , " + dstX + " ]");
- int x = srcX + patch;
- while (Math.abs(x-dstX) > 5)
- {
- mDstX = x;
- SlideSwitch.this.mSwitchStatus = SWITCH_SCROLING;
- SlideSwitch.this.postInvalidate();
- x += patch;
- try
- {
- Thread.sleep(10);
- }
- catch (InterruptedException e)
- {
- e.printStackTrace();
- }
- }
- mDstX = dstX;
- SlideSwitch.this.mSwitchStatus = mDstX > 35 ? SWITCH_ON : SWITCH_OFF;
- SlideSwitch.this.postInvalidate();
- }
- }
- }
- public static interface OnSwitchChangedListener
- {
- /**
- * 状态改变 回调函数
- * @param status SWITCH_ON表示打开 SWITCH_OFF表示关闭
- */
- public abstract void onSwitchChanged(SlideSwitch obj, int status);
- }
- }
// layout xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="#fdfdfd"
- android:orientation="vertical"
- android:paddingLeft="10dip"
- android:paddingRight="10dip" >
- <ImageView
- android:id="@+id/imageView1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:src="@drawable/top" />
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:text="网络构图"
- android:textSize="15sp" />
- <com.example.hellojni.SlideSwitch
- android:id="@+id/slideSwitch1"
- android:layout_width="116dip"
- android:layout_height="46dip"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/textView2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:text="保留原图"
- android:textSize="15sp" />
- <com.example.hellojni.SlideSwitch
- android:id="@+id/slideSwitch2"
- android:layout_width="116dip"
- android:layout_height="46dip"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- <RelativeLayout
- android:layout_width="fill_parent"
- android:layout_height="wrap_content" >
- <TextView
- android:id="@+id/textView3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:layout_centerVertical="true"
- android:text="拍照声音"
- android:textSize="15sp" />
- <com.example.hellojni.SlideSwitch
- android:id="@+id/slideSwitch3"
- android:layout_width="116px"
- android:layout_height="46px"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" />
- </RelativeLayout>
- <TextView
- android:id="@+id/textViewTip"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:gravity="center"
- android:text="TextView" />
- </LinearLayout>
SlideSwitch的更多相关文章
- Android开源项目分类汇总
目前包括: Android开源项目第一篇——个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView. ...
- GitHub开源项目总结
SwipeRefreshLayout 地址:https://github.com/hanks-zyh/SwipeRefreshLayout 首页轮播的Tab样式,PagerSlidingTab 地址: ...
- Android 开源项目分类汇总(转)
Android 开源项目分类汇总(转) ## 第一部分 个性化控件(View)主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Galler ...
- Android 开源项目分类汇总
Android 开源项目分类汇总 Android 开源项目第一篇——个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView ...
- JQuery淡入淡出 banner切换特效
附件中提供另一种实现方式 基本类似 主要的实现方法如下: var ShowAD=function(i){ showImg.eq(i).animate({opacity:1},settings.sp ...
- Android开源经典项目
目前包括: Android开源项目第一篇--个性化控件(View)篇 包括ListView.ActionBar.Menu.ViewPager.Gallery.GridView.ImageView. ...
- 【Android】自己定义控件实现可滑动的开关(switch)
~转载请注明来源:http://blog.csdn.net/u013015161/article/details/46704745 介绍 昨天晚上写了一个Android的滑动开关, 即SlideSwi ...
- Android常用酷炫控件(开源项目)github地址汇总
转载一个很牛逼的控件收集帖... 第一部分 个性化控件(View) 主要介绍那些不错个性化的 View,包括 ListView.ActionBar.Menu.ViewPager.Gallery.Gri ...
- 做出一个SwitchButton的效果,并详细学习一下onDraw(Canvas canvas)方法的使用
代码的灵感和原理主要来自于android自定义开关控件-SlideSwitch http://blog.csdn.net/singwhatiwanna/article/details/9254309这 ...
随机推荐
- 从客户端中检测到有潜在危险的Request.Form 值
今天往MVC中加入了一个富文本编辑框,在提交信息的时候报了如下的错误:从客户端(Content="<EM ><STRONG ><U >这是测试这...&q ...
- ios kaifa
弹窗提示 { ////ios 7 弹窗 // UIAlertView *alert1=[[UIAlertView alloc] // initWithTitle:@"tishi" ...
- php5.3之前版本升级至5.3以及更高版本后部分语法简单归纳
1. Deprecated: Assigning the return value of new by reference is deprecated in /usr/local/www/uugui/ ...
- drawRect导致内存暴增的真正原因
那么现在我们分析一下drawRect导致内存暴增的真正原因: 重写drawRect为何会导致内存大量上涨? 要想搞明白这个问题,我们需要撸一撸在 iOS 程序上图形显示的原理.在 iOS 系统中所有显 ...
- mysqldump命令
mysqldump命令 mysqldump命令是mysql数据库中备份工具,用于将MySQL服务器中的数据库以标准的sql语言的方式导出,并保存到文件中. 语法 mysqldump(选项) 选项 -- ...
- Python3基础 print 自带换行功能
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- <转>如何改变讨好型人格 | 你根本不需要讨好任何人
在我过去二十多年的生命里一直是一个“讨好者”. 我总是活在别人对我的期待中,我总是不停的追逐着别人对我的认可,我总是像个卑微的奴才一样去满足别人的需求. 但就和大多数的“讨好者”一样,我们越是寻求别人 ...
- Cheatsheet: 2013 09.01 ~ 09.09
.NET Multi Threaded WebScraping in CSharpDotNetTech .NET Asynchronous Patterns An Overview of Projec ...
- Bug2算法的实现(RobotBASIC环境中仿真)
移动机器人智能的一个重要标志就是自主导航,而实现机器人自主导航有个基本要求--避障.之前简单介绍过Bug避障算法,但仅仅了解大致理论而不亲自动手实现一遍很难有深刻的印象,只能说似懂非懂.我不是天才,不 ...
- Systematic LncRNA Classification
Systematic LncRNA Classification From: http://www.arraystar.com/Services/Services_main.asp?ID=307 An ...