Android实现3D云标签效果

作者:程序猿L 时间:2022-06-05 10:33:50 

本文实例为大家分享了Android实现3D云标签效果的具体代码,供大家参考,具体内容如下

Android实现3D云标签效果

一、自定义View


public class TagCloudView extends RelativeLayout {
RelativeLayout navigation_bar;
TextView mTextView1;
private final float TOUCH_SCALE_FACTOR = .8f;
private float tspeed;
private TagCloud mTagCloud;
private float mAngleX =0;
private float mAngleY =0;
private float centerX, centerY;
private float radius;
private Context mContext;
private List<TextView> mTextView;
private List<RelativeLayout.LayoutParams> mParams;
private int shiftLeft;
float dowx = 0;
float dowy = 0;
float cutx=100;
float cuty=100;
public TagCloudView(Context mContext, int width, int height, List<Tag> tagList) {
 this(mContext, width, height, tagList, 6 , 34, 1);
}
public TagCloudView(Context mContext, int width, int height, List<Tag> tagList,
   int textSizeMin, int textSizeMax, int scrollSpeed) {
 super(mContext);
 this.mContext= mContext;
 tspeed = scrollSpeed;
 centerX = width / 2;
 centerY = height / 2;
 radius = Math.min(centerX * 0.95f , centerY * 0.95f );
 shiftLeft = (int)(Math.min(centerX * 0.15f , centerY * 0.15f ));
 mTagCloud = new TagCloud(tagList, (int) radius , textSizeMin, textSizeMax);
 float[] tempColor1 = {0.9412f,0.7686f,0.2f,1}; //rgb Alpha
         //{1f,0f,0f,1} red  {0.3882f,0.21568f,0.0f,1} orange
         //{0.9412f,0.7686f,0.2f,1} light orange
 float[] tempColor2 = {1f,0f,0f,1}; //rgb Alpha
         //{0f,0f,1f,1} blue  {0.1294f,0.1294f,0.1294f,1} grey
         //{0.9412f,0.7686f,0.2f,1} light orange
 mTagCloud.setTagColor1(tempColor1);//higher color
 mTagCloud.setTagColor2(tempColor2);//lower color
 mTagCloud.setRadius((int) radius);
 mTagCloud.create(true);
 mTagCloud.setAngleX(mAngleX);
 mTagCloud.setAngleY(mAngleY);
 mTagCloud.update();
 mTextView = new ArrayList<TextView>();
 mParams = new ArrayList<RelativeLayout.LayoutParams>();
 Iterator<?> it=mTagCloud.iterator();
 Tag tempTag;
 int i=0;
 //取出每个数据放到TexView里
 while (it.hasNext()){
  tempTag= (Tag) it.next();    
  tempTag.setParamNo(i);
  mTextView.add(new TextView(this.mContext));
  mTextView.get(i).setText(tempTag.getText());
  mParams.add(new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
  mParams.get(i).addRule(RelativeLayout.ALIGN_PARENT_LEFT);
  mParams.get(i).addRule(RelativeLayout.ALIGN_PARENT_TOP);
  mParams.get(i).setMargins((int) (centerX -shiftLeft + tempTag.getLoc2DX()),(int) (centerY + tempTag.getLoc2DY()),0,0);
  mTextView.get(i).setLayoutParams(mParams.get(i));
  mTextView.get(i).setSingleLine(true);
  int mergedColor = Color.argb((int)(tempTag.getAlpha() * 255), (int) (tempTag.getColorR() * 255), (int) (tempTag.getColorG() * 255),(int) (tempTag.getColorB() * 255));
  mTextView.get(i).setTextColor(mergedColor);
  mTextView.get(i).setTextSize((int)(tempTag.getTextSize() * tempTag.getScale()));
  addView(mTextView.get(i));
  mTextView.get(i).setOnClickListener(OnTagClickListener(tempTag.getUrl()));
  //设置每个TexView有自己指定的标签为自己的位置,以便后期操作
  mTextView.get(i).setTag(i);
  i++;
 }
 /** 用来自动播放的*/
 new Timer().schedule(new TimerTask() {

@Override
  public void run() {
   handler.sendEmptyMessage(1);
  }
 }, 0,200);
}
@SuppressLint("HandlerLeak")
Handler handler=new Handler(){
 @Override
 public void handleMessage(Message msg) {
  super.handleMessage(msg);
  mAngleX = (cuty/radius) *tspeed * TOUCH_SCALE_FACTOR;
  mAngleY = (-cutx/radius) *tspeed * TOUCH_SCALE_FACTOR;
  changPosition();
 }
};
@Override
protected void onDraw(Canvas canvas){
 super.onDraw(canvas);
}

/**
 * 触发事件
 */
@Override
public boolean onTouchEvent(MotionEvent e) {
 switch (e.getAction()) {
 case MotionEvent.ACTION_DOWN:
  dowx=e.getX();
  dowy=e.getY();
  break;
 case MotionEvent.ACTION_UP:
  float upx=e.getX();
  float upy=e.getY();
  cutx=upx-dowx;
  cuty=upy-dowy;
  break;
 case MotionEvent.ACTION_MOVE:  
  mAngleX = (cuty/radius) *tspeed * TOUCH_SCALE_FACTOR;
  mAngleY = (-cutx/radius) *tspeed * TOUCH_SCALE_FACTOR;
  changPosition();
  break;
 }

return true;
}
/**
 * 改变位置
 */
private void changPosition(){
 mTagCloud.setAngleX(mAngleX);
 mTagCloud.setAngleY(mAngleY);
 mTagCloud.update();
 Iterator<?> it=mTagCloud.iterator();
 Tag tempTag;
 while (it.hasNext()){
  tempTag= (Tag) it.next();    
  mParams.get(tempTag.getParamNo()).setMargins(  
    (int) (centerX -shiftLeft + tempTag.getLoc2DX()),
    (int) (centerY + tempTag.getLoc2DY()),
    0,
    0);
  mTextView.get(tempTag.getParamNo()).setTextSize((int)(tempTag.getTextSize() * tempTag.getScale()));
  int mergedColor = Color.argb( (int) (tempTag.getAlpha() * 255),
     (int) (tempTag.getColorR() * 255),
     (int) (tempTag.getColorG() * 255),
     (int) (tempTag.getColorB() * 255));
  mTextView.get(tempTag.getParamNo()).setTextColor(mergedColor);
  mTextView.get(tempTag.getParamNo()).bringToFront();
 }

}
/**
 * 点击事件
 * @param url
 * @return
 */
View.OnClickListener OnTagClickListener(final String url){
 return new View.OnClickListener(){
  @Override
  public void onClick(View v) {

}
 };
}
}

二、自定义迭代器


/**
* 自定义的迭代器
* @author Administrator
*
*/
public class TagCloud implements Iterable<Object>{
private List<Tag> tagCloud;
private int radius;
private static final int DEFAULT_RADIUS = 3;
private static final int TEXT_SIZE_MAX = 30 , TEXT_SIZE_MIN= 4;
private static final float[] DEFAULT_COLOR1= { 0.886f, 0.725f, 0.188f, 1f};
private static final float[] DEFAULT_COLOR2= { 0.3f, 0.3f, 0.3f, 1f};
private float[] tagColor1;
private float[] tagColor2;
private int textSizeMax, textSizeMin;
private float sin_mAngleX,cos_mAngleX,sin_mAngleY,cos_mAngleY,sin_mAngleZ,cos_mAngleZ;
private float mAngleZ=0;
private float mAngleX =0;
private float mAngleY =0;
private int size=0;
private int smallest,largest;
private boolean distrEven = true;

public TagCloud(){
 this(new ArrayList<Tag>());
}
public TagCloud(List<Tag> tags){
 this(tags,DEFAULT_RADIUS);
}
public TagCloud(List<Tag> tags, int radius){
 this( tags, radius, DEFAULT_COLOR1, DEFAULT_COLOR2, TEXT_SIZE_MIN, TEXT_SIZE_MAX);
}
public TagCloud(List<Tag> tags, int radius,int textSizeMin, int textSizeMax){
 this( tags, radius, DEFAULT_COLOR1, DEFAULT_COLOR2, textSizeMin, textSizeMax);
}
public TagCloud(List<Tag> tags, int radius,float[] tagColor1, float[] tagColor2){
 this( tags, radius, tagColor1, tagColor2, TEXT_SIZE_MIN, TEXT_SIZE_MAX);
}  

public TagCloud(List<Tag> tags, int radius, float[] tagColor1, float[] tagColor2,
     int textSizeMin, int textSizeMax){
 this.tagCloud=tags;  
 this.radius = radius;
 this.tagColor1 = tagColor1;
 this.tagColor2 = tagColor2;
 this.textSizeMax = textSizeMax;
 this.textSizeMin = textSizeMin;
}
/**
 * 重写的方法
 */
@Override
public Iterator iterator() {
 return tagCloud.iterator();
}
/**
 * 创建
 * @param distrEven
 */
public void create(boolean distrEven){
 this.distrEven =distrEven;
 positionAll(distrEven);
 sineCosine( mAngleX, mAngleY, mAngleZ);
 updateAll();
 smallest = 9999;
 largest = 0;
 for (int i=0; i< tagCloud.size(); i++){
  int j = tagCloud.get(i).getPopularity();
  largest = Math.max(largest, j);
  smallest = Math.min(smallest, j);
 }
 Tag tempTag;
 for (int i=0; i< tagCloud.size(); i++){
  tempTag = tagCloud.get(i);
  int j = tempTag.getPopularity();
  float percentage = ( smallest == largest ) ? 1.0f : ((float)j-smallest) / ((float)largest-smallest);
  float[] tempColor = getColorFromGradient( percentage ); //(rgb Alpha)
  int tempTextSize = getTextSizeGradient( percentage );
  tempTag.setColorR(tempColor[0]);
  tempTag.setColorG(tempColor[1]);
  tempTag.setColorB(tempColor[2]);
  tempTag.setTextSize(tempTextSize);
 }  

this.size= tagCloud.size();
}
/**
 * create创建完,就需要update
 */
public void update(){
 if( Math.abs(mAngleX) > .1 || Math.abs(mAngleY) > .1 ){
  sineCosine( mAngleX, mAngleY, mAngleZ);
  updateAll();
 }
}
/**
 * 计算每个Tag的
 * @param distrEven 是否根据字计算位置 true为是,否则字有覆盖的
 */
private void positionAll(boolean distrEven){
 double phi = 0;
 double theta = 0;
 int max = tagCloud.size();
 for (int i=1; i<max+1; i++){
  if (distrEven){
   phi = Math.acos(-1.0 + (2.0*i -1.0)/max);
   theta = Math.sqrt(max*Math.PI) * phi;
  } else{
   phi = Math.random()*(Math.PI);
   theta = Math.random()*(2 * Math.PI);
  }

tagCloud.get(i-1).setLocX((int)( (radius * Math.cos(theta) * Math.sin(phi))));
  tagCloud.get(i-1).setLocY((int)(radius * Math.sin(theta) * Math.sin(phi)));
  tagCloud.get(i-1).setLocZ((int)(radius * Math.cos(phi)));
 }  
}  
/**
 * 更新所有的Tag位置
 */
private void updateAll(){
 int max = tagCloud.size();
 for (int j=0; j<max; j++){
  float rx1 = (tagCloud.get(j).getLocX());
  float ry1 = (tagCloud.get(j).getLocY()) * cos_mAngleX +
     tagCloud.get(j).getLocZ() * -sin_mAngleX;
  float rz1 = (tagCloud.get(j).getLocY()) * sin_mAngleX +
     tagCloud.get(j).getLocZ() * cos_mAngleX;      
  float rx2 = rx1 * cos_mAngleY + rz1 * sin_mAngleY;
  float ry2 = ry1;
  float rz2 = rx1 * -sin_mAngleY + rz1 * cos_mAngleY;
  float rx3 = rx2 * cos_mAngleZ + ry2 * -sin_mAngleZ;
  float ry3 = rx2 * sin_mAngleZ + ry2 * cos_mAngleZ;
  float rz3 = rz2;
  tagCloud.get(j).setLocX(rx3);
  tagCloud.get(j).setLocY(ry3);
  tagCloud.get(j).setLocZ(rz3);
  int diameter = 2 * radius;
  float per = diameter / (diameter+rz3);
  tagCloud.get(j).setLoc2DX((int)(rx3 * per));
  tagCloud.get(j).setLoc2DY((int)(ry3 * per));
  tagCloud.get(j).setScale(per);
  tagCloud.get(j).setAlpha(per / 2);
 }  
 //给Tag排序
 Collections.sort(tagCloud);  
}  
/**
 * 计算字体颜色
 * @param perc
 * @return
 */
private float[] getColorFromGradient(float perc){
 float[] tempRGB = new float[4];
 tempRGB[0] = ( perc * ( tagColor1[0] ) ) + ( (1-perc) * ( tagColor2[0] ) );
 tempRGB[1] = ( perc * ( tagColor1[1] ) ) + ( (1-perc) * ( tagColor2[1] ) );
 tempRGB[2] = ( perc * ( tagColor1[2] ) ) + ( (1-perc) * ( tagColor2[2] ) );
 tempRGB[3] = 1;
 return tempRGB;
}
/**
 * 计算字体的大小
 * @param perc
 * @return
 */
private int getTextSizeGradient(float perc){
 int size;
 size = (int)( perc*textSizeMax + (1-perc)*textSizeMin );
 return size;
}
/**
 * 计算圆形的x y z坐标
 * @param mAngleX
 * @param mAngleY
 * @param mAngleZ
 */
private void sineCosine(float mAngleX,float mAngleY,float mAngleZ) {
 double degToRad = (Math.PI / 180);
 sin_mAngleX= (float) Math.sin( mAngleX * degToRad);
 cos_mAngleX= (float) Math.cos( mAngleX * degToRad);
 sin_mAngleY= (float) Math.sin( mAngleY * degToRad);
 cos_mAngleY= (float) Math.cos( mAngleY * degToRad);
 sin_mAngleZ= (float) Math.sin( mAngleZ * degToRad);
 cos_mAngleZ= (float) Math.cos( mAngleZ * degToRad);
}
/**
 * 以下是get set方法
 * @return
 */
public int getRadius() {
 return radius;
}
public void setRadius(int radius) {
 this.radius = radius;
}
public float[] getTagColor1() {
 return tagColor1;
}
public void setTagColor1(float[] tagColor) {
 this.tagColor1 = tagColor;
}
public float[] getTagColor2() {
 return tagColor2;
}
public void setTagColor2(float[] tagColor2) {
 this.tagColor2 = tagColor2;
}

public float getRvalue(float[] color) {
 if (color.length>0)
  return color[0];
 else
  return 0;
}
public float getGvalue(float[] color) {
 if (color.length>0)
  return color[1];
 else
  return 0; }
public float getBvalue(float[] color) {
 if (color.length>0)
  return color[2];
 else
  return 0; }
public float getAlphaValue(float[] color) {
 if (color.length >= 4)
  return color[3];
 else
  return 0;  
}  
public float getAngleX() {
 return mAngleX;
}
public void setAngleX(float mAngleX) {
 this.mAngleX = mAngleX;
}
public float getAngleY() {
 return mAngleY;
}
public void setAngleY(float mAngleY) {
 this.mAngleY = mAngleY;
}
public int getSize() {
 return size;
}  

}

三、自定义数据


/**
* Comparable接口 可以自定义排序方式
* @author Administrator
*
*/
public class Tag implements Comparable<Tag>{

private String text, url;
private int popularity;
private int textSize;
private float locX, locY, locZ;
private float loc2DX, loc2DY;
private float scale;
private float colorR, colorG, colorB, alpha;
private static final int DEFAULT_POPULARITY = 1;
private int paramNo;

public Tag(String text, int popularity) {
 this(text, 0f, 0f, 0f, 1.0f, popularity, "");
}  
public Tag(String text, int popularity, String url) {
 this(text, 0f, 0f, 0f, 1.0f, popularity, url);
}  
public Tag(String text,float locX, float locY, float locZ) {
 this(text, locX, locY, locZ, 1.0f, DEFAULT_POPULARITY, "");
}
public Tag(String text,float locX, float locY, float locZ, float scale) {
 this(text, locX, locY, locZ, scale, DEFAULT_POPULARITY, "");
}
public Tag(String text,float locX, float locY, float locZ, float scale, int popularity,
   String url) {
 this.text = text;
 this.locX = locX;
 this.locY = locY;
 this.locZ = locZ;
 this.loc2DX = 0;
 this.loc2DY=0;
 this.colorR= 0.5f;
 this.colorG= 0.5f;
 this.colorB= 0.5f;
 this.alpha = 1.0f;
 this.scale = scale;
 this.popularity= popularity;
 this.url = url;
}  

@Override
public int compareTo(Tag another) {
 //排序方式
 return (int)(another.locZ - locZ);
}

public float getLocX() {
 return locX;
}
public void setLocX(float locX) {
 this.locX = locX;
}
public float getLocY() {
 return locY;
}
public void setLocY(float locY) {
 this.locY = locY;
}
public float getLocZ() {
 return locZ;
}
public void setLocZ(float locZ) {
 this.locZ = locZ;
}
public float getScale() {
 return scale;
}
public void setScale(float scale) {
 this.scale = scale;
}
public String getText() {
 return text;
}
public void setText(String text) {
 this.text = text;
}
public float getColorR() {
 return colorR;
}
public void setColorR(float colorR) {
 this.colorR = colorR;
}
public float getColorG() {
 return colorG;
}
public void setColorG(float colorG) {
 this.colorG = colorG;
}
public float getColorB() {
 return colorB;
}
public void setColorB(float colorB) {
 this.colorB = colorB;
}
public float getAlpha() {
 return alpha;
}
public void setAlpha(float alpha) {
 this.alpha = alpha;
}
public int getPopularity() {
 return popularity;
}
public void setPopularity(int popularity) {
 this.popularity = popularity;
}

public int getTextSize() {
 return textSize;
}
public void setTextSize(int textSize) {
 this.textSize = textSize;
}
public float getLoc2DX() {
 return loc2DX;
}
public void setLoc2DX(float loc2dx) {
 loc2DX = loc2dx;
}
public float getLoc2DY() {
 return loc2DY;
}
public void setLoc2DY(float loc2dy) {
 loc2DY = loc2dy;
}
public int getParamNo() {
 return paramNo;
}
public void setParamNo(int paramNo) {
 this.paramNo = paramNo;
}
public String getUrl() {
 return url;
}
public void setUrl(String url) {
 this.url = url;
}

}

四、调用


private TagCloudView mTagCloudView;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

this.requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
  WindowManager.LayoutParams.FLAG_FULLSCREEN);

Display display = getWindowManager().getDefaultDisplay();
@SuppressWarnings("deprecation")
int width = display.getWidth();
@SuppressWarnings("deprecation")
int height = display.getHeight();
List<Tag> myTagList= createTags();
mTagCloudView = new TagCloudView(this, width, height, myTagList );
setContentView(mTagCloudView);
mTagCloudView.requestFocus();
mTagCloudView.setFocusableInTouchMode(true);

}
private List<Tag> createTags(){
List<Tag> tempList = new ArrayList<Tag>();
tempList.add(new Tag("Google", 7, "http://www.google.com"));
tempList.add(new Tag("Yahoo", 3, "www.yahoo.com"));
tempList.add(new Tag("CNN", 4, "www.cnn.com"));
tempList.add(new Tag("MSNBC", 5, "www.msnbc.com"));
tempList.add(new Tag("CNBC", 5, "www.CNBC.com"));
tempList.add(new Tag("Facebook", 7, "www.facebook.com"));
tempList.add(new Tag("Youtube", 3, "www.youtube.com"));
tempList.add(new Tag("BlogSpot", 5, "www.blogspot.com"));
tempList.add(new Tag("Bing", 3, "www.bing.com"));
tempList.add(new Tag("Wikipedia", 8, "www.wikipedia.com"));
tempList.add(new Tag("Twitter", 5, "www.twitter.com"));
tempList.add(new Tag("Msn", 1, "www.msn.com"));
tempList.add(new Tag("Amazon", 3, "www.amazon.com"));
tempList.add(new Tag("Ebay", 7, "www.ebay.com"));
tempList.add(new Tag("LinkedIn", 5, "www.linkedin.com"));
tempList.add(new Tag("Live", 7, "www.live.com"));
tempList.add(new Tag("Microsoft", 3, "www.microsoft.com"));
tempList.add(new Tag("Flicker", 1, "www.flicker.com"));
tempList.add(new Tag("Apple", 5, "www.apple.com"));
tempList.add(new Tag("Paypal", 5, "www.paypal.com"));
tempList.add(new Tag("Craigslist", 7, "www.craigslist.com"));
tempList.add(new Tag("Imdb", 2, "www.imdb.com"));
tempList.add(new Tag("Ask", 4, "www.ask.com"));
tempList.add(new Tag("Weibo", 1, "www.weibo.com"));
tempList.add(new Tag("Tagin!", 8, "http://scyp.idrc.ocad.ca/projects/tagin"));
tempList.add(new Tag("Shiftehfar", 8, "www.shiftehfar.org"));
tempList.add(new Tag("Soso", 5, "www.google.com"));
tempList.add(new Tag("XVideos", 3, "www.xvideos.com"));
tempList.add(new Tag("BBC", 5, "www.bbc.co.uk"));
return tempList;
}

源码下载地址点击打开链接

来源:https://blog.csdn.net/mingyue_1128/article/details/38583009

标签:Android,云标签
0
投稿

猜你喜欢

  • C#中OpenCVSharp实现轮廓检测

    2022-04-03 17:38:11
  • java迷宫算法的理解(递归分割,递归回溯,深搜,广搜)

    2022-10-22 10:36:31
  • java 配置MyEclipse Maven环境具体实现步骤

    2021-07-31 04:12:23
  • Spring bean为什么需要依赖注入

    2022-01-24 11:07:21
  • SpringBoot如何整合redis实现过期key监听事件

    2023-08-04 18:51:19
  • Java实现级联下拉结构的示例代码

    2023-11-03 18:22:06
  • 使用@pathvariable与@requestparam碰到的一些问题及解决

    2023-11-27 16:30:34
  • 浅谈java实现背包算法(0-1背包问题)

    2022-04-28 15:23:43
  • Java内存模型(JMM)及happens-before原理

    2023-11-25 00:41:05
  • 简单实现Android弹出菜单效果

    2023-01-11 18:58:46
  • Java爬虫范例之使用Htmlunit爬取学校教务网课程表信息

    2021-07-17 00:52:51
  • Spring Boot与Kotlin 整合全文搜索引擎Elasticsearch的示例代码

    2023-03-18 11:57:58
  • java中SynchronizedList和Vector的区别详解

    2023-08-23 10:13:12
  • Java多线程实现Runnable方式

    2022-06-29 17:09:46
  • Java中如何避免sql注入实例详解

    2022-08-24 14:42:06
  • Java超详细讲解类变量和类方法

    2023-04-24 14:45:43
  • 详解Java枚举为什么是单例模式的最佳选择

    2022-07-16 20:42:47
  • ViewDragHelper实现QQ侧滑效果

    2022-12-25 23:26:54
  • 详解在Spring中如何使用AspectJ来实现AOP

    2021-10-23 02:06:06
  • response文件流输出文件名中文不显示的解决

    2023-02-06 19:41:02
  • asp之家 软件编程 m.aspxhome.com