android Html.fromHtml使用详解

 更新时间:2016年10月2日 16:23  点击:2611
下面我们来看一篇android Html.fromHtml使用方法,希望文章能够让各位深入的理解到android Html.fromHtml使用细节哦。

项目中往往需要显示一段文本,如果对文本需要特定的效果,就要写自定义的span,这样的工作量会变得很大,目前android支持html格式的文本。提供了两个接口,下面我们就来看一下怎么使用。

1. Spanned android.text.Html.fromHtml(String source) //输入的参数为(html格式的文本)

目前android不支持全部的html的标签,目前只支持与文本显示和段落等标签,对于图片和其他的多媒体,还有一些自定义标签不能识别;

例子:


TextView t3 = (TextView) findViewById(R.id.text3);  
t3.setText(Html.fromHtml( "<b>text3:</b>  Text with a " + "<a href=\"http://www.google.com\">link</a> " +"created in the Java source code using HTML.")); 

另外也可以在string.xml中使用,但是要用用<!–cdata–>去转义。如下例子:


<string name="htmlFormattedText">
 <![CDATA[
 Text with markup for [b]bold[/b]
 and [i]italic[/i] text.
 
 There is also support for a
 <tt>teletype-style</tt> font.
 But no use for the <code>code</code>
 tag!
 
 ]]></string>
 
TextView view = (TextView)findViewById(R.id.sampleText);
String formattedText = getString(R.string.htmlFormattedText);
Spanned result = Html.fromHtml(formattedText);
view.setText(result);
 

2.Spanned android.text.Html.fromHtml(String source, ImageGetter imageGetter, TagHandler tagHandler)

Source:    需处理的html文本
imageGetter :对图片处理(处理html中的图片标签)

tagHandler  :对标签进行处理(相当于自定义的标签处理,在这里面可以处理自定义的标签)

具体不细说,大家感兴趣可以自行学习;在实际项目里我们就可以使用第一种方式来替代之前我们用的自定义span了。

下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false">
 
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="60dp"
        android:background="@mipmap/www" />
 
 
    <LinearLayout
        android:id="@+id/ll_bottom"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:background="#F8549D"
        android:elevation="10dp"
        android:orientation="horizontal">
 
        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="bottom"
            android:layout_weight="1">
 
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@mipmap/ic_launcher" />
 
        </RelativeLayout>
 
        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="bottom"
            android:layout_weight="1">
 
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@mipmap/ic_launcher" />
 
        </RelativeLayout>
 
        <RelativeLayout
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:layout_gravity="bottom"
            android:background="@drawable/bottom_bg_shape">
 
            <ImageView
                android:layout_width="30dp"
                android:layout_height="30dp"
                android:layout_centerInParent="true"
                android:src="@mipmap/icon_go" />
 
        </RelativeLayout>
 
 
        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="bottom"
            android:layout_weight="1">
 
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@mipmap/ic_launcher" />
 
        </RelativeLayout>
 
        <RelativeLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_gravity="bottom"
            android:layout_weight="1">
 
            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:src="@mipmap/ic_launcher" />
 
        </RelativeLayout>
    </LinearLayout>
 
</RelativeLayout>

这张图呢是我刚刚做的,效果是参考了酷狗音乐播放器来完成的,我想说明重点在底部的导航栏:如图

 再来一张反效果预览图:
 
 
2016-08-04_101104
 
 如何使得蓝色圆形的播放键的显示越过粉色的范围。当然经过合理的布局是可以达到这样的效果的,但是却有更简单的方法。也就是在根布局的属性中加入一个来自Android自身提供的属性:


android:clipChildren="false"

属性解释和说明:

1、android:clipChildren的意思:是否限制子View在其范围内

2、可以通过android:layout_gravity控制超出的部分如何显示。

3、只需在根节点设置android:clipChildren为false即可,默认为true

下面小编为各位整理一些关于安卓开发ViewPager图片预览之图片的放大缩小,移动,切换的基本知识与例子,具体的如下介绍。

1,自由的放大和缩小

2.双击放大与缩小

3.放大以后可以进行自由的移动

4.处理与ViewPager之间的的事件冲突

需要用到的知识点

1.Matrix (图片放大,缩小需要用到矩阵)

2.ScaleGestureDetector(检测用户多指触控时缩放的手势)

3.GestureDetector:检测用户双击时需要做的一些处理

4.事件分发机制(当我们图片放大时,我们的图片是可以左右移动的,在ViewPager左右切换图片,两者会有冲突)。

 


----------------------------------------------------代码设计

第一课

第一步 :自定义ImageView 实现图片自适应控件大小:(效果是:图片小于控件大小时,放大到控件大小,图片大于控件大小时,自动缩小到控件大小)


package com.example.viewpagerimage;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;


//实现监听器OnGlobalLayoutListener,监听图片是否加载完成
public class MyImageView extends ImageView implements OnGlobalLayoutListener{

 private boolean mOnce;//判断是否初始化
 private float mInitScale;//初始化时缩放的值
 private float mMidScale;//双击放大到达的值
 private float mMaxScale;//放大的最大值

 private Matrix mScaleMatrix;
 public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  //init
  mScaleMatrix = new Matrix();
  setScaleType(ScaleType.MATRIX);
  //当图片加载时,图片可能很大,也可能很小,需要让图片自适应屏幕大小,当图片太大时自动缩小到屏幕大小,当图片太小时放大到屏幕大小。

 }

 public MyImageView(Context context, AttributeSet attrs) {
  this(context, attrs,0);
  // TODO Auto-generated constructor stub
 }

 public MyImageView(Context context) {
  this(context,null);
  // TODO Auto-generated constructor stub
 }
 @Override
 protected void onAttachedToWindow() {
  // TODO Auto-generated method stub
  super.onAttachedToWindow();//当View 显示在屏幕上时调用
  getViewTreeObserver().addOnGlobalLayoutListener(this);//注册接口
 }
 @SuppressWarnings("deprecation")
 @Override
 protected void onDetachedFromWindow() {
  // TODO Auto-generated method stub
  super.onDetachedFromWindow();//当View从屏幕上移除时调用
  getViewTreeObserver().removeGlobalOnLayoutListener(this);//移除接口
 }
 /**
  * 获取ImageView加载完成的图片
  */
 @Override
 public void onGlobalLayout() {
  // 全局的布局完成后调用
  if(!mOnce){
   //得到控件的宽和高
   int width = getWidth();
   int height = getHeight();
   //得到我们的图片以及宽和高
   Drawable d = getDrawable();
   if(d == null)
    return;

   int dw = d.getIntrinsicWidth();
   int dh = d.getIntrinsicHeight();
   float scale = 1.0f;//缩放值
   //如果图片的宽度大于控件高度,但是宽度小于控件的宽度,将其缩小
   if(dw > width && dh < height){
    scale = width*1.0f/dw;
   }
   else if(dh > height && dw < width){
    scale = height*1.0f /dh;
   }

   else if(dw > width && dh > height){
    scale = Math.min(width*1.0f/dw, height*1.0f/dh);
   }
   else if(dw < width && dh < height){
    scale = Math.min(width *1.0f/dw, height*1.0f/dh);
   }
   /*
    * 得到初始化时缩放的比例
    * */

   mInitScale = scale;
   mMaxScale = mInitScale * 4;
   mMidScale = mInitScale * 2;

   //将图片移动到当前控件的中心
   int dx = getWidth()/2 - dw /2;
   int dy = getHeight()/2 - dh/2;

   mScaleMatrix.postTranslate(dx, dy);//平移
   mScaleMatrix.postScale(mInitScale, mInitScale,width/2,height/2);//缩放,后面两个参数是缩放的中心点
   setImageMatrix(mScaleMatrix);

   mOnce = true;

 

 

  }
 }
}

布局文件使用:


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.viewpagerimage.MainActivity" >

    <com.example.viewpagerimage.MyImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="matrix"
        android:src="@drawable/viewpatherimage" />

</LinearLayout>


第二步:给自定义控件添加支持手指触控缩放的功能:(支持手指触控放大)

因为涉及到手势触摸事件所以要实现OnScaleGestureListener,OnTouchListener这两个接口。

声明成员变量: private ScaleGestureDetector mScaleGestureDetector;//捕获用户多指触控缩放的比例

在构造函数中初始化:

mScaleGestureDetector = new ScaleGestureDetector(context, this);
setOnTouchListener(this);

 

 

添加方法:


/**\
  * 获取当前图片的缩放值
  * @return
  */
 public float getScale(){
  float[] values = new float[9];
  mScaleMatrix.getValues(values);
  return values[Matrix.MSCALE_X];

 }

 

实现接口中的方法:

 

 

//缩放的区间,initScale maxScale
 @Override
 public boolean onScale(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  float scale = getScale();
  float scaleFactor = detector.getScaleFactor();//得到缩放的值

  if(getDrawable() == null){
   return true;
  }
  //缩放范围的控制
  if((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)){
   if(scale * scaleFactor < mInitScale){
    scaleFactor = mInitScale / scale;//当手指缩放小于最小值时 ,默认显示最小的比例
   }
   if(scale * scaleFactor > mMaxScale){//当手指缩放大于于最大值时 ,默认显示最大的比例
    scale = mMaxScale/scale;
   }
   //缩放
   mScaleMatrix.postScale(scaleFactor, scaleFactor, getWidth()/2, getHeight()/2);
   setImageMatrix(mScaleMatrix);
  }
  return true;//设置完成返回true保证事件能够进行
 }

 @Override
 public boolean onScaleBegin(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  return true;//必须返回true
 }

 @Override
 public void onScaleEnd(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub

 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO Auto-generated method stub
  mScaleGestureDetector.onTouchEvent(event);//把event传递给mscaleGestureDetector处理
  return true;//必须返true
 }

 

 


全部代码如下:


package com.example.viewpagerimage;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;
import android.view.View.OnTouchListener;

//实现监听器OnGlobalLayoutListener,监听图片是否加载完成
public class MyImageView extends ImageView implements OnGlobalLayoutListener, OnScaleGestureListener,OnTouchListener{

 private boolean mOnce;//判断是否初始化
 private float mInitScale;//初始化时缩放的值
 private float mMidScale;//双击放大到达的值
 private float mMaxScale;//放大的最大值

 private ScaleGestureDetector mScaleGestureDetector;//捕获用户多指触控缩放的比例

 private Matrix mScaleMatrix;
 public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  //init
  mScaleMatrix = new Matrix();
  setScaleType(ScaleType.MATRIX);

  mScaleGestureDetector = new ScaleGestureDetector(context, this);
  
  setOnTouchListener(this);
  //当图片加载时,图片可能很大,也可能很小,需要让图片自适应屏幕大小,当图片太大时自动缩小到屏幕大小,当图片太小时放大到屏幕大小。

 }

 public MyImageView(Context context, AttributeSet attrs) {
  this(context, attrs,0);
  // TODO Auto-generated constructor stub
 }

 public MyImageView(Context context) {
  this(context,null);
  // TODO Auto-generated constructor stub
 }
 @Override
 protected void onAttachedToWindow() {
  // TODO Auto-generated method stub
  super.onAttachedToWindow();//当View 显示在屏幕上时调用
  getViewTreeObserver().addOnGlobalLayoutListener(this);//注册接口
 }
 @SuppressWarnings("deprecation")
 @Override
 protected void onDetachedFromWindow() {
  // TODO Auto-generated method stub
  super.onDetachedFromWindow();//当View从屏幕上移除时调用
  getViewTreeObserver().removeGlobalOnLayoutListener(this);//移除接口
 }
 /**
  * 获取ImageView加载完成的图片
  */
 @Override
 public void onGlobalLayout() {
  // 全局的布局完成后调用
  if(!mOnce){
   //得到控件的宽和高
   int width = getWidth();
   int height = getHeight();
   //得到我们的图片以及宽和高
   Drawable d = getDrawable();
   if(d == null)
    return;

   int dw = d.getIntrinsicWidth();
   int dh = d.getIntrinsicHeight();
   float scale = 1.0f;//缩放值
   //如果图片的宽度大于控件高度,但是宽度小于控件的宽度,将其缩小
   if(dw > width && dh < height){
    scale = width*1.0f/dw;
   }
   else if(dh > height && dw < width){
    scale = height*1.0f /dh;
   }

   else if(dw > width && dh > height){
    scale = Math.min(width*1.0f/dw, height*1.0f/dh);
   }
   else if(dw < width && dh < height){
    scale = Math.min(width *1.0f/dw, height*1.0f/dh);
   }
   /*
    * 得到初始化时缩放的比例
    * */

   mInitScale = scale;
   mMaxScale = mInitScale * 4;
   mMidScale = mInitScale * 2;

   //将图片移动到当前控件的中心
   int dx = getWidth()/2 - dw /2;
   int dy = getHeight()/2 - dh/2;

   mScaleMatrix.postTranslate(dx, dy);//平移
   mScaleMatrix.postScale(mInitScale, mInitScale,width/2,height/2);//缩放,后面两个参数是缩放的中心点
   setImageMatrix(mScaleMatrix);

   mOnce = true;

 

 

  }
 }
 /**\
  * 获取当前图片的缩放值
  * @return
  */
 public float getScale(){
  float[] values = new float[9];
  mScaleMatrix.getValues(values);
  return values[Matrix.MSCALE_X];

 }
 //缩放的区间,initScale maxScale
 @Override
 public boolean onScale(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  float scale = getScale();
  float scaleFactor = detector.getScaleFactor();//得到缩放的值

  if(getDrawable() == null){
   return true;
  }
  //缩放范围的控制
  if((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)){
   if(scale * scaleFactor < mInitScale){
    scaleFactor = mInitScale / scale;//当手指缩放小于最小值时 ,默认显示最小的比例
   }
   if(scale * scaleFactor > mMaxScale){//当手指缩放大于于最大值时 ,默认显示最大的比例
    scale = mMaxScale/scale;
   }
   //缩放
   mScaleMatrix.postScale(scaleFactor, scaleFactor, getWidth()/2, getHeight()/2);
   setImageMatrix(mScaleMatrix);
  }
  return true;//设置完成返回true保证事件能够进行
 }

 @Override
 public boolean onScaleBegin(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  return true;//必须返回true
 }

 @Override
 public void onScaleEnd(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub

 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO Auto-generated method stub
  mScaleGestureDetector.onTouchEvent(event);//把event传递给mscaleGestureDetector处理
  return true;//必须返true
 }
}

目前实现的效果:无论手指触摸哪里都是以中心点位中心开始缩放的。

下面实现的效果是:以手指触控的任意点为中心开始缩放

第三课(第三步):支持以手指触控的任意点为中心开始缩放

关键部分是在缩放的时候不断进行边界检测,防止放大后缩小后出现白边:


/**
  * 在缩放的时候进行边界控制范围位置控制
  */

 private void checkBorderAndCenterWhenScale() {
  // TODO Auto-generated method stub
  RectF rect = getMatrixRectF();
  float deltaX = 0;
  float deltaY = 0;

  float width = getWidth();
  float height = getHeight();
  //缩放时进行边界检测,放在出现白边
  if(rect.width() >= width){
   if(rect.left > 0){//处理左边的空白
    deltaX = -rect.left;
   }
   if(rect.right < width){//处理右边的空白
    deltaX = (int) (width - rect.right);
   }
  }
  if(rect.height() >= height){
   if(rect.top > 0){
    deltaY = -rect.top;
   }
   if(rect.bottom < height){
    deltaY = height - rect.bottom;
   }
  }
  //如果宽度或高度小于控件的宽或高,则让其居中
  if(rect.width() < width){
   deltaX = width/2f -rect.right + rect.width()/2f;
  }
  if(rect.height() < height){
   deltaY = height /2f -rect.bottom + rect.height()/2f;
  }
  mScaleMatrix.postTranslate(deltaX, deltaY);

 }

全部代码:


package com.example.viewpagerimage;

import android.content.Context;
import android.graphics.Matrix;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.ScaleGestureDetector.OnScaleGestureListener;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;

//实现监听器OnGlobalLayoutListener,监听图片是否加载完成
public class MyImageView extends ImageView implements OnGlobalLayoutListener, OnScaleGestureListener,OnTouchListener{

 private boolean mOnce;//判断是否初始化
 private float mInitScale;//初始化时缩放的值
 private float mMidScale;//双击放大到达的值
 private float mMaxScale;//放大的最大值

 private ScaleGestureDetector mScaleGestureDetector;//捕获用户多指触控缩放的比例

 private Matrix mScaleMatrix;
 public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  //init
  mScaleMatrix = new Matrix();
  setScaleType(ScaleType.MATRIX);

  mScaleGestureDetector = new ScaleGestureDetector(context, this);

  setOnTouchListener(this);
  //当图片加载时,图片可能很大,也可能很小,需要让图片自适应屏幕大小,当图片太大时自动缩小到屏幕大小,当图片太小时放大到屏幕大小。

 }

 public MyImageView(Context context, AttributeSet attrs) {
  this(context, attrs,0);
  // TODO Auto-generated constructor stub
 }

 public MyImageView(Context context) {
  this(context,null);
  // TODO Auto-generated constructor stub
 }
 @Override
 protected void onAttachedToWindow() {
  // TODO Auto-generated method stub
  super.onAttachedToWindow();//当View 显示在屏幕上时调用
  getViewTreeObserver().addOnGlobalLayoutListener(this);//注册接口
 }
 @SuppressWarnings("deprecation")
 @Override
 protected void onDetachedFromWindow() {
  // TODO Auto-generated method stub
  super.onDetachedFromWindow();//当View从屏幕上移除时调用
  getViewTreeObserver().removeGlobalOnLayoutListener(this);//移除接口
 }
 /**
  * 获取ImageView加载完成的图片
  */
 @Override
 public void onGlobalLayout() {
  // 全局的布局完成后调用
  if(!mOnce){
   //得到控件的宽和高
   int width = getWidth();
   int height = getHeight();
   //得到我们的图片以及宽和高
   Drawable d = getDrawable();
   if(d == null)
    return;

   int dw = d.getIntrinsicWidth();
   int dh = d.getIntrinsicHeight();
   float scale = 1.0f;//缩放值
   //如果图片的宽度大于控件高度,但是宽度小于控件的宽度,将其缩小
   if(dw > width && dh < height){
    scale = width*1.0f/dw;
   }
   else if(dh > height && dw < width){
    scale = height*1.0f /dh;
   }

   else if(dw > width && dh > height){
    scale = Math.min(width*1.0f/dw, height*1.0f/dh);
   }
   else if(dw < width && dh < height){
    scale = Math.min(width *1.0f/dw, height*1.0f/dh);
   }
   /*
    * 得到初始化时缩放的比例
    * */

   mInitScale = scale;
   mMaxScale = mInitScale * 4;
   mMidScale = mInitScale * 2;

   //将图片移动到当前控件的中心
   int dx = getWidth()/2 - dw /2;
   int dy = getHeight()/2 - dh/2;

   mScaleMatrix.postTranslate(dx, dy);//平移
   mScaleMatrix.postScale(mInitScale, mInitScale,width/2,height/2);//缩放,后面两个参数是缩放的中心点
   setImageMatrix(mScaleMatrix);

   mOnce = true;

 

 

  }
 }
 /**
  * 获取当前图片的缩放值
  * @return
  */
 public float getScale(){
  float[] values = new float[9];
  mScaleMatrix.getValues(values);
  return values[Matrix.MSCALE_X];

 }
 //缩放的区间,initScale maxScale
 @Override
 public boolean onScale(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  float scale = getScale();
  float scaleFactor = detector.getScaleFactor();//得到缩放的值

  if(getDrawable() == null){
   return true;
  }
  //缩放范围的控制
  if((scale < mMaxScale && scaleFactor > 1.0f) || (scale > mInitScale && scaleFactor < 1.0f)){
   if(scale * scaleFactor < mInitScale){
    scaleFactor = mInitScale / scale;//当手指缩放小于最小值时 ,默认显示最小的比例
   }
   if(scale * scaleFactor > mMaxScale){//当手指缩放大于于最大值时 ,默认显示最大的比例
    scale = mMaxScale/scale;
   }
   //缩放,缩放中心是手指触控的地方
   mScaleMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(),detector.getFocusY());
   checkBorderAndCenterWhenScale();

   setImageMatrix(mScaleMatrix);
  }
  return true;//设置完成返回true保证事件能够进行
 }

 /**
  * 获得图片放大缩小以后的宽和高以及l r t b
  * @return
  */
 private RectF getMatrixRectF(){
  Matrix matrix = mScaleMatrix;
  RectF recF = new RectF();
  Drawable d = getDrawable();
  if(d != null){
   recF.set(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
   matrix.mapRect(recF);
  }
  return recF;
 }
 /**
  * 在缩放的时候进行边界控制范围位置控制
  */

 private void checkBorderAndCenterWhenScale() {
  // TODO Auto-generated method stub
  RectF rect = getMatrixRectF();
  float deltaX = 0;
  float deltaY = 0;

  float width = getWidth();
  float height = getHeight();
  //缩放时进行边界检测,放在出现白边
  if(rect.width() >= width){
   if(rect.left > 0){//处理左边的空白
    deltaX = -rect.left;
   }
   if(rect.right < width){//处理右边的空白
    deltaX = (int) (width - rect.right);
   }
  }
  if(rect.height() >= height){
   if(rect.top > 0){
    deltaY = -rect.top;
   }
   if(rect.bottom < height){
    deltaY = height - rect.bottom;
   }
  }
  //如果宽度或高度小于控件的宽或高,则让其居中
  if(rect.width() < width){
   deltaX = width/2f -rect.right + rect.width()/2f;
  }
  if(rect.height() < height){
   deltaY = height /2f -rect.bottom + rect.height()/2f;
  }
  mScaleMatrix.postTranslate(deltaX, deltaY);

 }

 @Override
 public boolean onScaleBegin(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub
  return true;//必须返回true
 }

 @Override
 public void onScaleEnd(ScaleGestureDetector detector) {
  // TODO Auto-generated method stub

 }

 @Override
 public boolean onTouch(View v, MotionEvent event) {
  // TODO Auto-generated method stub
  mScaleGestureDetector.onTouchEvent(event);//把event传递给mscaleGestureDetector处理
  return true;//必须返true
 }
}

下面我们来看一篇关于Android 开发之布局细节对比:RTL模式 ,希望这篇文章对各位同学会带来帮助,具体的细节如下介绍。

前言

讲真,好久没写博客了,2016都过了一半了,赶紧重新捡起来。(个人感慨,和内容无关……
所谓RTL,顾名思义也就是Right To Left,是一种阿拉伯语、波斯语等情况下从右往左的阅读方式。当所开发的App等面向海外用户时需要做这个适配。

从Android 4.2开始支持原生的RTL模式,对此之前的版本我也不想多做说明,这些老版本要是还支持那Android碎片化就没完没了了。

正文

如何查看效果

首先要说的是,想要看RTL模式,不必去把手机中的语言/国家设置到阿拉伯等,只需要在“开发者选项”中勾选“强制使用从右到左的布局方向“,这样真的是方便太多了。

此处以MIUI为例,大家也不妨自己动手试试。

如图,原本左右两侧的控件发生了对调,值得注意的是图中红色方框标注的图标发生了翻转(更标准的说法是”镜像“)。

如何支持RTL

是不是很有意思呢,那么如果在你的App中适配RTL呢?

1,需要在清单文件总队RTL的支持做一个声明,放到< application >节点下。

android:supportsRtl="true"
2,将布局中的”left、right“相关的属性换成对应的”start、end“属性。

这一步可能用说的不够清晰,看代码看图!

    <Button
        android:id="@+id/button"
        android:text="A"
        android:layout_width="60dp"
        android:layout_height="40dp" />

    <Button
        android:id="@+id/button2"
        android:text="B"
        android:layout_toRightOf="@id/button"
        android:layout_width="60dp"
        android:layout_height="40dp" />

    <Button
        android:id="@+id/button3"
        android:text="C"
        android:layout_toRightOf="@id/button2"
        android:layout_width="60dp"
        android:layout_height="40dp" />

应该可以看出来这是在一个相对布局中,默认情况下是这样的:

开启RTL后,却是这样的:

为什么B、C按钮不见了?因为根据属性,它们都在A的右边,这已经超出的屏幕边界。

如果我们对布局做一点修改:

android:layout_toRightOf
改成
android:layout_toEndOf

如果有left,也照搬改成start就好。

页面不想支持RTL怎么办

有一些界面你不想它支持RTL,或者它本身不需要支持,那又该如何呢?比如说拨号界面,难道要把数字键也镜像过去吗:

只需要加上这么一句就好了呀。

layoutDirect可以使用4种属性:
ltr:从左往右
rtl:从右往左
inherit:从上层视图中继承
locale:由Locale决定

分别对应的int值为0,1,2,3。
图片怎么办
只需要创建一个文件夹,把镜像后的图片放进去即可,代码中不用做任何修改。

drawable-ldrtl-xhdpi
drawable-xhdpi

分辨率是一一对应的


当然了,除了对图像做预处理外,要是想用代码直接控制也是可以的。

private ImageView image2;

// 省略

image2 =  (ImageView) findViewById(R.id.image2);

Drawable arrow = getResources().getDrawable(R.drawable.arrow);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
    if (arrow != null) {
       arrow.setAutoMirrored(true);
    }
}
image2.setImageDrawable(arrow);

[!--infotagslink--]

相关文章

  • 图解PHP使用Zend Guard 6.0加密方法教程

    有时为了网站安全和版权问题,会对自己写的php源码进行加密,在php加密技术上最常用的是zend公司的zend guard 加密软件,现在我们来图文讲解一下。 下面就简单说说如何...2016-11-25
  • Android子控件超出父控件的范围显示出来方法

    下面我们来看一篇关于Android子控件超出父控件的范围显示出来方法,希望这篇文章能够帮助到各位朋友,有碰到此问题的朋友可以进来看看哦。 <RelativeLayout xmlns:an...2016-10-02
  • ps怎么使用HSL面板

    ps软件是现在很多人都会使用到的,HSL面板在ps软件中又有着非常独特的作用。这次文章就给大家介绍下ps怎么使用HSL面板,还不知道使用方法的下面一起来看看。 &#8195;...2017-07-06
  • php中去除文字内容中所有html代码

    PHP去除html、css样式、js格式的方法很多,但发现,它们基本都有一个弊端:空格往往清除不了 经过不断的研究,最终找到了一个理想的去除html包括空格css样式、js 的PHP函数。...2013-08-02
  • Plesk控制面板新手使用手册总结

    许多的朋友对于Plesk控制面板应用不是非常的了解特别是英文版的Plesk控制面板,在这里小编整理了一些关于Plesk控制面板常用的使用方案整理,具体如下。 本文基于Linu...2016-10-10
  • 使用insertAfter()方法在现有元素后添加一个新元素

    复制代码 代码如下: //在现有元素后添加一个新元素 function insertAfter(newElement, targetElement){ var parent = targetElement.parentNode; if (parent.lastChild == targetElement){ parent.appendChild(newEl...2014-05-31
  • Android开发中findViewById()函数用法与简化

    findViewById方法在android开发中是获取页面控件的值了,有没有发现我们一个页面控件多了会反复研究写findViewById呢,下面我们一起来看它的简化方法。 Android中Fin...2016-09-20
  • Android模拟器上模拟来电和短信配置

    如果我们的项目需要做来电及短信的功能,那么我们就得在Android模拟器开发这些功能,本来就来告诉我们如何在Android模拟器上模拟来电及来短信的功能。 在Android模拟...2016-09-20
  • 使用GruntJS构建Web程序之构建篇

    大概有如下步骤 新建项目Bejs 新建文件package.json 新建文件Gruntfile.js 命令行执行grunt任务 一、新建项目Bejs源码放在src下,该目录有两个js文件,selector.js和ajax.js。编译后代码放在dest,这个grunt会...2014-06-07
  • 使用percona-toolkit操作MySQL的实用命令小结

    1.pt-archiver 功能介绍: 将mysql数据库中表的记录归档到另外一个表或者文件 用法介绍: pt-archiver [OPTION...] --source DSN --where WHERE 这个工具只是归档旧的数据,不会对线上数据的OLTP查询造成太大影响,你可以将...2015-11-24
  • 如何使用php脚本给html中引用的js和css路径打上版本号

    在搜索引擎中搜索关键字.htaccess 缓存,你可以搜索到很多关于设置网站文件缓存的教程,通过设置可以将css、js等不太经常更新的文件缓存在浏览器端,这样访客每次访问你的网站的时候,浏览器就可以从浏览器的缓存中获取css、...2015-11-24
  • 夜神android模拟器设置代理的方法

    夜神android模拟器如何设置代理呢?对于这个问题其实操作起来是非常的简单,下面小编来为各位详细介绍夜神android模拟器设置代理的方法,希望例子能够帮助到各位。 app...2016-09-20
  • android自定义动态设置Button样式【很常用】

    为了增强android应用的用户体验,我们可以在一些Button按钮上自定义动态的设置一些样式,比如交互时改变字体、颜色、背景图等。 今天来看一个通过重写Button来动态实...2016-09-20
  • jQuery 1.9使用$.support替代$.browser的使用方法

    jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support 。 在更新的 2.0 版本中,将不再支持 IE 6/7/8。 以后,如果用户需要支持 IE 6/7/8,只能使用 jQuery 1.9。 如果要全面支持 IE,并混合...2014-05-31
  • Android WebView加载html5页面实例教程

    如果我们要在Android应用APP中加载html5页面,我们可以使用WebView,本文我们分享两个WebView加载html5页面实例应用。 实例一:WebView加载html5实现炫酷引导页面大多...2016-09-20
  • 安装和使用percona-toolkit来辅助操作MySQL的基本教程

    一、percona-toolkit简介 percona-toolkit是一组高级命令行工具的集合,用来执行各种通过手工执行非常复杂和麻烦的mysql和系统任务,这些任务包括: 检查master和slave数据的一致性 有效地对记录进行归档 查找重复的索...2015-11-24
  • 深入理解Android中View和ViewGroup

    深入理解Android中View和ViewGroup从组成架构上看,似乎ViewGroup在View之上,View需要继承ViewGroup,但实际上不是这样的。View是基类,ViewGroup是它的子类。本教程我们深...2016-09-20
  • MySQL日志分析软件mysqlsla的安装和使用教程

    一、下载 mysqlsla [root@localhost tmp]# wget http://hackmysql.com/scripts/mysqlsla-2.03.tar.gz--19:45:45-- http://hackmysql.com/scripts/mysqlsla-2.03.tar.gzResolving hackmysql.com... 64.13.232.157Conn...2015-11-24
  • php语言中使用json的技巧及json的实现代码详解

    目前,JSON已经成为最流行的数据交换格式之一,各大网站的API几乎都支持它。我写过一篇《数据类型和JSON格式》,探讨它的设计思想。今天,我想总结一下PHP语言对它的支持,这是开发互联网应用程序(特别是编写API)必须了解的知识...2015-10-30
  • Android自定义WebView网络视频播放控件例子

    下面我们来看一篇关于Android自定义WebView网络视频播放控件开发例子,这个文章写得非常的不错下面给各位共享一下吧。 因为业务需要,以下代码均以Youtube网站在线视...2016-10-02