Android Open Source - Circular-Layout Circular Layout






From Project

Back to project page Circular-Layout.

License

The source code is released under:

MIT License

If you think the Android project Circular-Layout listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

package crocodile8000.circularlayout.lib;
/*from ww w. ja v a2s . c  om*/
import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.RelativeLayout;


/**
 * Layout ??? ??????????? ???????? ????????? View (???? ?????? ????????+1 ?????? ?????? CircularLayout)
 */
public class CircularLayout extends RelativeLayout {
  
  public static boolean needLog;
  public static String logTag = "CircularLayout";
  
  private List<ViewGroup> itemList = new ArrayList<ViewGroup>();
  
  private int w, h;
  private int itemW, itemH;
  private int mPadding = 5 ;
  private int lastXtouch, currXonStartTouch , startTouchX;
  private boolean needCircular, canScroll;
  
  /** ??????????? ?????? ?????? ????? (ViewGroup) ? ??? ?????? */
  public float ItemWRatio = 1.25f;
  
  // ??????????? ????????? ????????? ???????? ???????
  private int stepSaveSpeedCnt = 5;
  private int[] lastStepsSpeed = new int[stepSaveSpeedCnt];
  
  /** ????? ?? ??????????? ???????? ????? ?????????? */
  public boolean needSpeed = true;
  
  private long lastUpdTime;
  
  private boolean isTouching;
  
  private int currItem;
  private Paint paint, paintShadow;
  
  
  
  public CircularLayout(Context context) {
    super(context);
  }

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

  public CircularLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
  }
  
  
  @Override
  protected void onLayout(boolean changed, int l, int t, int r, int b) {
    super.onLayout( changed,  l,  t,  r,  b);
    init();
  }

  
  
  /**
   * ????????????? ?????????? ? ?????????? ??????? ??????
   */
  private void init(){
    lastUpdTime = System.currentTimeMillis();

    if (Build.VERSION.SDK_INT >=14) requestDisallowInterceptTouchEvent(true);
    
    initPaint();
    
    removeAllViews();
    w = getWidth();
    h = getHeight();
    itemH = h/10*9;
    itemW = (int) (itemH*ItemWRatio);
    
    int totalViewsLen = (itemW+mPadding)*itemList.size();
    if (totalViewsLen < w) canScroll = false;
    else canScroll = true;
    if (totalViewsLen-(itemW+mPadding)>w) needCircular = true;
    else needCircular = false;
    int mostLeftX = w;
    
    for (int i=0; i<itemList.size(); i++){
      this.addView(itemList.get(i));

      int left = currXonStartTouch+i*itemW+ i*mPadding + mPadding;
      
      if (needCircular){
        
        if (left+itemW+mPadding < 0) 
          while(left+itemW+mPadding<0) 
            left += totalViewsLen;
        
        if (left-mPadding>w) 
          while(left-mPadding > w) 
            left -= totalViewsLen;
        
        // ??????? ????? ???????? ????? ??? ????? ??????? ? ?????? ???? ? ????????? ??????????
        if (Math.abs(left-itemW/4)<mostLeftX){
          mostLeftX = Math.abs(left-itemW/4);
          currItem = i;
        }
        
      }else if(canScroll){
        if (currXonStartTouch > 0) currXonStartTouch=0;
        else if (currXonStartTouch < w -totalViewsLen -mPadding) currXonStartTouch= w -totalViewsLen -mPadding;
        left = currXonStartTouch+i*itemW+ i*mPadding + mPadding;
      }
      
      itemList.get(i).layout(left, mPadding, left+itemW, itemH);
    }
    if (needLog) Log.i(logTag, "currItem: "+currItem+ "   mostLeftX: "+mostLeftX);
  }
  
  
  
  
  
  private void initPaint(){
    if (paint==null){
      paint = new Paint();
      paint.setColor(Color.BLUE);
      paint.setAntiAlias(true);
    }
    if (paintShadow==null){
      paintShadow = new Paint();
      paintShadow.setColor(Color.argb(50, 0, 0, 0));
      paintShadow.setAntiAlias(true);
    }
  }
  
  
  
  
  public void onDraw(Canvas canv){
    super.onDraw(canv);

    // ???????? ?? ??????? ????? ?????????? (???? ?????)
    if (needSpeed){
      final int speedMult = 10;
      int slideSpeed = getSlideSpeed()*speedMult;
      if (slideSpeed != 0 && !isTouching){
        
        final int maxSpeed = 250;
        if (slideSpeed> maxSpeed) slideSpeed = maxSpeed;
        if (slideSpeed< -maxSpeed) slideSpeed = -maxSpeed;
        
        if (slideSpeed>0){
          slideSpeed--;
        }
        else{
          slideSpeed++;
        }
        updLastStepsSpeed(slideSpeed/speedMult);
        currXonStartTouch+=slideSpeed/speedMult;
        init();
      }
    }
    drawBottomCircles(canv);
  }
  
  
  
  
  /**
   * ?????????? ????? ????? ? ?????????? ???????? ?????
   */
  private void drawBottomCircles(Canvas canv){
    if (!needCircular) return;
    int pad = w / 25;
    int startX = w/2 - pad*itemList.size()/2;
    int y = h - (h/10) + (h/10)/2;
    int radius = h/50;
    for (int i=0; i<itemList.size(); i++){
      canv.drawCircle(startX+ pad*i, y, currItem==i? radius*2 : radius , paint);
    }
  }
  
  
  
  /**
   * ?????????? ?????? ????? ?? layout
   */
  public void addItem(Context context, ViewGroup view){
    view.setTag(itemList.size());
    itemList.add(view);
    init();
  }
  
  

  
  
  
  @Override
  public boolean onInterceptTouchEvent(MotionEvent event) {
    if (needLog) Log.d(logTag, "onInterceptTouchEvent");
    
    if ( canScroll && event.getAction() == MotionEvent.ACTION_DOWN) {
      startTouch(event);
      return false;
    }
    
    if ( canScroll && event.getAction() == MotionEvent.ACTION_MOVE) {
      // ??????????? ????????? ??????????????? ?????? ??? ?? ???????? ??????? ???????, 
      // ???? ????, ???????? ??? ????? ??????? ?? 1-2 ???????
      int pathX = Math.abs( (int)event.getX() - startTouchX ) ;
      if (pathX>h/10) return true;
    }
    
      return false;
  }
  

  
  private void startTouch(MotionEvent event){
    startTouchX = (int)event.getX();
    lastXtouch = startTouchX;
    isTouching = true;
    clearLastStepsSpeed();
  }
  
  
  
    @Override
    public boolean onTouchEvent(MotionEvent event) {
      
    if ( canScroll && event.getAction() == MotionEvent.ACTION_DOWN) {
      startTouch(event);
    }
      
    else if ( canScroll && event.getAction() == MotionEvent.ACTION_MOVE) {
      currXonStartTouch += ( event.getX() - lastXtouch );
      updLastStepsSpeed( (int) (event.getX() - lastXtouch));
      lastXtouch = (int)event.getX() ;
      //TODO ?????????? ?? ???????? ??? ?? ????????? ????????
      if (System.currentTimeMillis() - lastUpdTime >30) init();
    }
      
    else if ( canScroll && event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
      if (needLog) Log.i(logTag, "currXonStartTouch: " +currXonStartTouch+ "  speed: "+getSlideSpeed());
      init();
      isTouching = false;
    }
      
    return true;
    }
    
    
    
    
    /**
     * ???????? ?????? ????????? ????????? ????????
     */
    private void clearLastStepsSpeed(){
      for (int i =0; i< lastStepsSpeed.length; i++){
        lastStepsSpeed[i] = 0;
      }
    }
    
    
    /**
     * ???????? ?????? ????????? ????????? ????????
     */
    private void updLastStepsSpeed(int lastXSpeed){
      for (int i =0; i< lastStepsSpeed.length-1; i++){
        lastStepsSpeed[i] = lastStepsSpeed[i+1];
      }
      lastStepsSpeed[lastStepsSpeed.length-1] = lastXSpeed;
    }
    
    
    /**
     * ????? ??????? ???????? ????????? ????? ?????????
     */
    private int getSlideSpeed(){
      int speed = 0;
      for (int i =0; i< lastStepsSpeed.length; i++) speed+=lastStepsSpeed[i];
      speed = speed/lastStepsSpeed.length;
      return speed;
    }
  
  
    
    

}




Java Source Code List

crocodile8000.circularlayout.MainActivity.java
crocodile8000.circularlayout.lib.CircularLayout.java
crocodile8000.circularlayout.lib.CircularViewClickListener.java