在Android的开发中,很多时候系统提供的View已经不能够满足我们的要求,自定义View的需求自然而然就出来了。
实现自定义的View,其实就是去扩展View类,重写其某些方法函数,把原来由Android Framework 实现的东西,让我们自己来实现自己想要的某些效果。
其本质上就是封装了一些自己想要的效果,并使之能够被Framework识别,跟普通的系统的控件一样,可以重复利用。
下面就拿一个例子开始吧,先上一张效果图:
在这里,有六个正方形的View,每一个View的背景颜色都不一样,图片也不一样,旋转的角度也不一样,其实这三个都是自定义的属性来的。
1. 自定义属性。
在 res/values/文件夹中创建一个 attrs.xml 文件,定义我们的属性。
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomRotateView">
<attr name="drawable" format="reference"/>
<attr name="degree" format="float" />
<attr name="bgcolor" format="color" />
</declare-styleable>
</resources>
如上 name 是属性的名字, format 是属性对应值的类型, 其中reference 表明这个值是参考其他的资源文件,在xml 中使用这个属性的形式就是:"@drawable/photo1"
2. 定义好自定义属性之后,开始创建自定义的View。
很显然,一切得从继承View开始,代码如下:
package com.example.apidemostudy;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class CustomRotateView extends View {
private final static String tag = "com.example.apidemostudy.CustomRotateView";
private Bitmap mBitmap; // The bitmap to be drawn
private int bgColor; // the BackgroundColor
private float degree; // the angels to rotate
private Matrix matrix; // the matrix to transform
private int mWidth = 240, mHeight = 240; // The RotateImageView's height and
// width
private int mPivotX, mPivotY; // the pivot point to rotate by
private int mTranslateX, mTranslateY; // the translation to center in
// current view
/**
* Constructor, called when inflate the xml definition
*
* @param context
* @param attrs
*/
public CustomRotateView(Context context, AttributeSet attrs) {
super(context, attrs);
Log.v(tag, "CustomRotateView Initializing");
TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.CustomRotateView);
Drawable drawable = typedArray.getDrawable(R.styleable.CustomRotateView_drawable);
degree = typedArray.getFloat(R.styleable.CustomRotateView_degree, 0);
bgColor = typedArray.getColor(R.styleable.CustomRotateView_bgcolor,Color.YELLOW);
typedArray.recycle();
// Change to the drawable to bitmap and zoom it until the diagnoal line
// is shorter than the required width and height
mBitmap = zoomBitmap(drawableToBitmap(drawable), mWidth, mHeight);
// Rotate axis, the central point of the bitmap
mPivotX = mBitmap.getWidth() / 2;
mPivotY = mBitmap.getHeight() / 2;
// translation, translate the bitmap to the center of this view
mTranslateX = mWidth / 2 - mPivotX;
mTranslateY = mHeight / 2 - mPivotY;
matrix = new Matrix();
}
/**
* Measure the current view set it to the fixed width and height. it's ok to
* use the widthMeasureSpec and heightMeasureSpec if its size is decided by
* its parent.
*/
@Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(mWidth, mHeight);
}
/**
* Draw the current view, 1) draw background color by bgColor 2) rotate the
* bitmap 3) move the bitmap to center
*/
@Override
public void onDraw(Canvas canvas) {
canvas.drawColor(bgColor);
matrix.reset();
matrix.postRotate(degree, mPivotX, mPivotY);
matrix.postTranslate(mTranslateX, mTranslateY);
canvas.drawBitmap(mBitmap, matrix, null);
}
/**
* Zoom the bitmap to make sure it will be always displayed inside the view
*
* @param oldBitmap
* @return
*/
private Bitmap zoomBitmap(Bitmap oldBitmap, int reqWidth, int reqHeight) {
Matrix pMatrix = new Matrix();
int oldWidth = oldBitmap.getWidth();
int oldHeight = oldBitmap.getHeight();
double diagnoal = Math.sqrt(oldWidth * oldWidth + oldHeight * oldHeight);
float scaleX = (float) (reqWidth / diagnoal);
float scaleY = (float) (reqHeight / diagnoal);
float scale = scaleX < scaleY ? scaleX : scaleY;
pMatrix.postScale(scale, scale);
Bitmap bitmap = Bitmap.createBitmap(oldBitmap, 0, 0, oldWidth,
oldHeight, pMatrix, true);
return bitmap;
}
/**
* Change the drawable to Bitmap
*
* @param drawable
* @return
*/
private Bitmap drawableToBitmap(Drawable drawable) {
int w = drawable.getIntrinsicWidth();
int h = drawable.getIntrinsicHeight();
Bitmap.Config config = drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888
: Bitmap.Config.RGB_565;
Bitmap bitmap = Bitmap.createBitmap(w, h, config);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, w, h);
drawable.draw(canvas);
return bitmap;
}
}
自定义的View, 有以下几个步骤:
1)构造函数
CustomRotateView(Context context, AttributeSet attrs),从xml 中解析的view, 一定要有这个构造函数,包含有attributeSet 参数。
在构造函数中,做了几件事情:
第一,利用 TypedArray 获取自定义的属性,并将其中的drawable 转化为bitmap, 将其缩小到其对角线比当前View的宽跟高都要小,这样其在旋转角度的时候,就不会有些尖尖角角跑出这个View了。
第二,设定旋转的中心点和图片的偏移量,其实就是绕着图片中心转,然后将图片移到当前View的中心。
2)OnMeasure 函数
View 在被new 出来之后,并添加到布局去的时候,到其显示在窗口,让眼睛可以看到的过程中,其实是经过了三个步骤的,measure, layout 和 draw, 对于叶子View来说,不需要去关心layout, 因为这是由其父窗口来决定的,但是Measure过程和Draw过程,却是需要View也参与在其中的,学习Android 不久,详细的过程我目前没法很好地表达出来,各位可以自己在csdn 中找一下。
OnMeasure函数会决定当前的宽高是怎么样的,在这个例子中,简单地将当前的View 的宽高,设定为240, 240,一个正方形。
3) OnDraw 函数
当测量完当前的View 大小的时候,就是画内容了。在这里只是3.1)设置背景颜色 3.2)简单地利用matrix 作一个旋转和偏移。
3. 在布局文件中用上我们自定义的View
layout/custom_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.apidemostudy"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView1"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
custom:bgcolor="#000000"
custom:degree="0"
custom:drawable="@drawable/photo1" />
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView2"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentLeft="true"
android:layout_below="@+id/rotateView1"
custom:bgcolor="#FF0000"
custom:degree="45"
custom:drawable="@drawable/photo2" />
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView3"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentLeft="true"
android:layout_below="@+id/rotateView2"
custom:bgcolor="#FFFF00"
custom:degree="30"
custom:drawable="@drawable/photo3" />
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView4"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
custom:bgcolor="#CCCCCC"
custom:degree="60"
custom:drawable="@drawable/photo4" />
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView5"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentRight="true"
android:layout_below="@+id/rotateView4"
custom:bgcolor="#777777"
custom:degree="-30"
custom:drawable="@drawable/photo5" />
<com.example.apidemostudy.CustomRotateView
android:id="@+id/rotateView6"
android:layout_width="240dip"
android:layout_height="300dip"
android:layout_alignParentRight="true"
android:layout_below="@+id/rotateView5"
custom:bgcolor="#123456"
custom:degree="-60"
custom:drawable="@drawable/photo6" />
</RelativeLayout>
首先要定义一个自定义的命名空间,跟系统 的命名空间区分开来,如:
xmlns:custom="http://schemas.android.com/apk/res/com.example.apidemostudy"
将上面的“Android” 字样替换成包名。
然后就是用上我们自定义的View了,用法很简单,就是直接拿着绝对路径放上去。
<com.example.apidemostudy.CustomRotateView
最后就是设置我们自定义的属性,
custom:bgcolor="#000000"
custom:degree="0"
custom:drawable="@drawable/photo1"
背景颜色,旋转角度 ,展示的图片。
4. 最后在Activity 中放上我们的布局文件,如下:
public class CustomActivity extends Activity{
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_layout);
}
}
嗯,自定义View 就是这样的,下一次写一个自定义的ViewGroup.
分享到:
相关推荐
android demo,自定义控件view,点击该自定义view,onclick随机生成数字
Android自定义View之进度条Demo,Android自定义View之进度条Demo
android项目下对图片高斯模糊毛玻璃,自定义view,模糊程度可控制,高斯模糊毛玻璃,自定义view,模糊程度可控制
android使用自定义view和自定义button实现的小demo,可以实现button的点击变换背景等功能
android demo,自定义view,该view显示正在加载的文字,动态转圈的图标
在我们从Android小学生 进阶到 Android中学生的路上,肯定需要经历 自定义View。 大神已经给出了,最精简的Demo,我这里 顺水推舟,把一些基础知识 标记在代码之中,各位可以一边看源码 一边学基础。 觉得文章有用,...
Andorid自定义View学习Demo,包含常见的所有知识点,Layout, Paint,Xfermode,mask filter, canvas, reveal, search,path,path measure, svg, plus等
android自定义控件学习demo,自定义继承控件,自定义自绘View控件,自定义组合控件
Android 自定义view,自定义属性demo
自定义View Demo,用最简单的例子解释自绘、组合、继承三种方式实现的自定义控件,代码注释完整!
见博客:http://blog.csdn.net/mybeta/article/details/39962235
Android自定义View的学习使用Demo。根据guolin,hongyang等大神的blog的指导,写了几个简单的自定义View的Demo。准备作为下一篇blog的资源。
初学android ,自定义view手写小Demo,可供参考!
自定义View绘制一个太极旋转图片demo
自己实现的一个抢红包demo,自定义view实现了移动、旋转、透明度3种渐变效果,设置活动时效为1分钟,会越来越快,我封装在一个redbag类,中具体代码自己看吧 [注意:本资源来自网络,如有侵权,请联系我删除,谢谢。...
http://blog.csdn.net/zxw136511485/article/details/51914916
很好用的一款自定义android自定义FrameLayout布局Demo,可延伸到自定义View,有需要的小伙伴可以下载试下!
这是一个通过xml文件自定义view的一个Demo
android 自定义View 实例,不熟悉的朋友,可以看看这个demo,可以改写成任何你想要的样子。
Android自定义View-点赞动画效果View-Demo,点赞后,会有动画效果,绘制箭头。