Android App开发过程中,很多时候会遇到系统框架中提供的控件无法满足我们产品的设计需求,那么这时候我们可以选择先Google下有没有比较成熟的开源项目可以让我们用,当然现在Github上面的项目非常丰富,能够满足我们绝不多数的开发需求,但是在使用这些炫酷的第三方控件时,我们也要想一想,我们是不是也可以发挥自己的想象力,动手实现自己想要的控件,尽可能掌控实现的细节!
View绘制过程:
onDraw()��: view中onDraw()是个空函数,也就是说具体的视图都要覆写该函数来实现自己的绘制。对于ViewGroup则不需要实现该函数,因为作为容器是“没有内容“的
��onLayout()�: 主要是为viewGroup类型布局子视图用的,在View中这个函数为空函数。
��onMeasure():�� 用于计算视图大小(即长和宽)的方式。
��onTouchEvent�� 定义触屏事件来响应用户操作。
View:
Android所有的控件都是View或者View的子类,它其实表示的就是屏幕上的一块矩形区域,用一个Rect来表示,left,top表示View相对于它的parent View的起点,width,height表示View自己的宽高,通过这4个字段就能确定View在屏幕上的位置,确定位置后就可以开始绘制View的内容了。
获取屏幕宽度:
Android已经提供DisplayMetircs类可以很方便的获取分辨率。
WindowManager wm = (WindowManager) context�.getSystemService(Context.WINDOW_SERVICE);
�DisplayMetrics outMetrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
�screenWidth = outMetrics.widthPixels;
自定义属性:
有时候Android传统的页面布局不足以满足我们的需求,常常需要自己定义view,通常继承View,然后重写构造方法以及onDraw等函数,再具体实现自己定义的复杂view。我们知道在给控件赋属性时,通常使用的是android系统自带的属性,比如 android:layout_height="wrap_content",除此之外,我们亦可以自己定义属性,这样在使用的时候我们就可以使用形
如 myapp:myTextSize="20sp"的方式了
步骤大致如下:
1》在项目文件res/value下面创建一个attr.xml文件,该文件中包含若干个attr集合,例如:
format还可以指定其他的类型比如;
reference 表示引用,参考某一资源ID
�string 表示字符串
�color 表示颜色值
�dimension 表示尺寸值
�boolean 表示布尔值
�integer 表示整型值
float 表示浮点值
�fraction 表示百分数
enum 表示枚举值
可以看到我们的命名空间:xmlns:zhy="http://schemas.android.com/apk/res/com.example.zhy_slidingmenu" 是http://schemas.android.com/apk/res/加上我们的包名;
我们在自定义View 时,一般都会用到 �TypedArray obtainStyledAttributes(�AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes); 对于它的前面2个参数可能大家都知道
defStyleAttr 指向当前theme 某个item 描述的style 该style指定了一些默认值为这个TypedArray�defStyleRes 当defStyleAttr 找不到或者为0, 可以直接指定某个style
TypedArray中的函数是获取自定义属性的
获取px像素值:
ta.getDimensionPixelOffset(attr,def)
Dp转px方法
int size = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, context.getResources().getDisplayMetrics());��这里COMPLEX_UNIT_DIP是单位,20是数值,也就是20dp
代码:
效果图:
适配文件Sliding
package com.example.myslidingmenub;
import android.content.Context;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
public class Slidingitem extends HorizontalScrollView {
//屏幕的宽度
private int screenWidth;
//内容区域的宽度
private int contentWidth;
//菜单的宽度
private int menuWidth;
//菜单一半的宽度
private int halfmenuWidth;
//菜单的右边距
private int rightPading;
private boolean isMesure;
//是否已经打开菜单
private boolean isOpen;
/*
* 当没有使用自定义属性时,调用
* */
public Slidingitem(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics outMetrics=new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(outMetrics);
screenWidth=outMetrics.widthPixels;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(!isMesure){
isMesure=true;//避免mesure方法多次调用
//获取菜单和内容试图
LinearLayout wrapper=(LinearLayout) getChildAt(0);
ViewGroup menu=(ViewGroup) wrapper.getChildAt(0);
ViewGroup content=(ViewGroup) wrapper.getChildAt(1);
//计算右边距100dp转为px
rightPading = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, content.getResources().getDisplayMetrics());
menuWidth = screenWidth-rightPading;
halfmenuWidth=menuWidth/2;
//给菜单和内容区域设置宽度
menu.getLayoutParams().width=menuWidth;
content.getLayoutParams().width=screenWidth;
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
if(changed){
this.scrollTo(menuWidth, 0);
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
switch (ev.getAction()) {
case MotionEvent.ACTION_UP:
//getScrollX()获得划出屏幕左侧的宽度
int scrollx=getScrollX();
if(scrollx>halfmenuWidth){
this.smoothScrollTo(menuWidth, 0);
}else{
this.smoothScrollTo(0, 0);
}
return true;
}
return super.onTouchEvent(ev);
}
public void openDrawer() {
// TODO Auto-generated method stub
if(isOpen){
return;
}
this.smoothScrollTo(0, 0);
isOpen=true;
}
public void close() {
// TODO Auto-generated method stub
if(isOpen){
this.smoothScrollTo(menuWidth, 0);
isOpen=false;
}
}
public void toggle(){
if(isOpen){
close();
}else{
openDrawer();
}
}
}