dieses Gut werden Sie den Einstieg, ich implementiert eine einfache Tag-Wolke beiden Ansätze (zB durch Verlängerung View
und ViewGroup
), die weiterdreht. Sie können diese Logik in Ihrem benutzerdefinierten ViewGroup
verwenden, der seine Ansichten entsprechend positioniert. Danach fügen Sie anklickbare TextView
s in diesem Layout hinzu und behandeln Touch-Ereignisse.
Endgültiges Ergebnis (natürlich seine Dreh, näher betrachten):
Viele Dinge können in den folgenden Code verbessert werden.
VON ViewGroup
ERWEITERN:
Setzen Sie dieses in xml Layout:
<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
Klasse:
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);
}
}
}
VONERWEITERN:
dieses Layout in xml Put:
<com.vj.wordtap.TagCloud
android:layout_width="match_parent"
android:layout_height="match_parent" />
und dies in Java-Code:
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);
}
}
}
Verwenden Animation auf der Anlage - die Position der Kinder animieren. –