FrameLayout(帧布局)

常用属性

FrameLayout的属性很少就两个,但是在说之前我们先介绍一个东西:

前景图像:永远处于帧布局最上面,直接面对用户的图像,就是不会被覆盖的图片。

两个属性:

  • android:foreground:*设置改帧布局容器的前景图像
  • android:foregroundGravity:设置前景图像显示的位置

TableLayout(表格布局)

常用属性

android:collapseColumns:设置需要被隐藏的列的序号
android:shrinkColumns:设置允许被收缩的列的列序号
android:stretchColumns:设置运行被拉伸的列的列序号

以上这三个属性的列号都是从0开始算的,比如shrinkColunmns ="2",对应的是第三列!
可以设置多个,用逗号隔开比如"0,2",如果是所有列都生效,则用"*"号即可
除了这三个常用属性,还有两个属性,分别就是跳格子以及合并单元格,这和HTML中的Table类似:

android:layout_column="2":表示的就是跳过第二个,直接显示到第三个格子处,从1开始算的!
android:layout_span="4":表示合并4个单元格,也就说这个组件占4个单元格

RelativeLayout(相对布局)

LinearLayout(线性布局)

listview作为一个列表控件,他和普通的列表一样,可以自己设置表头与表尾: 以及分割线,可供我们设置的属性如下:

·        footerDividersEnabled:是否在footerView(表尾)前绘制一个分隔条,默认为true

·        headerDividersEnabled:是否在headerView(表尾)前绘制一个分隔条,默认为true

·        divider:设置分隔条,可以用颜色分割,也可以用drawable资源分割

·        dividerHeight:设置分隔条的高度

翻遍了了API发现并没有可以直接设置ListView表头或者表尾的属性,只能在Java中写代码 进行设置了,可供我们调用的方法如下:

·        addHeaderView(View v):添加headView(表头),括号中的参数是一个View对象

·        addFooterView(View v):添加footerView(表尾),括号中的参数是一个View对象

·        addHeaderView(headView, null, false):和前面的区别:设置Header是否可以被选中

·        addFooterView(View,view,false):同上

对了,使用这个addHeaderView方法必须放在listview.setAdapter前面,否则会报错。

4.设置点击颜色cacheColorHint

如果你为ListView设置了一个图片作为Background的话,当你拖动或者点击listView空白位置会发现 item都变成黑色了,这是时候我们可以通过这个cacheColorHint将颜色设置为透明:#00000000


5.隐藏滑动条

我们可以通过设置:android:scrollbars="none" 或者setVerticalScrollBarEnabled(true); 解决这个问题!

3.列表从底部开始显示:stackFromBottom

如果你想让列表显示你列表的最下面的话,那么你可以使用这个属性,将stackFromBottom 属性设置为true即可,设置后的效果图如下:

ViewHolder重用组件

嘿嘿,getView()会被调用多次,那么findViewById不一样得调用多次,而我们的ListView的Item 一般都是一样的布局,我们可以对这里在优化下,我们可以自己定义一个ViewHolder类来对这一部分 进行性能优化!修改后的代码如下:

@Override

public View getView(intposition, View convertView, ViewGroup parent) {

ViewHolder holder = null;

if(convertView == null){

convertView =LayoutInflater.from(mContext).inflate(R.layout.item_list_animal,parent,false);

holder = new ViewHolder();

holder.img_icon = (ImageView) convertView.findViewById(R.id.img_icon);

holder.txt_aName = (TextView)convertView.findViewById(R.id.txt_aName);

holder.txt_aSpeak = (TextView)convertView.findViewById(R.id.txt_aSpeak);

convertView.setTag(holder);   //将Holder存储到convertView中

}else{

holder = (ViewHolder)convertView.getTag();

}

holder.img_icon.setBackgroundResource(mData.get(position).getaIcon());

holder.txt_aName.setText(mData.get(position).getaName());

holder.txt_aSpeak.setText(mData.get(position).getaSpeak());

return convertView;

}

static class ViewHolder{

ImageView img_icon;

TextView txt_aName;

TextView txt_aSpeak;

}

没错就是这么简单,你以后BaseAdapter照着这个模板写就对了,哈哈,另外这个修饰ViewHolder的 static,关于是否定义成静态,跟里面的对象数目是没有关系的,加静态是为了在多个地方使用这个 Holder的时候,类只需加载一次,如果只是使用了一次,加不加也没所谓!——Berial(B神)原话~

 

 

WebView文件下载

1.调用其它浏览器下载文件:

这个很简单,我们只需为WebView设置setDownloadListener,然后重写DownloadListener的 onDownloadStart,然后在里面写个Intent,然后startActivity对应的Activity即可!

关键代码如下

wView.setDownloadListener(new DownloadListener(){

@Override

public voidonDownloadStart(String url, String userAgent, String contentDisposition,

String mimetype, long contentLength) {

Log.e("HEHE","开始下载");

Uri uri = Uri.parse(url);

Intent intent = new Intent(Intent.ACTION_VIEW,uri);

startActivity(intent);

}

});

2.自己写线程下载文件

当然,你可能不想把下载文件放到默认路径下,或者想自己定义文件名等等,你都可以自己来写 一个线程来下载文件,实现示例代码如下:

核心代码

我们自己另外写一个下载的线程类:

DownLoadThread.java

/**
 * Created by Jay on 2015/9/14 0014.
 */
public class DownLoadThread implements Runnable {
 
    private String dlUrl;
 
    public DownLoadThread(String dlUrl) {
        this.dlUrl = dlUrl;
    }
 
    @Override
    public void run() {
        Log.e("HEHE", "开始下载~~~~~");
        InputStream in = null;
        FileOutputStream fout = null;
        try {
            URL httpUrl = new URL(dlUrl);
            HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection();
            conn.setDoInput(true);
            conn.setDoOutput(true);
            in = conn.getInputStream();
            File downloadFile, sdFile;
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                Log.e("HEHE","SD卡可写");
                downloadFile = Environment.getExternalStorageDirectory();
                sdFile = new File(downloadFile, "csdn_client.apk");
                fout = new FileOutputStream(sdFile);
            }else{
                Log.e("HEHE","SD卡不存在或者不可读写");
            }
            byte[] buffer = new byte[1024];
            int len;
            while ((len = in.read(buffer)) != -1) {
                fout.write(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (fout != null) {
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        Log.e("HEHE", "下载完毕~~~~");
    }
}

然后MainActivity.java中创建并启动该线程:

wView.setDownloadListener(new DownloadListener(){
               @Override
               public void onDownloadStart(String url, String userAgent, String contentDisposition, 
    String mimetype, long contentLength) {
            Log.e("HEHE","onDownloadStart被调用:下载链接:" + url);
            new Thread(new DownLoadThread(url)).start();
    }
});

Java中定义ColorDrawable:

ColorDrawable drawable = new ColorDrawable(0xffff2200);  
txtShow.setBackground(drawable);  

利用静态方法argb来设置颜色:

Android使用一个int类型的数据表示颜色值,通常是十六进制,即0x开头, 颜色值的定义是由透明度alpha和RGB(红绿蓝)三原色来定义的,以"#"开始,后面依次为:
透明度-红-绿-蓝;eg:#RGB#ARGB #RRGGBB #AARRGGBB
每个要素都由一个字节(8bit)来表示,所以取值范围为0~255,在xml中设置颜色可以忽略透明度, 但是如果你是在Java代码中的话就需要明确指出透明度的值了,省略的话表示完全透明,这个时候 就没有效果了哦~比如:0xFF0000虽然表示红色,但是如果直接这样写,什么的没有,而应该这样写: 0xFFFF0000,记Java代码设置颜色值,需要在前面添加上透明度~ 示例:(参数依次为:透明度,红色值,绿色值,蓝色值) txtShow.setBackgroundColor(Color.argb(0xff,0x00, 0x00, 0x00));

ShapeDrawable

形状的Drawable咯,定义基本的几何图形,如(矩形,圆形,线条等),根元素是<shape../> 节点比较多,相关的节点如下:

·        ① <shape>:

·        ~ visible:设置是否可见

·        ~ shape:形状,可选:rectangle(矩形,包括正方形),oval(椭圆,包括圆),line(线段),ring(环形)

·        ~ innerRadiusRatio:当shape为ring才有效,表示环内半径所占半径的比率,如果设置了innerRadius, 他会被忽略

·        ~ innerRadius:当shape为ring才有效,表示环的内半径的尺寸

·        ~ thicknessRatio:当shape为ring才有效,表环厚度占半径的比率

·        ~ thickness:当shape为ring才有效,表示环的厚度,即外半径与内半径的差

·        ~ useLevel:当shape为ring才有效,表示是否允许根据level来显示环的一部分

·        ②<size>:

·        ~ width:图形形状宽度

·        ~ height:图形形状高度

·        ③<gradient>:后面GradientDrawable再讲~

·        ④<solid>

·        ~ color:背景填充色,设置solid后会覆盖gradient设置的所有效果!!!!!!

·        ⑤<stroke>

·        ~ width:边框的宽度

·        ~ color:边框的颜色

·        ~ dashWidth:边框虚线段的长度

·        ~ dashGap:边框的虚线段的间距

·        ⑥<conner>

·        ~ radius:圆角半径,适用于上下左右四个角

·        ~ topLeftRadius,topRightRadius,BottomLeftRadius,tBottomRightRadius:依次是左上,右上,左下,右下的圆角值,按自己需要设置!

·        ⑦<padding>

·        left,top,right,bottm:依次是左上右下方向上的边距!

GradientDrawable

一个具有渐变区域的Drawable,可以实现线性渐变,发散渐变和平铺渐变效果 核心节点:<gradient/>,有如下可选属性:

·        startColor:渐变的起始颜色

·        centerColor:渐变的中间颜色

·        endColor:渐变的结束颜色

·        type:渐变类型,可选(linear,radial,sweep),线性渐变(可设置渐变角度),发散渐变(中间向四周发散),平铺渐变

·        centerX:渐变中间亚瑟的x坐标,取值范围为:0~1

·        centerY:渐变中间颜色的Y坐标,取值范围为:0~1

·        angle:只有linear类型的渐变才有效,表示渐变角度,必须为45的倍数哦

·        gradientRadius:只有radial和sweep类型的渐变才有效,radial必须设置,表示渐变效果的半径

·        useLevel:判断是否根据level绘制渐变效果

·        先在drawable下创建三个渐变xml文件:

·        (线性渐变)gradient_linear.xml:

·         <?xml version="1.0" encoding="utf-8"?>
·         <shape
·             xmlns:android="http://schemas.android.com/apk/res/android"
·             android:shape="oval" >
·             <gradient
·                 android:angle="90"
·                 android:centerColor="#FFEB82"
·                 android:endColor="#35B2DE"
·                 android:startColor="#DEACAB" />
·          
·             <stroke
·                 android:dashGap="5dip"
·                 android:dashWidth="4dip"
·                 android:width="3dip"
·                 android:color="#fff" />
·         </shape>

·        (发散渐变)gradient_radial.xml:

·         <?xml version="1.0" encoding="utf-8"?>
·         <shape xmlns:android="http://schemas.android.com/apk/res/android"
·             android:innerRadius="0dip"
·             android:shape="ring"
·             android:thickness="70dip"
·             android:useLevel="false" >
·          
·             <gradient
·                 android:centerColor="#FFEB82"
·                 android:endColor="#35B2DE"
·                 android:gradientRadius="70"
·                 android:startColor="#DEACAB"
·                 android:type="radial"
·                 android:useLevel="false" />
·          
·         </shape> 

·        (平铺渐变)gradient_sweep.xml:

·         <?xml version="1.0" encoding="utf-8"?>
·         <shape xmlns:android="http://schemas.android.com/apk/res/android"
·             android:innerRadiusRatio="8"
·             android:shape="ring"
·             android:thicknessRatio="3"
·             android:useLevel="false" >
·          
·             <gradient
·                 android:centerColor="#FFEB82"
·                 android:endColor="#35B2DE"
·                 android:startColor="#DEACAB"
·                 android:type="sweep"
·                 android:useLevel="false" />
·          
·         </shape> 

InsetDrawable

表示把一个Drawable嵌入到另外一个Drawable的内部,并且在内部留一些间距, 类似与Drawable的padding属性,但padding表示的是Drawable的内容与Drawable本身的边距! 而InsetDrawable表示的是两个Drawable与容器之间的边距,当控件需要的背景比实际的边框 小的时候,比较适合使用InsetDrawable,比如使用这个可以解决我们自定义Dialog与屏幕之间 的一个间距问题,相信做过的朋友都知道,即使我们设置了layout_margin的话也是没用的,这个 时候就可以用到这个InsetDrawable了!只需为InsetDrawable设置一个insetXxx设置不同 方向的边距,然后为设置为Dialog的背景即可!

相关属性如下:

·        1.drawable:引用的Drawable,如果为空,必须有一个Drawable类型的子节点!

·        2.visible:设置Drawable是否额空间

·        3.insetLeft,insetRight,insetTop,insetBottm:设置左右上下的边距

①XML中使用:

<?xmlversion="1.0" encoding="utf-8"?>

<inset xmlns:android="http://schemas.android.com/apk/res/android"

android:drawable="@drawable/test1"

android:insetBottom="10dp"

android:insetLeft="10dp"

android:insetRight="10dp"

android:insetTop="10dp" />

在Java代码中使用

InsetDrawable insetDrawable =new InsetDrawable(getResources()

.getDrawable(R.drawable.test1), 10, 10,10, 10);

ClipDrawable

Clip可以译为剪的意思,我们可以把ClipDrawable理解为从位图上剪下一个部分; Android中的进度条就是使用ClipDrawable来实现的,他根据设置level的值来决定剪切 区域的大小,根节点是<clip>

相关属性如下

·        clipOrietntion:设置剪切的方向,可以设置水平和竖直2个方向

·        gravity:从那个位置开始裁剪

·        drawable:引用的drawable资源,为空的话需要有一个Drawable类型的子节点 ps:这个Drawable类型的子节点:就是在<clip里>加上这样的语句: 这样...

使用示例

核心:通过代码修改ClipDrawable的level的值!Level的值是0~10000!

运行效果图

代码实现

①定义一个ClipDrawable的资源xml:

<?xmlversion="1.0" encoding="utf-8"?>

<clipxmlns:android="http://schemas.android.com/apk/res/android"

android:clipOrientation="horizontal"

android:drawable="@mipmap/ic_bg_meizi"

android:gravity="left" />

②在activity_main主布局文件中设置一个ImageView,将src设置为clipDrawable! 记住是src哦,如果你写成了blackground的话可是会报空指针的哦!!!!

<LinearLayoutxmlns: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"

android:orientation="vertical">

<ImageView

android:id="@+id/img_show"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:src="@drawable/clip_bg" />

</LinearLayout>

③MainActivity.java通过setLevel设置截取区域大小:

public class MainActivityextends AppCompatActivity {

private ImageView img_show;

private ClipDrawable cd;

private Handler handler = new Handler() {

@Override

public void handleMessage(Message msg){

if (msg.what == 0x123) {

cd.setLevel(cd.getLevel() +500);

}

}

};

@Override

protected void onCreate(BundlesavedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

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

// 核心实现代码

cd = (ClipDrawable)img_show.getDrawable();

final Timer timer = new Timer();

timer.schedule(new TimerTask() {

@Override

public void run() {

handler.sendEmptyMessage(0x123);

if (cd.getLevel() >= 10000){

timer.cancel();

}

}

}, 0, 300);

}

}

获取Bitmap位图

从资源中获取位图的方式有两种:通过BitmapDrawable或者BitmapFactory,下面演示下: 我们首先得获得这个

BitmapDrawable方法

你可以创建一个构造一个BitmapDrawable对象,比如通过流构建BitmapDrawable:

BitmapDrawable bmpMeizi = newBitmapDrawable(getAssets().open("pic_meizi.jpg"));

Bitmap mBitmap =bmpMeizi.getBitmap();

img_bg.setImageBitmap(mBitmap);

BitmapFactory方法

都是静态方法,直接调,可以通过资源ID、路径、文件、数据流等方式来获取位图!

//通过资源ID

private BitmapgetBitmapFromResource(Resources res, int resId) {

return BitmapFactory.decodeResource(res,resId);

}

//文件

private BitmapgetBitmapFromFile(String pathName) {

return BitmapFactory.decodeFile(pathName);

}

//字节数组

public BitmapBytes2Bimap(byte[] b) {

if (b.length != 0) {

return BitmapFactory.decodeByteArray(b,0, b.length);

} else {

return null;

}

}

//输入流

private BitmapgetBitmapFromStream(InputStream inputStream) {

returnBitmapFactory.decodeStream(inputStream);

}


获取Bitmap的相关信息:

这个,只要我们获取了Bitmap对象,就可以调用相关方法来获取对应的参数了,getByteCount获得大小, getHeight和getWidth这些~这里就不写了,自己查文档!

抠图片上的某一角下来

有时,可能你想把图片上的某一角扣下来,直接通过Bitmap的createBitmap()扣下来即可 参数依次为:处理的bitmap对象,起始x,y坐标,以及截取的宽高

Bitmap bitmap1 = BitmapFactory.decodeResource(getResources(), R.mipmap.pic_meizi);
Bitmap bitmap2 = Bitmap.createBitmap(bitmap1,100,100,200,200);
img_bg = (ImageView) findViewById(R.id.img_bg);
img_bg.setImageBitmap(bitmap2);

对Bitmap进行缩放

我们这里不用Matrix来对Bitmap,而是直接使用Bitmap给我们提供的createScaledBitmap来实现, 参数依次是:处理的bitmap对象,缩放后的宽高,

BlurMaskFilter(模糊效果)

BlurMaskFilter(10f,BlurMaskFilter.Blur.NORMAL);

我们可以控制的就是这两个参数:

第一个参数:指定模糊边缘的半径;

第二个参数:指定模糊的风格,可选值有:

  • BlurMaskFilter.Blur.NORMAL:内外模糊
  • BlurMaskFilter.Blur.OUTER:外部模糊
  • BlurMaskFilter.Blur.INNER:内部模糊
  • BlurMaskFilter.Blur.SOLID:内部加粗,外部模糊

EmbossMaskFilter(浮雕效果)

EmbossMaskFilter(float[]direction, float ambient, float specular, float blurRadius) 参数依次是:

direction:浮点型数组,用于控制x,y,z轴的光源方向

ambient:设置环境光亮度,0到1之间

specular:镜面反射系数

blurRadius:模糊半径

注意事项

在使用MaskFilter的时候要注意,当我们的targetSdkVersion >=14的时候,MaskFilter 就不会起效果了,这是因为Android在API 14以上版本都是默认开启硬件加速的,这样充分 利用GPU的特性,使得绘画更加平滑,但是会多消耗一些内存!好吧,我们把硬件加速关了就好,可以在不同级别下打开或者关闭硬件加速,一般是关闭~

·        Application:在配置文件的application节点添加:android:hardwareAccelerated="true"

·        Activity:在配置文件的activity节点添加android:hardwareAccelerated="false"

·        View:可以获得View对象后调用,或者直接在View的onDraw()方法里设置:view.setLayerType(View.LAYER_TYPE_HARDWARE, null);

AvoidXfermode

嗯,和前面学的MaskFilter的两个子类一样,不支持硬件加速,所以如果是API 14以上的版本, 需要关闭硬件加速才会有效果!怎么关自己看上一节哈~

PS:需要在AndroidManifest.xml中的appliction节点添加关闭硬件加速: android:hardwareAccelerated="false"

我们来看看他给我们提供的构造方法!官方API文档:AvoidXfermode

参数有三个,依次是:

opColor:一个十六进制的带透明度的颜色值,比如0x00C4C4;

tolerance:容差值,如果你学过PS可能用过魔棒工具,就是设置选取颜色值的范围,比如 容差为0,你选的是纯黑的小点,当容差调为40的时候,范围已经扩大到大块黑色这样!如果 还不是很明白,等下我们写写代码就知道了!

mode:AvoidXfermode模式,有两种:TARGETAVOID


模式1:AvoidXfermode.Mode.TARGET

该模式会判断画布上是否有与我们设置颜色值不一样的颜色,如果有的话,会把这些区域 染上一层画笔定义的颜色,其他地方不染色!下面我们写代码演示下,顺便让大家感觉下这个容差值!

模式2:AvoidXfermode.Mode.AVOID

和上面的TARGET模式相反,上面是颜色一样才改变颜色,这里是颜色不一样反而改变颜色, 而容差值同样带来相反的结果,容差值为0时,只有当图片中的像素颜色值与设置的颜色值完全不一样 的时候才会被染色,而当容差值达到最大值255的时候,稍微有一点颜色不一样就会被染色! 我们只需简单的修改上面的例子就可以了,同一是修改下构造AvoidXfermode的内容! 我们改成下面这句:

avoidXfermode = new AvoidXfermode(0XFFD9E5F3,230, AvoidXfermode.Mode.AVOID);

构造方法详解


1)BitmapShader(图像渲染)

BitmapShader(Bitmapbitmap, Shader.TileMode tileX, Shader.TileMode tileY)

使用一张位图作为纹理来对某一区域进行填充,参数依次:

  • bitmap:用来作为填充的位图;
  • tileX:X轴方向上位图的衔接形式;
  • tileY:Y轴方向上位图的衔接形式;

而这个Shader.TileMode有三种:

  • CLAMP就是如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色
  • REPEAT则是平铺形式重复渲染
  • MIRROR则是在横向和纵向上以镜像的方式重复渲染位图。

2)ComposeShader(混合渲染)

ComposeShader(ShadershaderA, Shader shaderB, PorterDuff.Mode mode)

渲染效果的叠加,看到PorterDuff就知道什么了吧?比如将BitmapShader与LinearGradient的混合渲染 效果等。参数依次:

  • shaderA:第一种渲染效果
  • shaderB:第二种渲染效果
  • mode:两种渲染效果的叠加模式

3)LinearGradient(线性渲染)

LinearGradient(floatx0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile);

实现某一区域内颜色的线性渐变效果,参数依次是:

  • x0:渐变的起始点x坐标
  • y0:渐变的起始点y坐标
  • x1:渐变的终点x坐标
  • y1:渐变的终点y坐标
  • colors:渐变的颜色数组
  • positions:颜色数组的相对位置
  • tile:平铺方式

4)RadialGradient(环形渲染)

publicRadialGradient (float x, float y, float radius, int[] colors, float[]positions, Shader.TileMode tile);

实现某一区域内颜色的环形渐变效果,参数依次是:

  • x:环形的圆心x坐标
  • y:环形的圆心y坐标
  • radius:环形的半径
  • colors:环形渐变的颜色数组
  • positions:指定颜色数组的相对位置
  • tile:平铺方式

5)SweepGradient(梯度渲染)

publicSweepGradient (float cx, float cy, int[] colors, float[] positions)

扫描渲染,就是以某个点位中心旋转一周所形成的效果!参数依次是:

  • cx:扫描的中心x坐标
  • cy:扫描的中心y坐标
  • colors:梯度渐变的颜色数组
  • positions:指定颜色数组的相对位置

Matrix中的几个常用的变换方法

·        setTranslate(float dx, float dy):控制Matrix进行平移

·        setRotate(float degrees, float px, float py):旋转,参数依次是:旋转角度,轴心(x,y)

·        setScale(float sx, float sy, float px, float py):缩放, 参数依次是:X,Y轴上的缩放比例;缩放的轴心

·        setSkew(float kx, float ky):倾斜(扭曲),参数依次是:X,Y轴上的缩放比例

translate(平移)

方法translate(float dx, floatdy)

解析:平移,将画布的坐标原点向左右方向移动x,向上下方向移动y,canvas默认位置在(0,0)

参数:dx为水平方向的移动距离,dy为垂直方向的移动距离

使用示例

for(int i=0; i < 5; i++) {

canvas.drawCircle(50, 50, 50, mPaint);

canvas.translate(100, 100);

}

rotate(旋转)

方法rotate(float degrees) / rotate(floatdegrees, float px, float py)

解析:围绕坐标原点旋转degrees度,值为正顺时针

参数:degrees为旋转角度,px和py为指定旋转的中心点坐标(px,py)

使用示例

Rect rect = new Rect(50,0,150,50);

canvas.translate(200, 200);

for(int i = 0; i < 36;i++){

canvas.rotate(10);

canvas.drawRect(rect, mPaint);

}

scale(缩放)

方法scale(float sx, float sy)/ scale(float sx, float sy, float px, float py)

解析:对画布进行缩放

参数:sx为水平方向缩放比例,sy为竖直方向的缩放比例,px和py我也不知道,小数为缩小整数为放大

使用示例

canvas.drawBitmap(bmp,0,0,mPaint);

canvas.scale(0.8f, 0.8f);

canvas.drawBitmap(bmp, 0, 0, mPaint);

canvas.scale(0.8f, 0.8f);

canvas.drawBitmap(bmp,0,0,mPaint);

skew(倾斜)

方法skew(float sx, float sy)

解析:倾斜,也可以译作斜切,扭曲

参数:sx为x轴方向上倾斜的对应角度,sy为y轴方向上倾斜的对应角度,两个值都是tan值哦! 都是tan值!都是tan值!比如要在x轴方向上倾斜60度,那么小数值对应:tan60 = 根号3 = 1.732!

使用示例

canvas.drawBitmap(bmp,0,0,mPaint);

canvas.translate(200, 200);

canvas.skew(0.2f,-0.8f);

canvas.drawBitmap(bmp,0,0,mPaint);

Canvas图层的概念以及save()和restore()详解

我们一般喜欢称呼Canvas为画布,童鞋们一直觉得Canvas就是一张简单的画纸,那么我想问下多层的动画是怎么用canvas来完成的?上面那个translate平移的例子,为什么 drawCircle(50, 50, 50, mPaint); 参考坐标一直是(50,50)那为何会出现这样的效果?有疑惑的童鞋可能是一直将屏幕的概念与Canvas的概念混淆了,下面我们来还原下 调用translate的案发现场:

如图,是画布坐标原点的每次分别在x,y轴上移动100;那么假如我们要重新回到(0,0) 点处绘制新的图形呢?怎么破,translate(-100,-100)的慢慢地平移回去?不会真的这么纠结吧...

好吧,不卖关子了,我们可以在做平移变换之前将当前canvas的状态进行保存,其实Canvas为 我们提供了图层(Layer)的支持,而这些Layer(图层)是按"栈结构"来进行管理的

当我们调用save()方法,会保存当前Canvas的状态然后作为一个Layer(图层),添加到Canvas栈中,另外,这个Layer(图层)不是一个具体的类,就是一个概念性的东西而已!

而当我们调用restore()方法的时候,会恢复之前Canvas的状态,而此时Canvas的图层栈 会弹出栈顶的那个Layer,后继的Layer来到栈顶,此时的Canvas回复到此栈顶时保存的Canvas状态!

简单说就是:save()往栈压入一个Layer,restore()弹出栈顶的一个Layer,这个Layer代表Canvas的状态!也就是说可以save()多次,也可以restore()多次,但是restore的调用次数不能大于save 否则会引发错误!这是网上大部分的说法,不过实际测试中并没有出现这样的问题,即使我restore的 次数多于save,也没有出现错误~目测是系统改了,等下测给大家看~ 来来来,写个例子验证下save和restore的作用!

写个例子

例子代码

canvas.save();  //保存当前canvas的状态

canvas.translate(100, 100);

canvas.drawCircle(50, 50, 50, mPaint);

canvas.restore(); //恢复保存的Canvas的状态

canvas.drawCircle(50, 50, 50, mPaint);

Android 知识点相关推荐

  1. Android知识点汇总以及常见面试题

    Android知识点汇总以及常见面试题 1. 链表和数组的区别 2. List Hash 数组的区别 3. 用过哪些三方SDK 4. Android四大组件 5. 堆和栈的区别 6. Activity ...

  2. Android知识点 200 —— framework/base/cmds 常见的am命令,input,pm命令

    文章原文:http://www.360doc.com/content/11/0510/00/4154133_115595135.shtml 返回知识列表:Android知识点list /framewo ...

  3. Android 知识点——Method put in org.json.JSONObject not mocked

    先扯两句 老头子我没有什么别的优点,就剩下为了作死而作死了.总想玩的新鲜的东西,也就导致了新的问题,这篇存在的原因就是作死的报应啊! 下面给大家展示个神器,叫Android知识点--目录,好了,闲言少 ...

  4. Android知识点 431 -- recovery 强制执行恢复出厂设置(Rescue Party)

    转载原文:https://www.cnblogs.com/codeking100/p/10339258.html 返回知识列表:Android知识点list 1 Incremented rescue ...

  5. Android系统学习(37)---Android知识点及资料汇总

    Android知识点及资料汇总 废话不多说,直接上总结: Android入门方法和经验之谈 如何自学 Android 编程? 如何零基础学习安卓开发? 我是如何自学,资料分享 一张Android学习的 ...

  6. Android知识点大扫描

    Android知识点大扫描 什么是 3G 3G,全称为3rd Generation,中文含义就是指第三代数字通信. 所谓3G,是指将无线通信与国际互联网等多媒体通信结合的新一代移动通信系统. 3G只是 ...

  7. Android知识点 400 -- /data/tombstones

    原文地址 https://www.cnblogs.com/CoderTian/p/5980426.html 返回知识列表 Android知识点list tombstone一般是由Dalvik错误.状态 ...

  8. Android知识点复习(持续更新中)

    1 总览 作为开发者,基础知识非常重要的,尤其一些大厂非常注重基础,基础是一切的根本,在面试时候,如果没有事先准备,很容易被淘汰.笔者整理这套知识点,大大小小的一共几百多条,方便大家查漏补缺. 参考答 ...

  9. Android知识点小结

    Android中有很多零散的知识点,打算将平时开发中所遇到的一些记录下来,既可以加强记忆,也方便其他人查阅,共同进步.这篇博客会定期不断更新. 1.获得布局加载器LayoutInflater的三种方法 ...

  10. Android知识点原理总结

    Activity 4种启动模式 要讲启动模式,先讲讲任务栈Task,它是一种用来放置Activity实例的容器,他是以栈的形式进行盛放,也就是所谓的先进后出,主要有2个基本操作:压栈和出栈,其所存放的 ...

最新文章

  1. Tomcat 与 Resin PK大战
  2. UITextFile
  3. 2022考研 【理工专场讲座(新政策分析、专业分析、复习建议)】
  4. 程序人生:给所有程序员的27个建议,抽空看看吧!
  5. 知乎热议:杨辉团队公开否认抄袭,网友:避重就轻仍谎称「首创」
  6. .net core精彩实例分享 -- 面向对象编程
  7. 用Java实现古典问题兔子的计算
  8. 记录一下不能使用let时如何创建局部变量(使用立即执行函数)
  9. 第三季-第13课-无名管道通讯编程
  10. Ionic系列——Ionic介绍
  11. 软件测试的艺术_读书笔记(一)
  12. element表格标题两行设置办法
  13. 直角坐标和求坐标的转换详解-关于球坐标转换为直角坐标正负号相反问题
  14. 嵌入式系统C语言编程基础
  15. 微软官方工具_微软官方小工具,每天让你眼前一新
  16. 直角三角形面积Java_利用Eclipse编写第一个简单的Java程序,实现如下功能。 键盘输入:直角三角形两直角边a, b,根据勾股定理计算斜边的平方值。并输出。 例如:运行效果如下...
  17. 金泰克/tigo S300 240G SM225K H27QFG8PEM5R 完整开盘教程
  18. 包装类-Wrapper
  19. Nginx安装在服务器
  20. 当前计算机什么专业好就业找工作,计算机哪个专业最好就业

热门文章

  1. 软件测试面试题微信小程序-IT界的驾考宝典
  2. 迎新年[风火之旅]新区新服倾情开启!
  3. 合工大离散数学实验 数据输出
  4. 7nm舱泊一体SoC的新玩家
  5. 模拟投票系统--c语言版
  6. 解决kali安装不了Google输入法的原因
  7. 转:关于垂直网格与CSS基线对其的探讨
  8. 期货从入门到高深之手动交易系列D1课
  9. 您想知道的渗透测试都在这里
  10. Responsive Safety in Reinforcement Learning by PID Lagrangian Methods