2013-11-25 11 views
9

Bir çeşit "kanvas" uygulamak istiyorum. Burada, "rastgele konumlarda" X numaralı TextViews/Links'i yerleştirebilirsiniz (aşağıdaki resimde görüldüğü gibi). Ardından bu "kanvas" görünümünü sürekli olarak sola veya sağa kaydırırsınız ve görünüm dairesel olarak tekrarlanır/döner (kaydırma işlemini elle yaptığınız dışında bir HTML seçim çerçevesi gibi). En basit durumlarda, sadece yatay kaydırmaya bakıyorum - ama daha "karmaşık bir durum" örneği "küre kaydırma" yapabileceğiniz yer - Appy Geek'in aşağıdaki örneğine bakın. Appy Geek danMetin için 3D dairesel kaydırma görünümünü nasıl oluşturabilirim? (Appy Geek'te görüldüğü gibi)

Örnek (Şimdilik ben yatay kaydırma sadece ilgileniyorum):

enter image description here

+0

Kullanım animasyon - Çocukların konumuna animasyon. –

cevap

6

Eh bu başlamanıza olacak, ben tarafından yani her iki yaklaşımı kullanarak basit bir etiket bulutu (uygulamıştır dönmeyi sürdüren View ve ViewGroup genişletme). Bu mantığı, Görünümünü buna göre konumlandıran özel ViewGroup'da kullanabilirsiniz. Bundan sonra bu yerleşimin içine tıklanabilir TextView s ekleyin ve dokunma olaylarını ele alın.

Nihai sonuç (kendi döndürme tabii, yakından bak): şeylerden

enter image description here

Lot aşağıdaki kodda geliştirilebilir. ViewGroup uzatarak

:

xml düzeni koy:

<com.vj.tagcloud.TagCloudLayout 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" > 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 

    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="TextView" /> 
</com.vj.tagcloud.TagCloudLayout> 

TagCloudLayout sınıfı:

import java.util.Random; 

import android.content.Context; 
import android.os.Handler; 
import android.util.AttributeSet; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.TextView; 

public class TagCloudLayout extends ViewGroup { 
final Random mRandom = new Random(); 
private float mRotateAngle; 

private Handler mHandler = new Handler(); 
private float rotateAngleDegree; 

public TagCloudLayout(Context context) { 
    super(context); 
} 

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

public TagCloudLayout(Context context, AttributeSet attrs, int defStyle) { 
    super(context, attrs, defStyle); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    final float radius = Math.min(getMeasuredWidth(), getMeasuredHeight())/2F; 
    float halfWidth = getMeasuredWidth()/2F; 
    float halfHeight = getMeasuredHeight()/2F; 
    final int count = getChildCount(); 
    for (int i = 0; i < count; i++) { 
     View child = getChildAt(i); 
     LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
     float sinTheta = (float) Math.sin(lp.theta); 
     float x = (int) (radius * Math.cos(lp.fi + mRotateAngle) 
       * sinTheta); 

     if (child instanceof TextView) { 
      ((TextView) child) 
        .setTextSize(15 * ((radius - x)/radius) + 10); 
     } 
     measureChild(child, widthMeasureSpec, heightMeasureSpec); 
     // http://en.wikipedia.org/wiki/Spherical_coordinates 
     lp.x = (int) ((halfWidth + radius * Math.sin(lp.fi + mRotateAngle) 
       * sinTheta) - /* for balancing on x-axis */(child 
       .getMeasuredWidth()/2F)); 
     lp.y = (int) (halfHeight + radius * Math.cos(lp.theta)-/* for balancing on y-axis */(child 
       .getMeasuredHeight()/2F)); 
    } 
} 

@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 
    mHandler.postDelayed(new Runnable() { 

     @Override 
     public void run() { 
      rotateAngleDegree += 5; 
      mRotateAngle = (float) Math.toRadians(rotateAngleDegree); 
      requestLayout(); 
      mHandler.postDelayed(this, 40); 
     } 
    }, 40); 
} 

@Override 
protected void onDetachedFromWindow() { 
    super.onDetachedFromWindow(); 
    mHandler.removeCallbacksAndMessages(null); 
} 

@Override 
public void addView(View child, int index, 
     android.view.ViewGroup.LayoutParams params) { 
    super.addView(child, index, params); 

    LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
    lp.fi = (float) Math.toRadians(mRandom.nextInt(360)); 
    lp.theta = (float) Math.toRadians(mRandom.nextInt(360)); 
} 

@Override 
protected void onLayout(boolean changed, int l, int t, int r, int b) { 
    final int count = getChildCount(); 
    for (int i = 0; i < count; i++) { 
     View child = getChildAt(i); 
     LayoutParams lp = (LayoutParams) child.getLayoutParams(); 
     child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y 
       + child.getMeasuredHeight()); 
    } 
} 

@Override 
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { 
    return p instanceof LayoutParams; 
} 

@Override 
protected LayoutParams generateDefaultLayoutParams() { 
    return new LayoutParams(LayoutParams.WRAP_CONTENT, 
      LayoutParams.WRAP_CONTENT); 
} 

@Override 
public LayoutParams generateLayoutParams(AttributeSet attrs) { 
    return new LayoutParams(getContext(), attrs); 
} 

@Override 
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) { 
    return new LayoutParams(p.width, p.height); 
} 

public static class LayoutParams extends ViewGroup.LayoutParams { 
    int x; 
    int y; 
    float fi, theta; 

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

    public LayoutParams(int w, int h) { 
     super(w, h); 
    } 
} 
} 

uzatarak:

<com.vj.wordtap.TagCloud 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" /> 

ve bu java kodunda:

xml düzeni koy Düzeninize

import java.util.ArrayList; 
import java.util.List; 
import java.util.Random; 

import android.content.Context; 
import android.graphics.Camera; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.os.Handler; 
import android.text.TextPaint; 
import android.util.AttributeSet; 
import android.view.View; 

public class TagCloud extends View { 

private List<String> mItems = new ArrayList<String>(); 
private List<Angles> mAngles = new ArrayList<Angles>(); 
private Camera mCamera = new Camera(); 
private TextPaint mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG); 
private Handler mHandler = new Handler(); 
private float mRotateAngle; 
private float rotateAngleDegree; 

public static class Angles { 
    float fi, theta; 
} 

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

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

public TagCloud(Context context, AttributeSet attrs, int defStyleAttr) { 
    super(context, attrs, defStyleAttr); 
    init(); 
} 

private void init() { 
    List<String> items = new ArrayList<String>(); 
    for (int i = 0; i < 10; i++) { 
     items.add("item:" + i); 
    } 
    setItems(items); 
} 

@Override 
protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    canvas.translate(canvas.getWidth()/2F, canvas.getHeight()/2F); 
    mTextPaint.setColor(Color.BLACK); 
    final float radius = 100; 
    mCamera.setLocation(0, 0, -100); 
    for (int i = 0; i < mItems.size(); i++) { 
     String item = mItems.get(i); 
     Angles xyz = mAngles.get(i); 
     mCamera.save(); 
     canvas.save(); 
     float sinTheta = (float) Math.sin(xyz.theta); 
     float x = (float) (radius * Math.cos(xyz.fi + mRotateAngle) * sinTheta); 
     float y = (float) (radius * Math.sin(xyz.fi + mRotateAngle) * sinTheta); 
     float z = (float) (radius * Math.cos(xyz.theta)); 
     // mapping coordinates with Android's coordinates 
     // http://en.wikipedia.org/wiki/Spherical_coordinates 
     mCamera.translate(y, z, x); 
     mCamera.applyToCanvas(canvas); 

     // http://en.wikipedia.org/wiki/Spherical_coordinates 
     // set size based on x-Axis that is coming towards us 
     mTextPaint.setTextSize(20 * ((100 - x)/100) + 10); 
     canvas.drawText(item, 0, 0, mTextPaint); 
     mCamera.restore(); 
     canvas.restore(); 
    } 
} 

@Override 
protected void onAttachedToWindow() { 
    super.onAttachedToWindow(); 
    mHandler.postDelayed(new Runnable() { 

     @Override 
     public void run() { 
      rotateAngleDegree += 5; 
      mRotateAngle = (float) Math.toRadians(rotateAngleDegree); 
      invalidate(); 
      mHandler.postDelayed(this, 40); 
     } 
    }, 40); 
} 

@Override 
protected void onDetachedFromWindow() { 
    super.onDetachedFromWindow(); 
    mHandler.removeCallbacksAndMessages(null); 
} 

@Override 
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
} 

public void setItems(List<String> items) { 
    mItems = items; 
    final Random ran = new Random(); 
    final List<Angles> xyzList = mAngles; 
    xyzList.clear(); 

    for (int i = 0; i < items.size(); i++) { 
     Angles xyz = new Angles(); 
     float fi = (float) Math.toRadians(ran.nextInt(360)); 
     xyz.fi = fi; 
     float theta = (float) Math.toRadians(ran.nextInt(360)); 
     xyz.theta = theta; 
     xyzList.add(xyz); 
    } 
} 
} 
+1

Bu, kodun sadece 1 düzen dosyasıyla kopyalanmasıyla ve daha sonra düzeni bir etkinlikten çağırmakla (başka hiçbir şeye gerek duyulmadı!) Çalıştı. Çok güzel bir çözüm - paylaştığınız için teşekkürler – gnB

İlgili konular