안 드 로 이 드 모방 경 동 첫 페이지 윤방 문자 효과

15631 단어 Android윤파주마등
경 동 클 라 이언 트 의 라운드 문자 효과:

다음 에 실 현 될 것 은 뒤에 구 르 는 문자(앞 에 있 는 것 은 ImageView 나 TextView 로 이 루어 지면 됩 니 다)입 니 다.실 현 된 효 과 를 보 세 요.

사고의 방향 을 실현 하 다.

위의 그림 은 대략적인 사고 일 뿐 이 고 실현 하려 면 더 많은 세부 사항 을 보완 해 야 한다.다음 에 한 걸음 한 걸음 이 효 과 를 실현 할 것 이다.
1.패 키 징 데이터 소스:그림 에서 볼 수 있 듯 이 윤 방 의 문 자 는 두 부분 으로 나 뉘 는데 이 를 접두사 와 내용 이 라 고 부 릅 니 다.그리고 실제 사용 과정 에서 윤 방 도 를 클릭 하면 페이지 를 넘 어야 합 니 다.그리고 대부분 WebView 여야 합 니 다.클릭 할 때 얻 을 내용 이 바로 링크 라 고 설정 하면 데이터 소스 의 구 조 는 분명 합 니 다.
ADEnity클래스 를 만 들 고 기본 적 인 방법 을 보완 합 니 다.코드 는 다음 과 같 습 니 다.

public class ADEnity {
 private String mFront ; //     
 private String mBack ; //     
 private String mUrl ;//     

 public ADEnity(String mFront, String mBack,String mUrl) {
  this.mFront = mFront;
  this.mBack = mBack;
  this.mUrl = mUrl;
 }

 public String getmUrl() {
  return mUrl;
 }

 public void setmUrl(String mUrl) {
  this.mUrl = mUrl;
 }

 public String getmFront() {
  return mFront;
 }

 public void setmFront(String mFront) {
  this.mFront = mFront;
 }

 public String getmBack() {
  return mBack;
 }

 public void setmBack(String mBack) {
  this.mBack = mBack;
 }
}
2.다음은 이 사용자 정의 View 를 맞 추 는 것 입 니 다.먼저 생각 을 정리 하고 구조 도 를 보 세 요.

이 사용자 정의 View 를 실현 하 는 모든 매개 변 수 는 위 표 에 열거 되 어 있 습 니 다.대부분의 매개 변 수 는 쉽게 이해 할 수 있 습 니 다.개별 매개 변 수 를 추가 하 는 것 이 필요 합 니 다.예 를 들 어 문자 에 들 어 가 는 세로 좌 표를 초기 화 하 는 지,문자 가 이동 중 에 있 는 지,그 후의 내용 은 상세 하 게 서술 할 것 입 니 다.그림 을 그리 기 전에 기본 적 인 지식 을 알 아야 합 니 다.바로 문 자 를 그 리 는 방법 에 관 한 것 입 니 다.그 안에 처리 해 야 할 세부 사항 이 많 습 니 다.

방법 은 모두 이해 하기 쉽 습 니 다.지정 한 문자열(범 위 를 지정 할 수 있 습 니 다)을 그 리 는 것 은 좌표( x , y )에 있 습 니 다.그러나 그 중의x,y은 우리 가 이해 하 는 것 이 아니 라 문자 왼쪽 상단 의 좌표 점 입 니 다.그 중의 x 좌 표 는Paint의 속성 에 따라 변 경 될 수 있 습 니 다.기본 적 인 x 는 문자 의 왼쪽 좌표 입 니 다.만약Paint에 설정 되 어 있다 면paint.setTextAlign(Paint.Align.CENTER).바로 문자 의 중심 위치 입 니 다.Y좌 표 는 문자baseliney좌표 입 니 다.문 자 를 그 리 는 baseline:
그림 으로 얘 기해 주세요.

그림 에서 파란색 선 은 바로baseline이다.그 가 상단 좌표 도 아 닌 밑부분 좌표 임 을 알 수 있다.그러면 우리 가 문 자 를 그 릴 때 문 자 를 한가운데 에 그 리 려 고 하 는 것 이 분명 하 다.이때paint.getTextBound()방법getTextBounds(String text, int start, int end, Rect bounds)을 도입 하여Rect대상 에 게 전달 하고 이 방법 을 사용 하면 이 rect 대상 을 채 울 것 이다.채 워 진 내용 은 그 려 진 텍스트 가baseline의 오프셋 좌표 에 비해 이 Rect 에baseline의 좌 표를 더 해서 그 려 진 것 입 니 다.

그러나 사실 그의 수 치 는(2,-25,76,3)일 뿐 baseline 의 위치 에 비해 그림 을 그 리 는 것 이 이해 하기 쉽다.

텍스트 를 중간 에 그 리 려 면 실제 baseline 의 좌 표를 구성 요소 의 중심 에 텍스트 중심,즉 그림 속 상자 의 중간 좌 표를 baseline 의 오프셋 값 에 비해 그 려 야 합 니 다.>그러면 텍스트 를 중간 에 그 리 려 면 baseline 의 좌 표를 실제 그 리 는 것 은 그룹 부품 의 중심 이 어야 합 니 다.여기에 텍스트 중심(즉 그림 속 상자 의 중간 좌표)을 baseline 의 오프셋 값 에 비해 그 려 야 합 니 다.

이 그림 은 실제 텍스트 를 그 리 는 좌표 와 구성 요소 중심 좌표 의 관 계 를 잘 이해 할 수 있 을 것 입 니 다.오프셋 값 에 대한 계산 은 일반적인 기하학 적 계산 방법 에 따라 구성 요소 의 중심 좌표+오프셋 값 의 절대 값=baseline 좌표(즉,실제 그 리 는 좌표)여야 합 니 다.그러나 상자 의 좌표 값 은 모두 baseline 에 비해 계산 되 기 때문에 top 은 마이너스 이 고 botton 은 플러스 입 니 다.그러면 이 오프셋 값 은(top+bottom)/2 로 직접 표시 할 수 있 습 니 다.못 알 아 본 학생 은 약 도 를 그 릴 수 있 습 니 다.top=-25,bottom=3 으로 계산 하여 결과 가 일치 하 는 지 확인 할 수 있 습 니 다.
위의 이 해 를 통 해 우 리 는 문 자 를 정확하게 그 리 는 방법 도 확정 되 었 다.
구성 요소 의 높이 int mHeight,텍스트 외곽 상자 Rect bound 를 획득 한 경우
그림%1 개의 캡 션 을 편 집 했 습 니 다.

 mHeight / 2 - (bound.top + bound.bottom) / 2
//     mY       
//    
//mheight /2 = mY + (bound.top + bound.bottom) / 2 ;
텍스트 를 최고점 으로 스크롤

mY == 0 - bound.bottom
//     mY     ,            
//    
//mY + bound.bottom = 0 ;
텍스트 가 가장 낮은 곳 으로 스크롤 되 었 습 니 다.마침 구성 요소 에서 꺼 졌 습 니 다.

 mY = mHeight - indexBound.top;
//     mY     ,            
//    
//mY + bound.top = mHeight ;
문자 와 경계 상황 을 정확하게 그 리 는 좌 표를 알 게 되 었 습 니 다.다음은 문 자 를 그 리 는 절차 입 니 다.
우선 데 이 터 를 초기 화하 고 기본 값 을 설정 합 니 다.

//      
private void init() {
 mDuration = 500;
 mInterval = 1000;
 mIndex = 0;
 mPaintFront = new Paint();
 mPaintFront.setAntiAlias(true);
 mPaintFront.setDither(true);
 mPaintFront.setTextSize(30);


 mPaintBack = new Paint();
 mPaintBack.setAntiAlias(true);
 mPaintBack.setDither(true);
 mPaintBack.setTextSize(30);

}

앞의 서술 에서 우 리 는 처음에 들 어 갔 을 때 문 자 는 구성 요소 의 아래쪽 에 있어 야 한 다 는 것 을 알 고 있 습 니 다.그러나 이 값 은 구성 요소 의 높이 와 현재 표 시 된 문 자 를 가 져 와 서 판단 해 야 하기 때문에 onDraw 에 넣 어서 이 값 을 초기 화 해 야 합 니 다.따라서 앞의 속성 이 초기 화 되 었 는 지 여 부 를 판단 하고 mY==0 이 초기 화 되 지 않 았 을 때 mY 에 값 을 부여 해 야 합 니 다.
다음은 온 드 로 내 처리.
현재 데이터 가 져 오기

//       
ADEnity model = mTexts.get(mIndex);
String font = model.getmFront();
String back = model.getmBack();
//        
Rect indexBound = new Rect();
mPaintFront.getTextBounds(font, 0, font.length(), indexBound);

//       
Rect contentBound = new Rect();
mPaintBack.getTextBounds(back, 0, back.length(), contentBound);

mY 초기 화

if (mY == 0 && hasInit == false) {
 mY = getMeasuredHeight() - indexBound.top;
 hasInit = true;
}
경계 상황 처리
/

/      
if (mY == 0 - indexBound.bottom) {
 Log.i(TAG, "onDraw: " + getMeasuredHeight());
 mY = getMeasuredHeight() - indexBound.top;//    
 mIndex++;//      
}
//     
if (mY == getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
 isMove = false;//    
 Timer timer = new Timer();
 timer.schedule(new TimerTask() {
  @Override
  public void run() {
   postInvalidate();//    
   isMove = true;//     true
  }
 }, mInterval);//            
}
            
mY -= 1;//         ,        
//      
if (mIndex == mTexts.size()) {
 mIndex = 0;
}
//           ,     
//         ,            ,        1  
if (isMove) {
 postInvalidateDelayed(mDuration / getMeasuredHeight());
}
            ,          
public interface onClickLitener {
 public void onClick(String mUrl);
}

private onClickLitener onClickLitener;

public void setOnClickLitener(TextViewAd.onClickLitener onClickLitener) {
 this.onClickLitener = onClickLitener;
}
//  onTouchEvent  ,     true,                   
@Override
public boolean onTouchEvent(MotionEvent event) {
 int action = event.getAction();

 switch (action) {
  case MotionEvent.ACTION_DOWN:
   //    ,            
   if (onClickLitener != null) {
    onClickLitener.onClick(mTexts.get(mIndex).getmUrl());
   }

   break;
 }
 return true;
}
             
//     
public void setmTexts(List mTexts) {
 this.mTexts = mTexts;
}

//           
public void setmInterval(int mInterval) {
 this.mInterval = mInterval;
}

//             
public void setmDuration(int mDuration) {
 this.mDuration = mDuration;
}

//         
public void setFrontColor(int mFrontColor) {
 mPaintFront.setColor(mFrontColor);
}

//         
public void setBackColor(int mBackColor) {
 mPaintBack.setColor(mBackColor);
}
                attrs.xml                   ,       ,      copy  View   xml   copy    ,  as     ,                .(      ).
      ADTextView   ,    
package com.qiyuan.jindongshangcheng.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.TextView;

import com.qiyuan.jindongshangcheng.enity.ADEnity;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

/**
 * Created by huanghaojie on 2016/9/30.
 */

public class TextViewAd extends TextView {

 private int mDuration; //             
 private int mInterval; //               
 private List<ADEnity> mTexts; //        
 private int mY = 0; //   Y  
 private int mIndex = 0; //       
 private Paint mPaintBack; //       
 private Paint mPaintFront; //       
 private boolean isMove = true; //      
 private String TAG = "ADTextView";
 private boolean hasInit = false;//                

 public interface onClickLitener {
  public void onClick(String mUrl);
 }

 private onClickLitener onClickLitener;

 public void setOnClickLitener(TextViewAd.onClickLitener onClickLitener) {
  this.onClickLitener = onClickLitener;
 }

 public TextViewAd(Context context) {
  this(context, null);
 }

 public TextViewAd(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }
 //  onTouchEvent  ,     true,                   
 @Override
 public boolean onTouchEvent(MotionEvent event) {
  int action = event.getAction();

  switch (action) {
   case MotionEvent.ACTION_DOWN:
    //    ,            
    if (onClickLitener != null) {
     onClickLitener.onClick(mTexts.get(mIndex).getmUrl());
    }

    break;
  }
  return true;
 }

 //     
 public void setmTexts(List mTexts) {
  this.mTexts = mTexts;
 }

 //           
 public void setmInterval(int mInterval) {
  this.mInterval = mInterval;
 }

 //             
 public void setmDuration(int mDuration) {
  this.mDuration = mDuration;
 }

 //         
 public void setFrontColor(int mFrontColor) {
  mPaintFront.setColor(mFrontColor);
 }

 //         
 public void setBackColor(int mBackColor) {
  mPaintBack.setColor(mBackColor);
 }

 //      
 private void init() {
  mDuration = 500;
  mInterval = 1000;
  mIndex = 0;
  mPaintFront = new Paint();
  mPaintFront.setAntiAlias(true);
  mPaintFront.setDither(true);
  mPaintFront.setTextSize(30);


  mPaintBack = new Paint();
  mPaintBack.setAntiAlias(true);
  mPaintBack.setDither(true);
  mPaintBack.setTextSize(30);

 }

 @Override
 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
  super.onSizeChanged(w, h, oldw, oldh);
  Log.i(TAG, "onSizeChanged: " + h);
 }

 @Override
 protected void onDraw(Canvas canvas) {
  if (mTexts != null) {
   Log.i(TAG, "onDraw: " + mY);
   //       
   ADEnity model = mTexts.get(mIndex);
   String font = model.getmFront();
   String back = model.getmBack();
   //        
   Rect indexBound = new Rect();
   mPaintFront.getTextBounds(font, 0, font.length(), indexBound);

   //       
   Rect contentBound = new Rect();
   mPaintBack.getTextBounds(back, 0, back.length(), contentBound);
   //                      ,                              ,
   //       onDraw        ,               ,   mY==0          mY  .
   if (mY == 0 && hasInit == false) {
    mY = getMeasuredHeight() - indexBound.top;
    hasInit = true;
   }
   //      
   if (mY == 0 - indexBound.bottom) {
    Log.i(TAG, "onDraw: " + getMeasuredHeight());
    mY = getMeasuredHeight() - indexBound.top;//    
    mIndex++;//      
   }
   canvas.drawText(back, 0, back.length(), (indexBound.right - indexBound.left) + 20, mY, mPaintBack);
   canvas.drawText(font, 0, font.length(), 10, mY, mPaintFront);
   //     
   if (mY == getMeasuredHeight() / 2 - (indexBound.top + indexBound.bottom) / 2) {
    isMove = false;//    
    Timer timer = new Timer();
    timer.schedule(new TimerTask() {
     @Override
     public void run() {
      postInvalidate();//    
      isMove = true;//     true
     }
    }, mInterval);//            
   }
   //            
   mY -= 1;//         ,        
   //      
   if (mIndex == mTexts.size()) {
    mIndex = 0;
   }
   //           ,     
   //         ,            ,        1  
   if (isMove) {
    postInvalidateDelayed(mDuration / getMeasuredHeight());
   }
  }

 }
}

     ?
1,  xml            
<?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="vertical">
 <com.qiyuan.jindongshangcheng.view.TextViewAd
  android:id="@+id/textad"
  android:layout_width="match_parent"
  android:layout_height="wrap_content" />

</LinearLayout>

2. MainActivity   
/**
 * Created by huanghaojie on 2016/9/30.
 */

public class MainActivity extends Activity {
 private TextViewAd textViewAd;
 private List<ADEnity> mList;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main4);
  textViewAd = (TextViewAd) findViewById(R.id.textad);
  mList = new ArrayList<>();
  for (int i = 0; i < 10; i++) {
   ADEnity adEnity = new ADEnity("  " + i, "  " + i, "http://www.baidu.com"+i);
   mList.add(adEnity);
  }
  textViewAd.setmTexts(mList);
  textViewAd.setFrontColor(Color.RED);
  textViewAd.setBackColor(Color.BLUE);
  textViewAd.setmDuration(1000);
  textViewAd.setmInterval(1000);
  textViewAd.setOnClickLitener(new TextViewAd.onClickLitener() {
   @Override
   public void onClick(String mUrl) {
    Toast.makeText(MainActivity.this,"   "+mUrl,Toast.LENGTH_LONG).show();
   }
  });
 }
}
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기