Android 사용자 정의 View 모방 1 호 점 수직 스크롤 광고 줄 코드 구현

효과 도 전시,그림 이 약간 끊 기 고 인내심 을 가지 고 회 의 를 보면 원래 의 프로그램 이 매우 유창 하 다.

실현 절차:
성명 변수
4.567917.화필,텍스트 크기 와 좌 표를 초기 화 합 니 다.
  • onMeasure()적합 wrapcontent 의 너비
  • onDraw()는 좌표 에 따라 두 단락 의 텍스트 를 그립 니 다
  • 감청 클릭 이벤트
  • Activity 에서 클릭 이벤트 실현
  • 실현 원리(좌표 변환 원리):전체 과정 은 좌표 Y 의 증가 와 교환 을 바탕 으로 처리 되 고 Y 값 은 endY 까지 증가 한 다음 에 교환 논 리 를 한다.

    단계 1:성명 변수
    1 호 점 은 두 마디 의 구 르 기 때문에 우리 도 두 마디 로 이 루어 진다.
    
    private Paint mPaint;
    private float x, startY, endY, firstY, nextStartY, secondY;
    //  View            ,                
    private String[] text = {"    :  3.3 >>>", "  :    >>>"};
    private float textWidth, textHeight;
    //    
    private float speech = 0;
    private static final int CHANGE_SPEECH = 0x01;
    //       
    private boolean isScroll = false;
    단계 2:화필,텍스트 크기,좌표 초기 화
    첫 번 째 말 을 기준 으로 컨트롤 의 너비 와 높이 기준 을 하 다.
    
    //     
    mPaint = new Paint();
    mPaint.setColor(Color.RED);
    mPaint.setTextSize(30);
    //       ,        
    Rect rect = new Rect();
    mPaint.getTextBounds(text[0], 0, text[0].length(), rect);
    textWidth = rect.width();
    textHeight = rect.height();
    //     x,y  
    //             ,         ,     5px
    x = getX() + getPaddingLeft();
    startY = getTop() + textHeight + getPaddingTop() - 5;
    //     x,y  
    endY = startY + textHeight + getPaddingBottom();
    //          y  
    //             ,         ,     5px
    nextStartY = getTop() - 5;
    //       
    firstY = startY;
    secondY = nextStartY;
    STEP 3:onMeasure()wrapcontent 의 너비
    사용자 정의 View 를 배 웠 다 면 아래 코드 는 익숙 할 것 입 니 다.바로 warp 에 맞 는 것 입 니 다.content 템 플 릿 코드:
    
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
     super.onMeasure(widthMeasureSpec, heightMeasureSpec);
     int width = measureWidth(widthMeasureSpec);
     int height = measureHeight(heightMeasureSpec);
     setMeasuredDimension(width, height);
    }
    private int measureHeight(int heightMeasureSpec) {
     int result = 0;
     int size = MeasureSpec.getSize(heightMeasureSpec);
     int mode = MeasureSpec.getMode(heightMeasureSpec);
     if (mode == MeasureSpec.EXACTLY) {
      result = size;
     } else {
      result = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
      if (mode == MeasureSpec.AT_MOST) {
       result = Math.min(result, size);
      }
     }
     return result;
    }
    private int measureWidth(int widthMeasureSpec) {
     int result = 0;
     int size = MeasureSpec.getSize(widthMeasureSpec);
     int mode = MeasureSpec.getMode(widthMeasureSpec);
     if (mode == MeasureSpec.EXACTLY) {
      result = size;
     } else {
      result = (int) (getPaddingLeft() + getPaddingRight() + textWidth);
      if (mode == MeasureSpec.AT_MOST) {
       result = Math.min(result, size);
      }
     }
     return result;
    }
    STEP 4:onDraw()는 좌표 에 따라 두 단락 의 Text 를 그립 니 다.(복구 됨:Text 가 멈 췄 을 때 반 짝 이 는 bug)
    Handler 를 통 해서 속 도 를 바 꿔 요.
    isScroll 자 물 쇠 를 통 해 Handler 를 한 번 만 변경 하도록 제어 합 니 다.
    invalidate 를 통 해 두 마디 의 글 자 를 계속 다시 그립 니 다.
    
    @Override
    protected void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     //    
     if (!isScroll) {
      mHandler.sendEmptyMessageDelayed(CHANGE_SPEECH, 2000);
      isScroll = true;
     }
     canvas.drawText(text[0], x, startY, mPaint);
     canvas.drawText(text[1], x, nextStartY, mPaint);
     startY += speech;
     nextStartY += speech;
     //  View    
     if (startY > endY || nextStartY > endY) {
      if (startY > endY) {
       //          
       startY = secondY;
       nextStartY = firstY;
      } else if (nextStartY > endY) {
       //          
       startY = firstY;
       nextStartY = secondY;
      }
      speech = 0;
      isScroll = false;
     }
     invalidate();
    }
    
    private Handler mHandler = new Handler() {
     @Override
     public void handleMessage(Message msg) {
      super.handleMessage(msg);
      switch (msg.what) {
       case CHANGE_SPEECH:
        speech = 1f;
        break;
      }
     }
    };
    STEP 5:감청 클릭 이벤트(복구 됨:클릭 이벤트 가 어 지 러 운 문제)
    사용자 정의 View 에 dispatchTouchEvent 를 다시 쓰 고 클릭 이 벤트 를 처리 합 니 다.이것 도 템 플 릿 코드 입 니 다.
    
    public onTouchListener listener;
    public interface onTouchListener {
     void touchListener(String s);
    }
    public void setListener(onTouchListener listener) {
     this.listener = listener;
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
     switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
      case MotionEvent.ACTION_MOVE:
       //    
       if (listener != null) {
        if (startY >= firstY && nextStartY < firstY) {
         listener.touchListener(text[0]);
        } else if (nextStartY >= firstY && startY < firstY) {
         listener.touchListener(text[1]);
        }
       }
       break;
     }
     return true;
    }
    STEP 6:Activity 에서 클릭 이벤트 구현
    
    public class VerTextViewActivity extends AppCompatActivity {
     @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_ver_text_view);
      VerTextView tv_ver = (VerTextView) findViewById(R.id.tv_ver);
      tv_ver.setListener(new VerTextView.onTouchListener() {
       @Override
       public void touchListener(String s) {
        Toast.makeText(VerTextViewActivity.this, s, Toast.LENGTH_LONG).show();
       }
      });
     }
    }
    레이아웃 파일
    
    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="horizontal">
     <ImageView
      android:layout_width="120dp"
      android:layout_height="30dp"
      android:background="@drawable/vertextview" />
     <com.handsome.app3.Custom.VerTextView.VerTextView
      android:id="@+id/tv_ver"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:background="#ffffff"
      android:padding="8dp" />
    </LinearLayout>
    전체 클래스 의 원본 코드:
    
    /**
     * =====  =====
     *    
     * =====  =====
     * 2016/10/11.
     */
    public class VerTextView extends View {
     private Paint mPaint;
     private float x, startY, endY, firstY, nextStartY, secondY;
     //  View            ,                
     private String[] text = {"    :  3.3 >>>", "  :    >>>"};
     private float textWidth, textHeight;
     //    
     private float speech = 0;
     private static final int CHANGE_SPEECH = 0x01;
     //       
     private boolean isScroll = false;
     private Handler mHandler = new Handler() {
      @Override
      public void handleMessage(Message msg) {
       super.handleMessage(msg);
       switch (msg.what) {
        case CHANGE_SPEECH:
         speech = 1f;
         break;
       }
      }
     };
     public VerTextView(Context context, AttributeSet attrs) {
      super(context, attrs);
      //     
      mPaint = new Paint();
      mPaint.setColor(Color.RED);
      mPaint.setTextSize(30);
      //       ,        
      Rect rect = new Rect();
      mPaint.getTextBounds(text[0], 0, text[0].length(), rect);
      textWidth = rect.width();
      textHeight = rect.height();
      //     x,y  
      //             ,         ,     5px
      x = getX() + getPaddingLeft();
      startY = getTop() + textHeight + getPaddingTop() - 5;
      //     x,y  
      endY = startY + textHeight + getPaddingBottom();
      //          y  
      //             ,         ,     5px
      nextStartY = getTop() - 5;
      //       
      firstY = startY;
      secondY = nextStartY;
     }
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
      super.onMeasure(widthMeasureSpec, heightMeasureSpec);
      int width = measureWidth(widthMeasureSpec);
      int height = measureHeight(heightMeasureSpec);
      setMeasuredDimension(width, height);
     }
     private int measureHeight(int heightMeasureSpec) {
      int result = 0;
      int size = MeasureSpec.getSize(heightMeasureSpec);
      int mode = MeasureSpec.getMode(heightMeasureSpec);
      if (mode == MeasureSpec.EXACTLY) {
       result = size;
      } else {
       result = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
       if (mode == MeasureSpec.AT_MOST) {
        result = Math.min(result, size);
       }
      }
      return result;
     }
     private int measureWidth(int widthMeasureSpec) {
      int result = 0;
      int size = MeasureSpec.getSize(widthMeasureSpec);
      int mode = MeasureSpec.getMode(widthMeasureSpec);
      if (mode == MeasureSpec.EXACTLY) {
       result = size;
      } else {
       result = (int) (getPaddingLeft() + getPaddingRight() + textWidth);
       if (mode == MeasureSpec.AT_MOST) {
        result = Math.min(result, size);
       }
      }
      return result;
     }
     @Override
     protected void onDraw(Canvas canvas) {
      super.onDraw(canvas);
      //    
      if (!isScroll) {
       mHandler.sendEmptyMessageDelayed(CHANGE_SPEECH, 2000);
       isScroll = true;
      }
      canvas.drawText(text[0], x, startY, mPaint);
      canvas.drawText(text[1], x, nextStartY, mPaint);
      startY += speech;
      nextStartY += speech;
      //  View    
      if (startY > endY || nextStartY > endY) {
       if (startY > endY) {
        //          
        startY = secondY;
        nextStartY = firstY;
       } else if (nextStartY > endY) {
        //          
        startY = firstY;
        nextStartY = secondY;
       }
       speech = 0;
       isScroll = false;
      }
      invalidate();
     }
     public onTouchListener listener;
     public interface onTouchListener {
      void touchListener(String s);
     }
     public void setListener(onTouchListener listener) {
      this.listener = listener;
     }
     @Override
     public boolean dispatchTouchEvent(MotionEvent event) {
      switch (event.getAction()) {
       case MotionEvent.ACTION_DOWN:
       case MotionEvent.ACTION_MOVE:
        //    
        if (listener != null) {
         if (startY >= firstY && nextStartY < firstY) {
          listener.touchListener(text[0]);
         } else if (nextStartY >= firstY && startY < firstY) {
          listener.touchListener(text[1]);
         }
        }
        break;
      }
      return true;
     }
    }
    위 에서 말 한 것 은 소 편 이 소개 한 안 드 로 이 드 사용자 정의 View 가 1 호 점 수직 스크롤 광고 코드 를 실현 하 는 것 입 니 다.여러분 에 게 도움 이 되 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 메 시 지 를 남 겨 주세요.소 편 은 바로 답 해 드 리 겠 습 니 다.여기 서도 저희 사이트 에 대한 여러분 의 지지 에 감 사 드 립 니 다!

    좋은 웹페이지 즐겨찾기