`

Android文字竖直排版TextViewVertical(可横向滚动)(转)

 
阅读更多

实现中国古文的那种行文格式排版,从上至下从右至左的顺序。
废话不多说,先看效果
<ignore_js_op style="word-wrap: break-word;"> 

 

 

 

(1)自定义竖排文字控件TextViewVertical.java:

package org.guyue;

/**************************
 * 作者:古月摇光
 * E-mail:45361251@qq.com
 * 更新日期:2012/02/28
 * 说明:本类实现了文字的竖直排版显示(中国古时的行文形式),
 * 		 虽然仍有许多特效及功能仍未实现,但基本的使用已经能满足。
 * 版权:尽管放心用吧,可以自行随意改进转载和使用,转载时请保留这段文字即可
 * 另特别感谢 老僧xp 提出的修改意见
 **************************/
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Paint.FontMetrics;
import android.graphics.drawable.BitmapDrawable;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * 自定义竖排文字控件
 */
public class TextViewVertical extends View {

	public static final int LAYOUT_CHANGED = 1;
    private Paint paint;
    private int mTextPosx = 0;// x坐标
    private int mTextPosy = 0;// y坐标
    private int mTextWidth = 0;// 绘制宽度
    private int mTextHeight = 0;// 绘制高度
    private int mFontHeight = 0;// 绘制字体高度
    private float mFontSize = 24;// 字体大小
    private int mRealLine = 0;// 字符串真实的行数
    private int mLineWidth = 0;//列宽度
    private int TextLength = 0 ;//字符串长度
    private int oldwidth = 0 ;//存储久的width
    private String text="";//待显示的文字
    private Handler mHandler=null;
    private Matrix matrix;
    BitmapDrawable drawable = (BitmapDrawable) getBackground();
    public TextViewVertical(Context context, AttributeSet attrs, int defStyle) {  
        super(context, attrs, defStyle);  
    }  
    public TextViewVertical(Context context,AttributeSet attrs) {
        super(context, attrs);
        matrix = new Matrix();
        paint = new Paint();//新建画笔
        paint.setTextAlign(Align.CENTER);//文字居中
        paint.setAntiAlias(true);//平滑处理
        paint.setColor(Color.BLACK);//默认文字颜色
        try{
        	mFontSize	= Float.parseFloat(attrs.getAttributeValue(null,"textSize"));//获取字体大小属性  	
        }catch(Exception e){}
    }
    /*
    //获取整数值
    private final int getAttributeIntValue(AttributeSet attrs,String field) {
    	int intVal = 0;
    	//TODO 
    	//应该可以直接用attrs.getAttributeIntValue()获取对应的数值的,
    	//但不知道为什么一直无法获得只好临时写个函数凑合着用,没有写完整,暂时只支持px作为单位,其它单位的转换有空再写
    	String tempText=attrs.getAttributeValue(androidns, field);
    	intVal = (int)Math.ceil(Float.parseFloat(tempText.replaceAll("px","")));
		return intVal;
    }*/
    //设置文字
    public final void setText(String text) {
    	this.text=text;
    	this.TextLength = text.length();
    	if(mTextHeight>0)GetTextInfo();
    }
    //设置字体大小
    public final void setTextSize(float size) {
        if (size != paint.getTextSize()) {
        	mFontSize = size;
        	if(mTextHeight>0)GetTextInfo();
        }
    }
    //设置字体颜色
    public final void setTextColor(int color) {
    	paint.setColor(color);
    }
    //设置字体颜色
    public final void setTextARGB(int a,int r,int g,int b) {
    	paint.setARGB(a, r, g, b);
    }
    //设置字体
    public void setTypeface(Typeface tf) {
        if (this.paint.getTypeface() != tf) {
        	this.paint.setTypeface(tf);
        }
    }
    //设置行宽
    public void setLineWidth(int LineWidth) {
    	mLineWidth = LineWidth;
    }
    //获取实际宽度
    public int getTextWidth() {
		return mTextWidth;
    }
    //设置Handler,用以发送事件
    public void setHandler(Handler handler) {
    	mHandler=handler;
    }
    @Override
    protected void onDraw(Canvas canvas) {
    	super.onDraw(canvas);
    	Log.v("TextViewVertical","onDraw");
    	if(drawable!=null){
    		//画背景
    		Bitmap b = Bitmap.createBitmap(drawable.getBitmap(),0,0,mTextWidth,mTextHeight);
    		canvas.drawBitmap(b, matrix, paint);
    	}
        //画字
        draw(canvas, this.text);
    }  
    private void draw(Canvas canvas, String thetext) {
    	char ch;
    	mTextPosy = 0;//初始化y坐标
    	mTextPosx = mTextWidth - mLineWidth;//初始化x坐标    	
        for (int i = 0; i < this.TextLength; i++) {
        	ch = thetext.charAt(i);
        	if (ch == '\n') {
        		mTextPosx -= mLineWidth;// 换列
    	    	mTextPosy = 0;
        	} else {
        		mTextPosy += mFontHeight;
        		if (mTextPosy > this.mTextHeight) {
        			mTextPosx -= mLineWidth;// 换列
        			i--;
        			mTextPosy = 0;
        		}else{
        			canvas.drawText(String.valueOf(ch), mTextPosx, mTextPosy, paint);
        		}
        	}	
        }
        
        //调用接口方法
        //activity.getHandler().sendEmptyMessage(TestFontActivity.UPDATE);
    }
    //计算文字行数和总宽
    private void GetTextInfo() {
    	Log.v("TextViewVertical","GetTextInfo");
    	char ch;
    	int h = 0;
    	paint.setTextSize(mFontSize);
    	//获得字宽
    	if(mLineWidth==0){
    		float[] widths = new float[1];
    		paint.getTextWidths("正", widths);//获取单个汉字的宽度
    		mLineWidth=(int) Math.ceil(widths[0] * 1.1 +2);
    	}
    	
    	FontMetrics fm = paint.getFontMetrics();  
      	mFontHeight = (int) (Math.ceil(fm.descent - fm.top) * 0.9);// 获得字体高度
      	
      	//计算文字行数
      	mRealLine=0;
    	for (int i = 0; i < this.TextLength; i++) {
    		ch = this.text.charAt(i);
    		if (ch == '\n') {
	    	    mRealLine++;// 真实的行数加一
	    	    h = 0;
    		} else {
    			h += mFontHeight;
    			if (h > this.mTextHeight) {
    				mRealLine++;// 真实的行数加一
    				i--;
    				h = 0;
    			} else {
    				if (i == this.TextLength - 1) {
    					mRealLine++;// 真实的行数加一
    				}
    			}
    	   }
    	}
    	mRealLine++;//额外增加一行
    	mTextWidth = mLineWidth*mRealLine;//计算文字总宽度
    	measure(mTextWidth, getHeight());//重新调整大小
        layout(getLeft(), getTop(), getLeft()+mTextWidth, getBottom());//重新绘制容器
    }
    @Override   
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
		int measuredHeight = measureHeight(heightMeasureSpec);  
		//int measuredWidth = measureWidth(widthMeasureSpec);  
		if(mTextWidth==0)GetTextInfo();
		setMeasuredDimension(mTextWidth, measuredHeight);  
		if(oldwidth!=getWidth()){//
			oldwidth=getWidth();
			if(mHandler!=null)mHandler.sendEmptyMessage(LAYOUT_CHANGED);
		}
	}  
		  
	private int measureHeight(int measureSpec) {  
		int specMode = MeasureSpec.getMode(measureSpec);  
		int specSize = MeasureSpec.getSize(measureSpec);  
		int result = 500;  
		if (specMode == MeasureSpec.AT_MOST){  
			result = specSize;  
		}else if (specMode == MeasureSpec.EXACTLY){  
			result = specSize;  
		}  
		mTextHeight=result;//设置文本高度
		return result;  
	}  
	/*  
	private int measureWidth(int measureSpec) {  
		int specMode = MeasureSpec.getMode(measureSpec);  
		int specSize = MeasureSpec.getSize(measureSpec);  
		int result = 500;  
		if (specMode == MeasureSpec.AT_MOST){  
			result = specSize;  
		}else if (specMode == MeasureSpec.EXACTLY){  
			result = specSize;  
		}  
		return result;  
	}  */
}

 

 

(2)使用界面:

package org.guyue;

import android.app.Activity;
//import android.graphics.Typeface;
import android.os.Bundle;
import android.os.Handler;
import android.widget.HorizontalScrollView;

public class TestFontActivity extends Activity{
	private HorizontalScrollView sv;
	private TextViewVertical tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
    	 super.onCreate(savedInstanceState);
         setContentView(R.layout.main);
         
         tv=(TextViewVertical)findViewById(R.id.tv);  
         sv=(HorizontalScrollView)findViewById(R.id.sv);  
         
         //设置接口事件接收
         Handler handler=new Handler(){
     		public void handleMessage(android.os.Message msg) {
     			switch(msg.what){
     				case TextViewVertical.LAYOUT_CHANGED:
     					sv.scrollBy(tv.getTextWidth(), 0);//滚动到最右边
     					break;
     			}
     		}
         };
         tv.setHandler(handler);//将Handler绑定到TextViewVertical
         
         //创建并设置字体(这里只是为了效果好看一些,但为了让网友们更容易下载,字体库并没有一同打包
         //如果需要体验下效果的朋友可以自行在网络上搜索stxingkai.ttf并放入assets/fonts/中)
         //Typeface face=Typeface.createFromAsset(getAssets(),"fonts/stxingkai.ttf");
         //tv.setTypeface(face);
         
         //设置文字内容
         tv.setText("测试\n这是一段测试文字,主要是为了测试竖直排版TextView的显示效果。" +
         		"为了能更好的体验感受,我特意增加了比较接近书法的字体和颜色,如果有什么改进的建议请发邮件到我的邮箱吧。" +
         		"\n竖直排版的TextView需要配合HorizontalScrollView使用才能有更佳的效果。当然,如果你有时间的话,也可以给这个类" +
         		"加上滚动的功能。");
    }

}

 

简单易用,工程见附件

 

分享到:
评论

相关推荐

    竖直排版(android)

    综上所述,实现竖直排版的Android TextView需要对Android的绘图系统有深入理解,包括自定义View、Canvas绘图、文字方向设置、测量与布局、滚动处理以及性能优化等方面的知识。通过这些技术,我们可以创建出一个功能...

    Android-一个文字竖直滚动的view控件

    在Android开发中,有时我们需要创建一个特殊的视图控件,以实现文字的竖直滚动效果。这在公告、滚动字幕或广告展示等场景中尤为常见。本篇将详细讲解如何构建这样一个`TextLooperView`,它是一个专门用于实现文字...

    android 竖直自定义进度条 带文字竖直进度条 类似电量显示

    总的来说,实现一个竖直自定义进度条并带文字显示的过程涉及到了Android的自定义View、样式配置、XML drawable以及布局管理等多个方面。理解这些知识点可以帮助开发者更自由地设计和定制Android应用的界面,提供更...

    Android竖直(竖直)漂亮seekbar的源码实现

    本篇文章将详细探讨如何在Android中实现一个美观的竖直SeekBar,以及相关的源码实现。 一、竖直SeekBar的原理 传统的SeekBar是基于水平方向的ViewGroup,如LinearLayout或RelativeLayout。要实现竖直SeekBar,我们...

    Android实现文字垂直滚动、纵向走马灯效果的实现方式汇总

    Android 实现文字垂直滚动、纵向走马灯效果的实现方式汇总 Android 实现文字垂直滚动、纵向走马灯效果是 Android-applications 中常见的效果,本文将为大家分享三种实现这种效果的方式,并对相关属性和注意事项进行...

    Android垂直滚动

    在Android开发中,垂直滚动是用户界面中常见的一种交互方式,尤其在长内容展示时尤为重要。本主题将深入探讨如何实现Android垂直滚动,主要聚焦于`ScrollView`组件的使用及其改写。 `ScrollView`是Android SDK提供...

    Android-竖直SeekBar源码.zip

    Android-竖直SeekBar源码.zip Android-竖直SeekBar源码.zip Android-竖直SeekBar源码.zip

    android竖直滑动的效果wheelview

    在Android开发中,实现竖直滑动的效果,通常会用到一些特定的视图组件,如`WheelView`。`WheelView`是一个可滚动的选择器,它可以用来展示一系列的数据,并且用户可以通过上下滑动来选择其中的一项。在这个案例中,...

    安卓时间轴时光轴相关-Android竖直时光轴效果可扩展支持图文排版.rar

    Android竖直时光轴效果,可扩展,支持图文排版.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。

    Android 自定义拍照实例(解决竖拍照片横向问题)

    本教程将深入探讨如何解决Android拍照时出现的竖拍照片横向显示的问题。这个问题通常出现在使用SurfaceView来显示相机预览,并通过Camera类进行拍照操作时。 首先,我们需要了解Android中的Camera类。Camera类是...

    竖直滚动TextView

    在Android开发中,有时我们需要创建一种特殊的用户界面元素,它能以竖直方向滚动显示文本信息,例如在公告栏或广告区域。这就是我们所说的“竖直滚动TextView”。这个功能可以帮助我们在有限的空间内展示大量文本,...

    android_SeekBar竖直显示自定义背景thumb完美Demo(附带解决说明)

    在Android开发中,SeekBar是一个非常常见的控件,用于让用户通过滑动来选择一个介于最小值和最大值之间的值。通常,SeekBar是水平显示的,但有时为了满足特定的界面设计需求,我们可能需要将其设置为竖直显示。本...

    Android 竖直刻度尺效果

    在Android开发中,创建一个竖直刻度尺效果通常是用于展示数据或指示度量值的可视化组件。这种效果可以应用于各种场景,如健康应用显示心率范围、金融应用表示股票指数,或者是测量工具类应用等。本文将详细介绍如何...

    Android垂直tab导航栏、左侧竖直tab导航栏

    "Android垂直tab导航栏、左侧竖直tab导航栏"就是这样一个设计,它允许用户在屏幕左侧以竖直的方式浏览和选择不同的选项卡,提供了一种不同于传统水平选项卡的新颖体验。 这个设计不仅支持使用ViewPager,而且可以...

    Android项目竖直滑动条.rar

    本项目“Android项目竖直滑动条.rar”显然专注于实现垂直方向上的滑动条,这在某些应用场景中非常实用,比如空间有限或者设计需要时。下面将详细介绍这个项目可能涉及的知识点和实现细节。 1. **自定义View**: 在...

    旋转TextView文字显示

    本篇文章将详细探讨如何实现“旋转TextView文字显示”,并结合提供的压缩包文件`android-typeface-helper-master`中的内容进行讲解。 首先,我们要明白,TextView的文字旋转可以通过修改其属性来实现。在XML布局...

    Android案例页面底部弹框PopupWindow+竖直滑动选择器WheelView的实现

    `PopupWindow`常用于创建底部弹出框,而`WheelView`则是一个可滚动的选择器,通常用于日期选择、时间选择等场景。下面将详细介绍这两个组件的使用方法以及如何将它们结合在实际应用中。 ### 1. PopupWindow详解 `...

Global site tag (gtag.js) - Google Analytics