自定义控件实现弹出菜单选项

11 篇文章 0 订阅
public class PaddyMenuView extends GLSurfaceView
{
   public PaddyMenuView(Context context)
   {
      super(context);
   }

   public PaddyMenuView(Context context, AttributeSet attrs)
   {
      super(context, attrs);
   }

   @Override
   public void surfaceCreated(SurfaceHolder holder)
   {
      m_Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
      m_Paint.setColor(Color.GREEN);
      m_Paint.setTextSize(60);
      m_Paint.setStyle(Paint.Style.STROKE);
      m_Paint.setStrokeWidth(2f);
      m_Paint.setDither(true);//防止文字抖动
      m_Paint.setPathEffect(new CornerPathEffect(10));//增加圆角

      m_DPoint = new PointF(0, 0);
      //
      m_MenuThd = new MenuThread("PaddingMenuThread");
      m_MenuThd.start();
   }

   @Override
   public void surfaceChanged(SurfaceHolder holder, int format, int w, int h)
   {
   }

   @Override
   public void surfaceDestroyed(SurfaceHolder holder)
   {
      if (m_MenuThd != null)
      {
         m_MenuThd.setStopCmd();
         m_MenuThd.Join();
         m_MenuThd = null;
      }
   }

   @Override
   public boolean onTouchEvent(MotionEvent event)
   {
      if (event.getAction() == MotionEvent.ACTION_DOWN && event.getActionMasked() == MotionEvent.ACTION_DOWN)
      {
         //判断落点,处理点击事件
         float x = event.getX();
         float y = event.getY();
         if (!(y >= getMeasuredHeight() / 2f - m_Radius && y <= getMeasuredHeight() / 2f + m_Radius))
            return true;
         if (x >= m_POffset - m_Radius && x <= m_POffset + m_Radius)
         {
            m_Status = 0;
            if (m_OpenMenu.get()) m_OpenMenu.set(false);
            else m_OpenMenu.set(true);
            m_DPoint.set(x, y);
            rippleAnimate();
         }
         if (!(m_PMoveSet == m_POffset || m_PMoveSet == 4 * m_POffset)) return true;
         if (m_PMoveSet != 4 * m_POffset) return true;

         if (x > 2 * m_POffset - m_Radius && x < 2 * m_POffset + m_Radius)
         {
            m_Status = 1;
            rippleAnimate();
         } else if (x > 3 * m_POffset - m_Radius && x < 3 * m_POffset + m_Radius)
         {
            m_Status = 2;
            rippleAnimate();
         } else if (x > 4 * m_POffset - m_Radius && x < 4 * m_POffset + m_Radius)
         {
            m_Status = 3;
            rippleAnimate();
         }

         m_DPoint.set(x, y);
      }
      return true;
   }

   private class MenuThread extends ThreadEx
   {

      public MenuThread(String threadName)
      {
         super(threadName);
      }

      public void setStopCmd()
      {
         this.stopCmd = true;
      }

      @Override
      public void run()
      {
         super.run();
         for (; ; )
         {
            if (stopCmd) break;
            Canvas c = PaddyMenuView.this.getHolder().lockCanvas();
            if (c != null)
            {
               m_Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
               m_Paint.setMaskFilter(null);
               c.drawPaint(m_Paint);
               m_Paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
               c.drawColor(Color.DKGRAY);
               // 设置光源的方向
               float[] direction = new float[]{1, 1, 1};
               //环境光亮度
               float light = 0.8f;
               //反射等级
               float specular = 6f;
               //模糊级别
               float blur = 0f;
               m_Paint.setMaskFilter(new EmbossMaskFilter(direction, light, specular, blur));
               //
               m_Lock.lock();
               drawMenuItem(c);
               drawInfoTxt(c);
               drawRipple(c);
               m_Lock.unlock();
               PaddyMenuView.this.getHolder().unlockCanvasAndPost(c);
            }
            if (!ThreadEx.Sleep(8)) setStopCmd();
            m_Lock.lock();
            if (m_OpenMenu.get())
            {
               //检查偏移量越界时的跳动现象
               if (m_PMoveSet + m_OffsetSpeed <= 4 * m_POffset) m_PMoveSet += m_OffsetSpeed;
               else if (m_PMoveSet + m_OffsetSpeed > 4 * m_POffset)
                  m_PMoveSet += 4 * m_POffset - m_PMoveSet;
            } else
            {
               //检查偏移量越界时的跳动现象
               if (m_PMoveSet - m_OffsetSpeed >= m_POffset) m_PMoveSet -= m_OffsetSpeed;
               else if (m_PMoveSet - m_POffset < m_POffset)
                  m_PMoveSet -= m_PMoveSet - m_POffset;
            }

            m_Lock.unlock();
         }
      }

      private boolean stopCmd;
   }

   private void drawMenuItem(Canvas c)
   {
      //始终画第一个item
      if (m_PMoveSet <= 4 * m_POffset)
      {
         c.save();
         c.drawCircle(1f * m_POffset, getHeight() / 2f, m_Radius, m_Paint);
         Rect rect = new Rect(m_POffset - m_Radius, getHeight() / 2 - m_Radius, m_POffset + m_Radius, getHeight() / 2 + m_Radius);
         Paint.FontMetricsInt fm = m_Paint.getFontMetricsInt();
         int baseLine = rect.top + ((rect.bottom - rect.top) - (fm.bottom - fm.top)) / 2 - fm.top;
         m_Paint.setTextAlign(Paint.Align.CENTER);
         c.drawText("M", rect.centerX(), baseLine, m_Paint);
         c.restore();
      }
      //画第二个item
      if (m_PMoveSet >= 2 * m_POffset)
      {
         c.save();
         c.drawCircle(2f * m_POffset, getHeight() / 2f, m_Radius, m_Paint);
         Rect rect = new Rect(2 * m_POffset - m_Radius, getHeight() / 2 - m_Radius, 2 * m_POffset + m_Radius, getHeight() / 2 + m_Radius);
         Paint.FontMetricsInt fm = m_Paint.getFontMetricsInt();
         int baseLine = rect.top + ((rect.bottom - rect.top) - (fm.bottom - fm.top)) / 2 - fm.top;
         m_Paint.setTextAlign(Paint.Align.CENTER);
         c.drawText("1", rect.centerX(), baseLine, m_Paint);
         c.restore();
      }
      //画第三个item
      if (m_PMoveSet >= 3 * m_POffset)
      {
         c.save();
         c.drawCircle(3f * m_POffset, getHeight() / 2f, m_Radius, m_Paint);
         Rect rect = new Rect(3 * m_POffset - m_Radius, getHeight() / 2 - m_Radius, 3 * m_POffset + m_Radius, getHeight() / 2 + m_Radius);
         Paint.FontMetricsInt fm = m_Paint.getFontMetricsInt();
         int baseLine = rect.top + ((rect.bottom - rect.top) - (fm.bottom - fm.top)) / 2 - fm.top;
         m_Paint.setTextAlign(Paint.Align.CENTER);
         c.drawText("2", rect.centerX(), baseLine, m_Paint);
         c.restore();
      }
      //画运动中的item(运动到最后,则既是第四个item      if (m_PMoveSet > m_POffset)
      {
         c.save();
         float count = (float) m_PMoveSet / (float) m_POffset;
         int i = -1;
         float rDegree = 0;
         if (count >= 1 && count < 2)
         {
            i = 1;
            rDegree = 360f * ((m_PMoveSet - 1f * m_POffset) / ((float) m_POffset));
         }
         if (count >= 2 && count < 3)
         {
            i = 2;
            rDegree = 360f * ((m_PMoveSet - 2f * m_POffset) / ((float) m_POffset));
         }
         if (count >= 3 && count <= 4)
         {
            i = 3;
            rDegree = 360f * ((m_PMoveSet - 3f * m_POffset) / ((float) m_POffset));
         }
         c.rotate(rDegree, m_PMoveSet, getHeight() / 2f);
         c.drawCircle(m_PMoveSet, getHeight() / 2f, m_Radius, m_Paint);
         //
         Rect rect = new Rect(m_PMoveSet - m_Radius, getHeight() / 2 - m_Radius, m_PMoveSet + m_Radius, getHeight() / 2 + m_Radius);
         Paint.FontMetricsInt fmi = m_Paint.getFontMetricsInt();
         int baseLine1 = rect.top + ((rect.bottom - rect.top) - (fmi.bottom - fmi.top)) / 2 - fmi.top;
         m_Paint.setTextAlign(Paint.Align.CENTER);
         if (i != -1) c.drawText(String.valueOf(i), rect.centerX(), baseLine1, m_Paint);
         c.restore();
      }
   }

   private void drawInfoTxt(Canvas c)
   {
      //center txt
      c.save();
      String str = "";
      if (m_PMoveSet == m_POffset) str = "close";
      else if (m_PMoveSet == 4 * m_POffset && m_Status != 0) str = String.valueOf(m_Status);
      //make text in center
      Rect targetRect = new Rect(0, getHeight() / 2 - m_Radius, getWidth(), getHeight() / 2 + m_Radius);
      Paint.FontMetricsInt fm = m_Paint.getFontMetricsInt();
      int baseLine = (targetRect.top + ((targetRect.bottom - targetRect.top) - (fm.bottom - fm.top)) / 2 - fm.top);
      m_Paint.setTextAlign(Paint.Align.RIGHT);
      c.drawText(str, targetRect.width(), baseLine, m_Paint);
      c.restore();
   }

   private void drawRipple(Canvas c)
   {
      m_Paint.setStyle(Paint.Style.FILL);
      m_Paint.setAlpha(180);
      c.save();
      c.drawCircle(m_DPoint.x, m_DPoint.y, m_RipRadius, m_Paint);
      c.restore();
      m_Paint.setStyle(Paint.Style.STROKE);
      m_Paint.setAlpha(255);
   }

   private void rippleAnimate()
   {
      if (m_RippleAnimator != null)
      {
         m_RippleAnimator.cancel();
         m_RippleAnimator = null;
         m_RipRadius = 0;
      }
      m_RippleAnimator = new Animation()
      {
         @Override
         protected void applyTransformation(float interpolatedTime, Transformation t)
         {
            m_RipRadius = (int) (.6f * m_Radius * interpolatedTime);
            if (interpolatedTime == 1)
            {
               m_RipRadius = 0;
            }
         }
      };
      m_RippleAnimator.setDuration(500);
      m_RippleAnimator.setInterpolator(new LinearInterpolator());
      startAnimation(m_RippleAnimator);
   }

   private MenuThread m_MenuThd;
   private ReentrantLock m_Lock = new ReentrantLock();
   private Paint m_Paint;
   private final static int m_Radius = 60;
   private final static int m_POffset = 150;
   private int m_PMoveSet = m_POffset;
   private final static int m_OffsetSpeed = 18;
   private AtomicBoolean m_OpenMenu = new AtomicBoolean(false);
   private int m_Status = -1;
   private PointF m_DPoint;
   private int m_RipRadius;
   private Animation m_RippleAnimator;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值