仿Android QQ实现的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(),把下一次移动的数据准备好了。所以侦数就稍有上升了。

转自:http://www.pin5i.com/showtopic-android-qq-top-bar-oval-transparent-background-moving-effect.html

时间: 2024-09-30 16:58:23

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

设计一个android引导页面的动画,最好是透明渐变动画效果,求大神帮忙!

问题描述 设计一个android引导页面的动画,最好是透明渐变动画效果,求大神帮忙! 设计一个android引导页面的动画,最好是透明渐变动画效果,大概样式就像APP微信精选那个引导页面那种样式,求大神帮忙给个Demo! 解决方案 之前回复的都回复不了,现在重新再给你回复一遍吧,首先创建三个Fragment,我现在给你举一个例子: public class WelcomeFragment1 extends Fragment { @Override public void onCreate(Bun

android如何做出像qq好友分栏一样的抽屉效果?

问题描述 请问android如何做出像qq好友分栏一样的抽屉效果,谢谢了- 解决方案 详细参考http://blog.csdn.net/yaoyeyzq/article/details/6579160解决方案二:如果想简单就直接用expanListView!

Android开发仿QQ空间根据位置弹出PopupWindow显示更多操作效果_Android

我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图: 这个要实现这个效果可以分几步进行 1.第一步自定义PopupWindow,实现如图的样式,这个继承PopupWindow自定义布局很容易实现 2.得到点击按钮的位置,根据位置是否在屏幕的中间的上方还是下方,将PopupWindow显示在控件的上方或者下方 3.适配问题,因为PopupWindow上面的操作列表

Android开发仿QQ空间根据位置弹出PopupWindow显示更多操作效果

我们打开QQ空间的时候有个箭头按钮点击之后弹出PopupWindow会根据位置的变化显示在箭头的上方还是下方,比普通的PopupWindow弹在屏幕中间显示好看的多. 先看QQ空间效果图: 这个要实现这个效果可以分几步进行 1.第一步自定义PopupWindow,实现如图的样式,这个继承PopupWindow自定义布局很容易实现 2.得到点击按钮的位置,根据位置是否在屏幕的中间的上方还是下方,将PopupWindow显示在控件的上方或者下方 3.适配问题,因为PopupWindow上面的操作列表

Android开发中模仿qq列表信息滑动删除功能

这个效果的完成主要分为两个部分 自定义view作为listview的列表项 一个view里面包括 显示头像,名字,消息内容等的contentView和滑动才能显示出来的删除,置顶的右边菜单menuView 在手指移动的时候同时改变这两个视图的位置 重写listview 判断item向左还是向右滑动 正常的滚动还是左右滑动等等 重写onTouchEvent 进行事件分发 大致思路: listview进行事件分发,判断需要滑动还是滚动等状态,如果需要滑动将事件传递给item进行滑动处理. 在item

Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果_Android

本文实例讲述了Android基于ListView实现类似QQ空间的滚动翻页与滚动加载效果.分享给大家供大家参考,具体如下: 1. 滚动加载 listView.setOnScrollListener(new OnScrollListener() { //添加滚动条滚到最底部,加载余下的元素 @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == OnScro

android友盟分享QQ和QQ空间时出现内存泄露

问题描述 android友盟分享QQ和QQ空间时出现内存泄露 05-12 19:22:46.570: E/StrictMode(30304): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. 05-12 19:22:46.570: E/StrictMode(30304): jav

android类是手机QQ游戏大厅的设计求帮助下面详细描述我的困难

问题描述 android类是手机QQ游戏大厅的设计求帮助下面详细描述我的困难 就是我想知道这个图片的下面是用Fragment做的还是intent 然后还有中间的滑动是不是用的gallery 3D如果是的话这个代码该具体怎么写.我不知道吧滑动放到哪里.求各位帮帮忙吧

qq音乐歌词置顶功能在哪 qq音乐歌词置顶的方法介绍

方法一: 1.如我们在打开QQ音乐之后点击 切换按钮,切换到歌词面板 细节如下图所示 2..之后我们"总是在最前面"点击它就可以了 方法二: 1.我们同样打开QQ音乐,我们会看到菜单上有一个 小锁我们就可以锁定它,效果与方法一是一样的. 好了到此两种QQ音乐歌词置顶的方法也就介绍完了,现在我们做其它的事情时歌词也会显示出来的哦.