gpt4 book ai didi

android - 如何为文本创建 3D 圆形 ScrollView ? (如 Appy Geek 中所见)

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:37:19 24 4
gpt4 key购买 nike

我希望实现某种“ Canvas ”,您可以在其中将 X 数量的 TextViews/Links 放置在“随机位置”(如下图所示)。然后,您将能够连续向左或向右滚动此“ Canvas ” View ,并且该 View 将重复/呈圆形(有点像 HTML 选取框,只是您正在手动滚动)。在最简单的情况下,我只是希望进行水平滚动——但是一个更“复杂的情况”的例子是你可以做“球体滚动”的地方——参见下面来自 Appy Geek 的例子。 (现在我只对水平滚动感兴趣)

来自 Appy Geek 的示例:

enter image description here

最佳答案

好吧,这会让你开始,我已经使用两种方法(即通过扩展 ViewViewGroup)实现了一个简单的标签云,它一直在旋转。您可以在自定义 ViewGroup 中使用此逻辑,从而相应地定位其 View 。之后在该布局中添加可点击的 TextView 并处理触摸事件。

最终结果(当然是旋转的,仔细看):

enter image description here

下面的代码可以改进很多东西。

通过扩展 ViewGroup:

将其放入 xml 布局中:

 <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 类:

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);
}
}
}

通过扩展 View :

将其放入 xml 布局中:

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

这是在 java 代码中:

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);
}
}
}

关于android - 如何为文本创建 3D 圆形 ScrollView ? (如 Appy Geek 中所见),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20193168/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com