catching of click in a custom view

10 views
Skip to first unread message

Саша Козловский

unread,
Nov 9, 2019, 6:38:25 PM11/9/19
to eyes-f...@googlegroups.com, prog...@freelists.org
Hello everybody. How I can correct catch click on custom view. In
telegram if android less then aight I can't accept or decline telegram
calls,because double tap not works for me for this. I compiled telegram
for android with android studio and solved this problem,but before
sending of pull request I need in advice,how correct to solve it.
1. As I noticed (i dont know why),in method performAccessibilityAction
action click is not appeared,so I set clickable as true in constructor
of this view and overrided method onPerformClick (is it a good way,or
it's better override onPopulateAccessibilityEvent and check,if type of
this event is click?). Also I at the end of onTouchAccessibilityEvent
return super version of this method,instead of dragging,as return by
developers of telegram. I modified class CallSwipeView.java. After
double tap it should be call listener.onDragComplete() method,which use
to accept or decline telegram call. Below you will see code of this
view. Thanks everybody very much for any help and any advices.

package org.telegram.ui.Components.voip;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityNodeInfo;

import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.BuildVars;
import org.telegram.messenger.FileLog;

import java.util.ArrayList;

public class CallSwipeViewextends View {

   private PaintarrowsPaint,pullBgPaint;
   private int[]arrowAlphas = {64,64,64};
   private ViewviewToDrag;
   private boolean dragging =false,dragFromRight;
   private float dragStartX;
   private RectFtmpRect =new RectF();
   private Listenerlistener;
   private Patharrow =new Path();
   private AnimatorSetarrowAnim;
   private boolean animatingArrows =false;
   private boolean canceled =false;

   public CallSwipeView(Context context) {
      super(context);
      init();
   }

   private void init() {
//this line was added by myself.
setClickable(true);
arrowsPaint =new Paint(Paint.ANTI_ALIAS_FLAG);
      arrowsPaint.setColor(0xFFFFFFFF);
      arrowsPaint.setStyle(Paint.Style.STROKE);
      arrowsPaint.setStrokeWidth(AndroidUtilities.dp(2.5f));
      pullBgPaint =new Paint(Paint.ANTI_ALIAS_FLAG);

      ArrayList<Animator> anims =new ArrayList<>();
      for (int i =0; i <arrowAlphas.length; i++) {
         ArrowAnimWrapper aaw =new ArrowAnimWrapper(i);
         ObjectAnimator anim =
ObjectAnimator.ofInt(aaw,"arrowAlpha",64,255,64);
         anim.setDuration(700);
         anim.setStartDelay(200 * i);
         //anim.setRepeatCount(ValueAnimator.INFINITE); anims.add(anim);
      }
      arrowAnim =new AnimatorSet();
      arrowAnim.playTogether(anims);
      arrowAnim.addListener(new AnimatorListenerAdapter() {
         private long startTime;
         private Runnablerestarter =new Runnable() {
            @Override public void run() {
               if (arrowAnim !=null) {
                  arrowAnim.start();
               }
            }
         };

         @Override public void onAnimationEnd(Animator animation) {
            if (System.currentTimeMillis() -startTime <
animation.getDuration() /4) {
               if (BuildVars.LOGS_ENABLED) {
                  FileLog.w("Not repeating animation because previous
loop was too fast");
               }
               return;
            }
            if (!canceled &&animatingArrows)
               post(restarter);
         }

         @Override public void onAnimationCancel(Animator animation) {
            canceled =true;
         }

         @Override public void onAnimationStart(Animator animation) {
            startTime = System.currentTimeMillis();
         }
      });
   }

   @Override protected void onDetachedFromWindow() {
      super.onDetachedFromWindow();
      if (arrowAnim !=null) {
         canceled =true;
         arrowAnim.cancel();
         arrowAnim =null;
      }
   }

   public void setColor(int color) {
      pullBgPaint.setColor(color);
      pullBgPaint.setAlpha(0xB2);
   }

   public void setViewToDrag(View viewToDrag,boolean dragFromRight) {
      this.viewToDrag = viewToDrag;
      this.dragFromRight = dragFromRight;
      updateArrowPath();
   }

   public void setListener(Listener listener) {
      this.listener = listener;
   }

   private int getDraggedViewWidth() {
      return getHeight();
   }

   @Override public boolean onTouchEvent(MotionEvent ev) {
      if (!isEnabled())
         return false;
      if (ev.getAction() == MotionEvent.ACTION_DOWN) {
         if ((!dragFromRight && ev.getX() < getDraggedViewWidth()) ||
(dragFromRight && ev.getX() > getWidth() - getDraggedViewWidth())) {
dragging =true;
            dragStartX = ev.getX();
            getParent().requestDisallowInterceptTouchEvent(true);
            listener.onDragStart();
            stopAnimatingArrows();
         }
      }else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
         viewToDrag.setTranslationX(Math.max(dragFromRight ?
-(getWidth() - getDraggedViewWidth()) :0, Math.min(ev.getX()
-dragStartX,dragFromRight ?0 : (getWidth() - getDraggedViewWidth()))));
         invalidate();
      }else if (ev.getAction() == MotionEvent.ACTION_UP ||
ev.getAction() == MotionEvent.ACTION_CANCEL) {
         if (Math.abs(viewToDrag.getTranslationX()) >= getWidth() -
getDraggedViewWidth() && ev.getAction() == MotionEvent.ACTION_UP) {
            listener.onDragComplete();
         }else {
            listener.onDragCancel();
viewToDrag.animate().translationX(0).setDuration(200).start();
            invalidate();
            startAnimatingArrows();
            dragging =false;
         }
      }
//i return super.ontouchEvent instead of value of dragging
variable,because as i understand,talkback not get any events for all
views of this type in this case.
            return super.onTouchEvent(ev);
   }

public void stopAnimatingArrows() {
      animatingArrows =false;
   }

   public void startAnimatingArrows() {
      if (animatingArrows ||arrowAnim ==null)
         return;
      animatingArrows =true;
      if (arrowAnim !=null) {
         arrowAnim.start();
      }
   }

   public void reset() {
      if (arrowAnim ==null ||canceled) {
         return;
      }
      listener.onDragCancel();
viewToDrag.animate().translationX(0).setDuration(200).start();
      invalidate();
      startAnimatingArrows();
      dragging =false;
   }

   @Override protected void onDraw(Canvas canvas) {
      if (viewToDrag.getTranslationX() !=0) {
         if (dragFromRight) {
            tmpRect.set(getWidth() +viewToDrag.getTranslationX() -
getDraggedViewWidth(),0, getWidth(), getHeight());
         }else {
            tmpRect.set(0,0,viewToDrag.getTranslationX() +
getDraggedViewWidth(), getHeight());
         }
         canvas.drawRoundRect(tmpRect, getHeight() /2, getHeight()
/2,pullBgPaint);
      }
      canvas.save();
      if (dragFromRight) {
         canvas.translate(getWidth() - getHeight() -
AndroidUtilities.dp(12 +6), getHeight() /2);
      }else {
         canvas.translate(getHeight() + AndroidUtilities.dp(12),
getHeight() /2);
      }
      float offsetX = Math.abs(viewToDrag.getTranslationX());
      for (int i =0; i <3; i++) {
         float masterAlpha =1;
         if (offsetX > AndroidUtilities.dp(16 * i)) {
            masterAlpha =1 - Math.min(1, Math.max(0, (offsetX - i *
AndroidUtilities.dp(16)) / AndroidUtilities.dp(16)));
         }
         arrowsPaint.setAlpha(Math.round(arrowAlphas[i] * masterAlpha));
         canvas.drawPath(arrow,arrowsPaint);
         canvas.translate(AndroidUtilities.dp(dragFromRight ? -16 :16),0);
      }
      canvas.restore();
      invalidate();
   }

   private void updateArrowPath() {
      arrow.reset();
      int size = AndroidUtilities.dp(6);
      if (dragFromRight) {
         arrow.moveTo(size, -size);
         arrow.lineTo(0,0);
         arrow.lineTo(size, size);
      }else {
         arrow.moveTo(0, -size);
         arrow.lineTo(size,0);
         arrow.lineTo(0, size);
      }
   }

   @Override public void
onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info){
      super.onInitializeAccessibilityNodeInfo(info);
      info.addAction(AccessibilityNodeInfo.ACTION_CLICK) ;
   }
//I haven't action click in this method in android seven. Why?
   @Override public boolean performAccessibilityAction(int action,
Bundle arguments){
      if(action==AccessibilityNodeInfo.ACTION_CLICK && isEnabled()){
         listener.onDragComplete();
      }
      return super.performAccessibilityAction(action, arguments);
   }
//this method was added by myself. Is this a good way to fix
accessibility problem,or it's better to use onPopulateAccessibilityEvent
instead?
   @Override public boolean performClick() {
      if(isEnabled()) {
         listener.onDragComplete();
      }
      return super.performClick();
   }
   public interface Listener {
   void onDragComplete();
      void onDragStart();
      void onDragCancel();
   }

   private class ArrowAnimWrapper {

      private int index;

      public ArrowAnimWrapper(int value) {
         index = value;
      }

      public int getArrowAlpha() {
         return arrowAlphas[index];
      }

      public void setArrowAlpha(int value) {
         arrowAlphas[index] = value;
      }
   }
}

Reply all
Reply to author
Forward
0 new messages