android自定义控件实现左右划出菜单并添加点击事件

本文将详细讲解如何在Android中创建一个自定义控件,该控件允许用户通过左右滑动来显示隐藏的菜单,并且为菜单项添加点击事件监听,以实现更丰富的交互体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >





public class SwipeItemView extends View
{
   public SwipeItemView(Context context)
   {
      super(context);
      init();
   }

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

   public void setSwipeTxt(String leftTxt, String rightTxt)
   {
      this.leftTxt = leftTxt;
      this.rightTxt = rightTxt;
   }

   @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
   private void init()
   {
      m_Paint = new Paint(Paint.ANTI_ALIAS_FLAG);
      m_Paint.setDither(true);
      m_Paint.setTextSize(64);
	//记录绘制试图的矩形
      m_CRect = new RectF(0, 0, 0, 0);//中间矩形
      m_LRect = new RectF(0, 0, 0, 0);//左边矩形
      m_RRect = new RectF(0, 0, 0, 0);//右边矩形
      m_TWRect = new Rect(0, 0, 0, 0);//记录文字宽高的矩形
      setBackgroundColor(getResources().getColor(android.R.color.holo_green_dark));
   }

   @Override
   public boolean onTouchEvent(MotionEvent event)
   {
      switch (event.getAction() & event.getActionMasked())
      {
         case MotionEvent.ACTION_DOWN:
            m_ActDownPX = event.getX();
            float y = event.getY();
            if (Math.abs(m_Offset) == .5f * getWidth())
            {
               if (!(y > 0 && y < getHeight())) break;
               if (m_ActDownPX > 0 && m_ActDownPX < .5f * getWidth() && m_Offset > 0)
               {	//点击左侧菜单,增加一个该view到父容器
                  int w = SwipeItemView.this.getWidth();
                  int h = SwipeItemView.this.getHeight();
                  if (!(getParent() instanceof LinearLayout)) break;
                  LinearLayout.LayoutParams lp1 = (LinearLayout.LayoutParams) SwipeItemView.this.getLayoutParams();
                  LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(w, h);
                  lp.setMargins(0, lp1.topMargin, 0, 0);
                  LinearLayout ll = (LinearLayout) SwipeItemView.this.getParent();
                  SwipeItemView view = new SwipeItemView(getContext());
                  view.setLayoutParams(lp);
                  ll.addView(view, ll.getChildCount() - 1);
               }
               if (m_ActDownPX > .5f * getWidth() && m_ActDownPX < getWidth() && m_Offset < 0)
               {	//点击右侧菜单,从父容器中删除该view
                  ViewGroup ll = (ViewGroup) SwipeItemView.this.getParent();
                  ll.removeView(SwipeItemView.this);
               }
            }
            break;
         case MotionEvent.ACTION_MOVE: //计算触摸滑动的偏移量
            m_Lock.lock();
            if (Math.abs(m_Offset + event.getX() - m_ActDownPX) <= .5f * getWidth())
            {
               m_Offset += event.getX() - m_ActDownPX;
               m_ActDownPX = event.getX();
               postInvalidate();
            }
            m_Lock.unlock();
            break;
         case MotionEvent.ACTION_UP:
            if (m_Offset == 0) break;
            if (m_Animation != null)//设置停止触摸后的偏移动画,偏移到指定位置。
            {
               m_Animation.cancel();
               m_Animation = null;
            }

            if (Math.abs(m_Offset) <= .2f * getWidth())
            {
               m_Animation = new Animation()
               {
                  float offset = m_Offset;

                  @Override
                  protected void applyTransformation(float interpolatedTime, Transformation t)
                  {
                     m_Offset = offset * (1 - interpolatedTime);
                     postInvalidate();//重绘
                  }
               };
               m_Animation.setDuration(120);
               startAnimation(m_Animation);
            } else
            {
               if (m_Offset > 0)
               {
                  m_Animation = new Animation()
                  {
                     float offset = m_Offset;
                     float gap = .5f * getWidth() - m_Offset;

                     @Override
                     protected void applyTransformation(float interpolatedTime, Transformation t)
                     {
                        m_Offset = offset + gap * interpolatedTime;
                        postInvalidate();
                     }
                  };
                  m_Animation.setDuration(120);
                  startAnimation(m_Animation);
               } else
               {
                  m_Animation = new Animation()
                  {
                     float offset = m_Offset;
                     float gap = -.5f * getWidth() - m_Offset;

                     @Override
                     protected void applyTransformation(float interpolatedTime, Transformation t)
                     {
                        m_Offset = offset + gap * interpolatedTime;
                        postInvalidate();
                     }
                  };
                  m_Animation.setDuration(120);
                  startAnimation(m_Animation);
               }
            }
            break;
         default:
            break;
      }
      return true;
   }

   @Override
   protected void onDraw(Canvas c)
   {
      super.onDraw(c);
      m_Lock.lock();
      m_CRect.set(m_Offset, 0, getWidth() + m_Offset, getHeight());
      Paint.FontMetricsInt fmi = m_Paint.getFontMetricsInt();
      float baseLine = m_CRect.top + ((m_CRect.bottom - m_CRect.top) - (fmi.bottom - fmi.top)) / 2f - fmi.top;
      m_Paint.setTextAlign(Paint.Align.CENTER);
      //center text
      m_Paint.setColor(Color.BLACK);
      c.drawText("SwipeItemView", m_CRect.centerX(), baseLine, m_Paint);

      if (m_Offset > 0)
      {
         //left text
         m_Paint.setColor(Color.DKGRAY);
         m_LRect.set(0, 0, m_Offset, getHeight());
         c.drawRect(m_LRect, m_Paint);

         m_Paint.getTextBounds(leftTxt, 0, leftTxt.length(), m_TWRect);
         if (Math.abs(m_Offset) >= m_TWRect.width())
         {
            m_Paint.setColor(Color.WHITE);
            c.drawText(leftTxt, m_LRect.centerX(), baseLine, m_Paint);
         }
      } else if (m_Offset < 0)
      {
         //right text
         m_Paint.setColor(Color.RED);
         m_RRect.set(getWidth() - Math.abs(m_Offset), 0, getWidth(), getHeight());
         c.drawRect(m_RRect, m_Paint);

         m_Paint.getTextBounds(rightTxt, 0, rightTxt.length(), m_TWRect);
         if (Math.abs(m_Offset) >= m_TWRect.width())
         {
            m_Paint.setColor(Color.WHITE);
            c.drawText(rightTxt, m_RRect.centerX(), baseLine, m_Paint);
         }
      }

      m_Lock.unlock();
   }

   private String leftTxt = "L ITEM";
   private String rightTxt = "R ITEM";
   private ReentrantLock m_Lock = new ReentrantLock();
   private RectF m_CRect;
   private RectF m_LRect;
   private RectF m_RRect;
   private Rect m_TWRect;
   private Paint m_Paint;
   float m_ActDownPX;
   private Animation m_Animation;
   private float m_Offset = 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值