`
djking
  • 浏览: 8804 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

QQ顶栏椭圆透明背景移动的实现!

阅读更多
先看ANDROID QQ截图:

再看DEMO截图:



直接看代码:

public class test3 extends Activity {
	
	private NewLayOut layout;
	
	private myThread mThread;
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
    	layout = (NewLayOut) inflater.inflate(R.layout.move, null);
    	
    	ImageView button = (ImageView)layout.findViewById(R.id.ImageView01);
    	button.setOnClickListener(mClickListener);
    	ImageView button2 = (ImageView)layout.findViewById(R.id.ImageView02);
    	button2.setOnClickListener(mClickListener);
    	ImageView button3 = (ImageView)layout.findViewById(R.id.ImageView03);
    	button3.setOnClickListener(mClickListener);
    	
    	this.setContentView(layout);
    }
    
    private View.OnClickListener mClickListener = new View.OnClickListener() {
		
		public void onClick(View v) {
			startMove(v);
		}
	};
	
	private void startMove(View v)
    {
    	stopThread();//停止之前的线程
		mThread = new myThread(v);
		mThread.start();
    }
	
	private void stopThread()
    {
    	if (mThread != null)
		{
    		try
			{
    			layout.mIsStop = true;
				mThread.join();
			}
			catch(Exception e)
			{
				e.printStackTrace();
			}
		}
    }
	
	class myThread extends Thread
    {
    	private View mView;
    	
    	public myThread(View v){ this.mView = v; }
    	
		public void run() {
			layout.doWork(this.mView);
		}
    	
    }
}


NewLayOut 类 继承 LinearLayout,因为需要在LinearLayout里面画图

package test3.program;

import android.content.Context;

import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;

public class NewLayOut extends LinearLayout {

	private static final short SPEED = 15;
	
	private Context mContext;
	private Rect mNowRect;//当前的区域
	private Rect mEndRect;//结束的区域
	private BitmapDrawable mSelecter;//移动的半透明背景bitmaip
	private boolean mSyn = false;//循环和onDraw同步
	public boolean mIsStop = false;//是否到达指定区域
	
	public NewLayOut(Context context) {
		super(context);
		init(context);
	}
	
	public NewLayOut(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}
	
	private void init(Context context)
	{
		mContext = context;
		mSelecter = new BitmapDrawable(
				BitmapFactory.decodeResource(mContext.getResources(), 
						R.drawable.topbar_select));
		mNowRect = new Rect();
		mEndRect = new Rect();
	}
	
	protected void onLayout(boolean paramBoolean, int paramInt1, int paramInt2, int paramInt3, int paramInt4)
	{
		super.onLayout(paramBoolean, paramInt1, paramInt2, paramInt3, paramInt4);
		this.getChildAt(0).getHitRect(mNowRect);//取得第一个控制区域作为起始区域
	}
	
	/**
	 * 
	 * @param v 目标控件
	 */
	public void doWork(View v)
	{
		v.getHitRect(this.mEndRect);
		
		if (this.mNowRect.right < this.mEndRect.right)
		{
			work(new RunForword()
			{
				public void run()
				{
					mNowRect.left += SPEED;//每次左边移动15格
					mNowRect.right += SPEED;//每次右边移动15格
					
					System.out.println("is run run run");
					
					if (mNowRect.right >= mEndRect.right)//如果移动超出或等于目标区域
						ReachRect();
				}
			});
		}
		else if(this.mNowRect.right > this.mEndRect.right)
		{
			work(new RunForword()
			{
				public void run()
				{
					mNowRect.left -= SPEED;//每次左边移动15格
					mNowRect.right -= SPEED;//每次右边移动15格
					
					if (mNowRect.right <= mEndRect.right)//如果移动超出或等于目标区域
						ReachRect();
				}
			});
		}
	}
	
	private void work(RunForword run)
	{
		this.mIsStop = false;
		while(!this.mIsStop)
		{
			if(this.mSyn)//画图与循环同步
			{
				run.run();
				System.out.println("is running!");
				this.mSyn = false;
				this.postInvalidate();
				//Thread.sleep(35);
			}
		}
	}
	
	/**
	 * 到达目的地
	 */
	private void ReachRect()
	{
		mNowRect.left = mEndRect.left;
		mNowRect.right = mEndRect.right;
		mIsStop = true;
	}
	
	protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		
		mSelecter.setBounds(mNowRect);
		mSelecter.draw(canvas);
		this.mSyn = true;

		System.out.println("is ondraw");
	}
	
	public interface RunForword
	{
		void run();
	}
}


编写的过程中发现一点问题:

第一:画图与循环同步的问题

private void work(RunForword run)
	{
		this.mIsStop = false;
		while(!this.mIsStop)
		{
			if(this.mSyn)//画图与循环同步
			{
				run.run();
				System.out.println("is running!");
				this.mSyn = false;
				this.postInvalidate();
				//Thread.sleep(35);
			}
		}
	}


如果把 if(this.mSyn) 这段去掉 看图:



就是while循环好多次之后,onDraw才执行一次。猜想onDraw在上一次未执行完之前是不会被执行第二次的(onDraw好像开了一个新线程画图,但看SDK源码实现没看出个端儿。),所以需要做一个这样的同步。这里是继承LinearLayout的,不知道直接继承View会不会出现这种情况。上面的程序,onDraw执行完的时间大概在Thread.sleep(35)这么多时间。

看看把 if(this.mSyn) 加上去后的打印数据 看图:



第二:把移动的运算部份run.run();的方法直接放到onDraw里面运算

private void work(RunForword run)
	{
		this.mIsStop = false;
		while(!this.mIsStop)
		{
			if(this.mSyn)//画图与循环同步
			{

				System.out.println("is running!");
				this.mSyn = false;
				this.postInvalidate();
				//Thread.sleep(35);
			}
		}
	}
protected void onDraw(Canvas canvas)
	{
		super.onDraw(canvas);
		run.run();//大概时这个意思。。当实这样实写是不行的。
		mSelecter.setBounds(mNowRect);
		mSelecter.draw(canvas);
		this.mSyn = true;

		System.out.println("is ondraw");
	}


这样做的话,发觉移动的侦数比较底下,分析了一下原因。首先上面讲的,因为onDraw在上一次未画完图之前,第二次是不会运行的。而while循环又无视onDraw方法未执行完毕。所以在onDraw未执行完毕的过程中。运行run.run(),把下一次移动的数据准备好了。所以侦数就稍有上升了。

最后附上DEMO的源码: test3.rar

如上描述,有不正确的地方,请指教。谢谢。。

完毕。

有关ANDROID QQ的一些实现方法,请听下回分解。
  • 大小: 15.2 KB
  • 大小: 5.4 KB
  • 大小: 5.3 KB
  • 大小: 2.9 KB
  • 大小: 3.1 KB
分享到:
评论
6 楼 binner 2011-03-31  
cool!
5 楼 ffshow2006 2011-01-05  
下回分解在哪?要是引用的给个链接啊。
4 楼 Coding.Ghost 2010-12-16  
进入高级View必须学习的东西。
3 楼 huanxisha147 2010-11-05  
不错 我要深入学习 
2 楼 Czero 2010-09-15  
不错啊,楼主有心
1 楼 offeeyang 2010-08-28  
效果不错啊

相关推荐

    仿Android QQ实现的QQ顶栏椭圆透明背景移动效果

    通过以上步骤,我们可以成功地在Android应用中实现类似QQ顶栏的椭圆透明背景移动效果。这不仅提升了应用的视觉效果,也为用户带来了更丰富的交互体验。在实际开发中,开发者应根据项目需求灵活运用这些技术,创造出...

    C#400例子.pdf

    - **实例说明**:为工具栏添加背景色或背景图片,使其更加美观。 - **技术要点**: - 设置工具栏的背景属性。 - 可能需要处理图像的裁剪和缩放。 **实例008 带浮动工具栏** - **实例说明**:允许工具栏从固定...

    visual c++ 程序开发范例宝典 随书CD 源码 窗体与界面设计

    2、工具栏应用实例,包括:带背景的工具栏、带图标的工具栏、带下拉菜单的工具栏、可调整按钮位置的工具栏、浮动工具栏、根据表中数据动态生成工具栏、具有提示功能的工具栏。3、状态栏应用实例,包括:带进度条的...

    原生js实现图片放大镜效果

    首先,我们需要理解放大镜效果的基本原理:在原始图片上覆盖一个透明的小窗口,当用户移动鼠标时,这个小窗口会显示被鼠标覆盖部分的放大图像。这种效果通常通过CSS创建一个具有透明度的遮罩层,并利用JavaScript...

    Visual C++程序开发范例宝典(光盘) 第四部分

    实例008 带背景的工具栏 实例009 带图标的工具栏 实例010 带下拉菜单的工具栏 实例011 可调整按钮位置的工具栏 实例012 浮动工具栏 实例013 根据表中数据动态生成工具栏 实例014 具有提示功能的工具栏 1.4 ...

    Visual C++程序开发范例宝典(光盘) 第八部分

    实例008 带背景的工具栏 实例009 带图标的工具栏 实例010 带下拉菜单的工具栏 实例011 可调整按钮位置的工具栏 实例012 浮动工具栏 实例013 根据表中数据动态生成工具栏 实例014 具有提示功能的工具栏 1.4 ...

    C#经典特效代码470例(PDF已经整理)

    - 使用`ToolStrip`类的`BackgroundImage`属性来设置工具栏的背景图片。 - 使用`BackgroundImageLayout`属性来控制背景图片的显示方式。 **实例008:带浮动工具栏** - **实例说明**:创建一个可以自由浮动的工具...

    Visual C++ 程序开发范例宝典 源码 光盘 part2

    cc实例017 滚动字幕的状态栏 1.5 导航界面应用实例 cc实例018 Outlook导航界面 cc实例019 树状导航界面 cc实例020 按钮导航界面 cc实例021 类QQ导航菜单 1.6 界面窗体应用实例 cc实例022 背景为渐变...

    Visual C++程序开发范例宝典(PDF扫描版).part3

     cc实例008 带背景的工具栏   cc实例009 带图标的工具栏   cc实例010 带下拉菜单的工具栏   cc实例011 可调整按钮位置的工具栏   cc实例012 浮动工具栏   cc实例013 根据表中数据动态生成工具栏  ...

    Visual C++程序开发范例宝典(PDF扫描版).part2

     cc实例008 带背景的工具栏   cc实例009 带图标的工具栏   cc实例010 带下拉菜单的工具栏   cc实例011 可调整按钮位置的工具栏   cc实例012 浮动工具栏   cc实例013 根据表中数据动态生成工具栏  ...

    C#.net_经典编程例子400个

    5 实例006 菜级联菜单 7 1.2 工具栏设计 7 实例007 带背景的工具栏 7 实例008 浮动工具栏 8 实例009 带下拉菜单的工具栏 9 实例010 具有提示功能的工具栏 9 1.3 状态栏设计 10...

    明日科技C#开发入门及项目实战

    实例078 尝试制作一个半透明渐显窗体 实例079 使窗体标题栏文字右对齐 实例080 窗口间移动按钮 实例081 窗体中滚动的字幕 实例082 使用任意组件拖动窗体 实例083 窗体换肤程序 第9章 windows应用程序常用控件 实例...

    java源码包---java 源码 大量 实例

     util实现Java图片水印添加功能,有添加图片水印和文字水印,可以设置水印位置,透明度、设置对线段锯齿状边缘处理、水印图片的路径,水印一般格式是gif,png,这种图片可以设置透明度、水印旋转等,可以参考代码...

    PaintApp.zip

    MFC实现绘图软件功能如下:绘制 直线(移动,选中,拉伸,线条类型,颜色,粗细)绘制椭圆(Ctrl按住即为圆形,填充色选择边框色选择粗细透明色等等)矩形,四边随意拉伸效果,画笔实现直线同样功能(选中续画),...

Global site tag (gtag.js) - Google Analytics