안 드 로 이 드 모방 매일 듣 기 좋 은 노래 자동 스크롤 view

최근 프로젝트 에 서 는 매일 듣 기 좋 은 노래 가 자동 으로 줄 을 구 르 는 것 과 같은 효 과 를 만들어 야 한다.먼저 안 드 로 이 드 가 굴 러 가 야 할 것 은 scroller 류 나 scrollto,scrollby 가 결합 되 었 거나 view.layot()방법 이나 애니메이션 을 사용 하 는 것 이 라 고 생각 했 습 니 다.하지만 순환 스크롤 을 하려 면 마지막 줄 에서 첫 줄 로 스크롤 하 는 것 이 효과 가 있 는 것 같 아서 해결 방법 이 좋 지 않 습 니 다.어찌 사건 만물 을 그 릴 수 있 는 캔버스 를 잊 었 겠 습 니까?좋아,기왕 찾 았 으 니 이 방안 을 써 라!하지만 매일 듣 기 좋 은 노래 는 수 동 으로 미 끄 러 지 는 효과 가 있어 글 을 쓰 지 않 은 것 같다.기왕 이렇게 된 바 에 야 스스로 써 라!실현 되 기 전에 매일 듣 기 좋 은 효 과 를 먼저 보 세 요.

본문
생각 1:미 끄 러 지 는 거 리 를 얻 고 얼마나 미 끄 러 졌 는 지 계산 한 다음 에 데 이 터 를 업데이트 합 니 다.실현 해 보 니 효과 가 별로 없 는 것 같다.
생각 2:우 리 는 그 가 구 르 는 것 이 한 줄 한 줄 구 르 는 것 임 을 알 수 있다.다만 구 르 는 속도 에 따라 구 르 는 줄 의 속 도 를 결정 할 뿐이다.그렇다면 스크롤 만 하면 일정 시간 한 줄 의 스크롤 을 한 다음 스크롤 속도 에 따라 업데이트 간격 을 결정 합 니 다.
응,어떻게 실현 할 지 생각 했 으 니 지금 코드 를 써 라.
먼저 클래스 를 써 서 TextView 를 계승 합 니 다.
VerticalScrollTextView.class

public class VerticalScrollTextView extends TextView implements Runnable{
 //      
 private Paint mContentPaint;
 //      
 private Paint mLinePaint;
 //          
 private Paint mRectPaint;
 //    
 private List<Sentence> mDataList;
 //  
 private int index = 0 ;
 //  view  
 private float mX;
 //  view  
 private float mY;
 //  view      
 private float middleY;
 //        
 private final static int DY = 80 ;
 //      
 private int mTextSize = 35;
 //         
 private int mBigTextSize = 45;
 //      
 private boolean isTouch = false ;
 //     view y   
 private float mLastY;
 //      
 private boolean isMoving;
 //          
 private long lastMoveTime;
 //       
 private VelocityTracker mVelocityTracker;
 //      
 private int mMaximumVelocity;
 //      
 private boolean isEmpty;

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

 public VerticalScrollTextView(Context context, AttributeSet attrs) {
 this(context, attrs,0);
 }

 public VerticalScrollTextView(Context context, AttributeSet attrs, int defStyleAttr) {
 super(context, attrs, defStyleAttr);
 //          
 mMaximumVelocity = ViewConfiguration.get(context)
  .getScaledMaximumFlingVelocity();
 init();
 }
 private void init(){
 setFocusable(true);
 setClickable(true);
 //         
 if(mDataList==null){
  mDataList = new ArrayList<>();
  Sentence sentence = new Sentence(0,"       ",0);
  mDataList.add(sentence);
  isEmpty = true ;
 }
 //       
 mContentPaint = new Paint();
 mContentPaint.setTextSize(mTextSize);
 mContentPaint.setAntiAlias(true);
 mContentPaint.setColor(Color.parseColor("#e5e2e2"));
 //   serif  
 mContentPaint.setTypeface(Typeface.SERIF);
 //       
 mContentPaint.setTextAlign(Paint.Align.CENTER);
 //       
 mLinePaint = new Paint();
 mLinePaint.setAntiAlias(true);
 mLinePaint.setStrokeWidth(1);
 mLinePaint.setColor(Color.WHITE);
 //        
 mRectPaint = new Paint();
 mLinePaint.setAntiAlias(true);
 mRectPaint.setColor(Color.parseColor("#66666666"));
 }

 @Override
 protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 //       -1,    ,    
 if (index == -1)
  return;
 Sentence sentence = mDataList.get(index);
 //        ,       ,   
 mContentPaint.setColor(Color.WHITE);
 mContentPaint.setTextSize(mBigTextSize);
 canvas.drawText(sentence.getName(), mX/2, middleY, mContentPaint);
 //                ,       
 if(!isEmpty&&isTouch){
  //            
  float baseLine = middleY-Math.abs(mContentPaint.ascent());
  //      
  canvas.drawRect(10.0f,baseLine-70,150.0f,baseLine,mRectPaint);
  //    
  canvas.drawLine(10.0f,baseLine,mX-10,baseLine,mLinePaint);
  //        
  mContentPaint.setTextSize(mTextSize);
  //      
  canvas.drawText(String.valueOf(index),85,baseLine-35,mContentPaint);
 }
 //   isEmpty
 isEmpty = false ;
 //         
 mContentPaint.setColor(Color.parseColor("#e5e2e2"));
 mContentPaint.setTextSize(mTextSize);
 //         ,             
 float tempY = middleY;
 //          
 for (int i = index - 1; i >= 0; i--) {
  tempY = tempY - DY;
  if (tempY < 0) {
  break;
  }
  Sentence preSentence = mDataList.get(i);
  canvas.drawText(preSentence.getName(), mX/2, tempY, mContentPaint);
 }
 tempY = middleY;
 //          
 for (int i = index + 1; i < mDataList.size(); i++) {
  tempY = tempY + DY;
  if (tempY > mY) {
  break;
  }
  Sentence nexeSentence = mDataList.get(i);
  canvas.drawText(nexeSentence.getName(), mX/2, tempY, mContentPaint);
 }
 //   isMoving,         
 isMoving = false ;
 }
 protected void onSizeChanged(int w, int h, int ow, int oh) {
 super.onSizeChanged(w, h, ow, oh);
 //  view    
 mX = w;
 mY = h;
 middleY = h * 0.5f;
 }
 public long updateIndex(int index) {
 if (index == -1)
  return -1;
 this.index=index;
 return index;
 }
 public List<Sentence> getDataList() {
 return mDataList;
 }
 public void setDataList(List<Sentence> mDataList){
 this.mDataList = mDataList ;
 }
 public void updateUI(){
 new Thread(this).start();
 }

 @Override
 public boolean onTouchEvent(MotionEvent event) {
 int action = event.getAction();
 switch (action){
  case MotionEvent.ACTION_DOWN:
  isTouch =true;
  mLastY = event.getY();
  break;
  case MotionEvent.ACTION_MOVE:
  //       
  initVelocityTrackerIfNotExists();
  mVelocityTracker.addMovement(event);
  mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
  //      。   100
  float velocity = mVelocityTracker.getYVelocity()==0?100:mVelocityTracker.getYVelocity();
  long currentTime = System.currentTimeMillis();
  //                     
  if(!isMoving&&currentTime-lastMoveTime>20000/Math.abs(velocity)){
   isMoving = true ;
   lastMoveTime = System.currentTimeMillis();
   float currentY = event.getY();
   float mMoveY = currentY - mLastY;
   //    -1    +1
   int newIndex = mMoveY>0?index - 1:index+1;
   //    
   newIndex=newIndex<0?mDataList.size()-1:newIndex>=mDataList.size()?0:newIndex;
   updateIndex(newIndex);
   invalidate();
   mLastY = currentY;
  }
  break;
  case MotionEvent.ACTION_UP:
  isTouch = false ;
  recycleVelocityTracker();
  break;
 }
 return super.onTouchEvent(event);
 }

 @Override
 public void run() {
 //           
 long time = 1000;
 //    
 int i=0;
 while (true) {
  //              
  if(!isTouch){
  //        
  long sleeptime = updateIndex(i);
  //  handle  ui
  mHandler.post(mUpdateResults);
  if (sleeptime == -1)
   return;
  try {
   Thread.sleep(time);
   i++;
   //                  
   if(i==getDataList().size())
   i=0;
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  }
 }
 }
 Handler mHandler = new Handler();
 Runnable mUpdateResults = new Runnable() {
 public void run() {
  invalidate();
 }
 };
 //       
 private void initVelocityTrackerIfNotExists() {
 if (mVelocityTracker == null) {
  mVelocityTracker = VelocityTracker.obtain();
 }
 }
 //  
 private void recycleVelocityTracker() {
 if (mVelocityTracker != null) {
  mVelocityTracker.recycle();
  mVelocityTracker = null;
 }
 }
}
사용자 정의 view 는 기본적으로 이 렇 습 니 다.우 리 는 정의 할 속성 을 attrs 에 쓸 수 있 습 니 다.여 기 는 쓰기 가 귀 찮 습 니 다.대략적인 사고방식 은 먼저 지 정 된 index 줄 의 가 사 를 그린 다음 에 index 위 줄 의 가 사 를 그린 다음 에 index 아래 줄 의 가 사 를 그 리 는 것 이다.그리고 handle 을 통 해 일정 시간 간격 으로 가사 줄 수 를 새로 고 칠 수 있 도록 스 레 드 를 새로 만 듭 니 다.그리고 onTouchEvent 에서 터치 스크롤 줄 수 를 처리 하고 현재 스크롤 속 도 를 가 져 와 업데이트 시간 간격 을 결정 합 니 다.터치 스크롤 리 셋 의 속 도 를 실현 합 니 다.기본적으로 이렇다.다른 것 은 주석 을 보십시오.
데이터 테스트 를 초기 화 하 는 Activity:
VerticalScrollTextActivity.class

public class VerticalScrollTextActivity extends Activity {
 VerticalScrollTextView mSampleView;
 String[] str = {"             ",
  "             ",
  "         ",
  "        ",
  "           ",
  "            ",
  "          ",
  "           ",
  "            ",
  "            ",
  "         ",
  "           ",
  "          ",
  "         ",
  "         ",
  "             ",
  "             ",
  "         ",
  "        ",
  "           ",
  "            ",
  "          ",
  "           ",
  "            ",
  "            ",
  "         ",
  "           ",
  "          ",
  "         ",
  "         "
 };
 @Override
 public void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.activity_main);
 mSampleView = (VerticalScrollTextView) findViewById(R.id.sampleView1);
 List lst=new ArrayList<>();
 for(int i=0;i<str.length;i++){
  Sentence sen=new Sentence(i,str[i],i+1202034);
  lst.add(i, sen);
 }
 mSampleView.setDataList(lst);
 mSampleView.updateUI();
 } 
}

가사 데 이 터 를 모 의 한 다음 setDataList 에서 updateUI()를 호출 하면 됩 니 다.
마지막 으로 레이아웃 파일 보기
activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent">

 <com.goach.lib.VerticalScrollTextView
 android:id="@+id/sampleView1"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:background="@drawable/bg"
 />
</RelativeLayout>
테스트 를 해 보면 우 리 는 효 과 를 볼 수 있다.
 
원본 다운로드:안 드 로 이 드 모방 매일 듣 기 좋 은 노래 자동 스크롤
이상 은 본 고의 모든 내용 입 니 다.여러분 이 안 드 로 이 드 소프트웨어 프로 그래 밍 을 배 우 는 데 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기