androidattributeset
‘壹’ android listView 显示不全,为什么
重写LinearLayout显示列表
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
/***
*
* @author FreePC
*
*/
public class LinearLayoutForListView extends LinearLayout
{
private BaseAdapter adapter;
private OnItemClickListener onItemClickListener;
/**
* 通过 java代码 实例化
* @param context
*/
public LinearLayoutForListView(Context context)
{
super(context);
//设置LinearLayoutForListView为垂直布局,否者默认为水平布局,容易疏忽导致子项显示不全
LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL);
}
/**
* 此构造函数可以允许我们通过 XML的方式注册 控件
* @param context
* @param attrs
*/
public LinearLayoutForListView(Context context, AttributeSet attrs)
{
super(context, attrs);
LinearLayoutForListView.this.setOrientation(LinearLayout.VERTICAL);
}
/**
* 设置适配器
*
* @param adpater
*/
public void setAdapter(BaseAdapter adpater)
{
this.adapter = adpater;
bindLinearLayout();
}
/**
* 获取适配器Adapter
*
* @return adapter
*/
public BaseAdapter getAdpater()
{
return adapter;
}
/**
* 绑定布局:将每个子项的视图view添加进此线性布局LinearLayout中
*/
public void bindLinearLayout()
{
int count = adapter.getCount();
for (int i = 0; i < count; i++)
{
View v = adapter.getView(i, null, null);
if (i != count - 1)
{ //添加每项item之间的分割线
v = addLine(v);
}
addView(v, i);
}
setItemClickListener();
Log.v("countTAG", "" + count);
}
/**
* 添加每项item之间的分割线
*
* @param view
* @return
*/
public View addLine(View view)
{
//分割线view
View lineView = new View(view.getContext());
// 将数据从dip(即dp)转换到px,第一参数为数据原单位(此为DIP),第二参数为要转换的数据值
float fPx = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
(float) 0.5, view.getResources().getDisplayMetrics());
int iPx = Math.round(fPx);
LayoutParams layoutParams = new LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT, iPx);
lineView.setLayoutParams(layoutParams);
lineView.setBackgroundColor(view.getSolidColor());
LinearLayout ly = new LinearLayout(view.getContext());
ly.setOrientation(LinearLayout.VERTICAL);
ly.addView(view);
ly.addView(lineView);
return ly;
}
/**
* 设置点击子项事件监听对象
* @param onItemClickListener
*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener)
{
this.onItemClickListener = onItemClickListener;
setItemClickListener();
}
/**
* 获取点击子项事件监听对象
* @return
*/
public OnItemClickListener getOnItemClickListener()
{
return onItemClickListen
‘贰’ android 如何让自定VIEW的显示超出view的定义大小
在onTouchEvent里面能获得当前点击位置的坐标,根据位置的变化,以原点为基础,通过scrollBy来设置view的显示位置。
自定义Layout实现放入其中的组件可以动态改变位置和大小。
自定义CustomLayout.java
package com.wxq.layout;
import android.content.Context;
import android.util.AttributeSet;
import android.view.ViewGroup;
//import android.widget.AbsoluteLayout;
public class CustomLayout extends ViewGroup {
public CustomLayout(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public CustomLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
3.其中只有自己的布局,其他的View要自己手动添加。
主程序:
TextView mTextView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater inflater = getLayoutInflater();
LinearLayout linearLayout = (LinearLayout) inflater.inflate(R.layout.main, null);
mTextView = new TextView(this);
mTextView.setText("wxq say hello!");
mTextView.setTextColor(Color.WHITE);
mTextView.setBackgroundColor(Color.RED);
ViewGroup.LayoutParams layoutParams = new ViewGroup.LayoutParams(100, 100);
CustomLayout cLayout = (CustomLayout) linearLayout.findViewById(R.id.cLayout);
cLayout.setBackgroundColor(Color.BLUE);
cLayout.addView(mTextView,layoutParams);
mTextView.layout(20, 20, 150+20, 150+20);
Log.d("wxq", "mTextView = " +mTextView + ",and parent is:"+mTextView.getParent());
mTextView.post(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
Log.d("wxq", "textW = "+mTextView.getMeasuredWidth()+ ",H = "+mTextView.getMeasuredHeight());
}
});
setContentView(linearLayout);
}
实现的效果如下:
‘叁’ 从源码中浅析Android中怎么利用attrs和styles定义控件
1.attrs.xml:
我们知道Android的源码中有attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性
你可以找到attrs.xml这个文件,打开它,全选,右键->Show In->OutLine。可以看到整个文件的解构
我们大概可以看出里面是Android中的各种属性的声明,比如textStyle这个属性是这样定义的:
Java代码
<!-- Default text typeface style. -->
<attr name="textStyle">
<flag name="normal" value="0" />
<flag name="bold" value="1" />
<flag name="italic" value="2" />
</attr>
那么现在你知道,我们在写android:textStyle的时候为什么会出现normal,bold和italic这3个东西了吧,就是定义在这个地方。
再看看textColor:
Java代码
<!-- Color of text (usually same as colorForeground). -->
<attr name="textColor" format="reference|color" />
format的意思是说:这个textColor可以以两种方式设置,要么是关联一个值,要么是直接设置一个颜色的RGB值,这个不难理解,因为我们可以平时也这样做过。
也就是说我们平时在布局文件中所使用的各类控件的属性都定义在这里面,那么这个文件,除了定义这些属性外还定义了各种具体的组件,比如TextView,Button,SeekBar等所具有的各种特有的属性
比如SeekBar:
Java代码
<declare-styleable name="SeekBar">
<!-- Draws the thumb on a seekbar. -->
<attr name="thumb" format="reference" />
<!-- An offset for the thumb that allows it to extend out of the range of the track. -->
<attr name="thumbOffset" format="dimension" />
</declare-styleable>
也许你会问SeekBar的background,等属性怎么没有看到?这是因为Android中几乎所有的组件都是从View中继承下来的,SeekBar自然也不例外,而background这个属性几乎每个控件都有,因此被定义到了View中,你可以在declare-styleable:View中找到它。
总结下,也就是说attrs.xml这个文件定义了布局文件中的各种属性attr:***,以及每种控件特有的属性declare-styleable:***
2.styles.xml:
刚才的attrs.xml定义的是组件的属性,现在要说的style则是针对这些属性所设置的值,一些默认的值。
这个是SeekBar的样式,我们可以看到,这里面设置了一个SeekBar的默认的样式,即为attrs.xml文件中的各种属性设置初始值
Java代码
<style name="Widget.SeekBar">
<item name="android:indeterminateOnly">false</item>
<item name="android:progressDrawable">@android:drawable/progress_horizontal</item>
<item name="android:indeterminateDrawable">@android:drawable/progress_horizontal</item>
<item name="android:minHeight">20dip</item>
<item name="android:maxHeight">20dip</item>
<item name="android:thumb">@android:drawable/seek_thumb</item>
<item name="android:thumbOffset">8dip</item>
<item name="android:focusable">true</item>
</style>
这个是Button的样式:
Java代码
<style name="Widget.Button">
<item name="android:background">@android:drawable/btn_default</item>
<item name="android:focusable">true</item>
<item name="android:clickable">true</item>
<item name="android:textAppearance">?android:attr/textAppearanceSmallInverse</item>
<item name="android:textColor">@android:color/primary_text_light</item>
<item name="android:gravity">center_vertical|center_horizontal</item>
</style>
有了属性和值,但是这些东西是如何关联到一起的呢?它们如何被android的framework层所识别呢?
3.组件的源码
我们看下TextView的源码:
Java代码
public TextView(Context context) {
this(context, null);
}//这个构造器用来给用户调用,比如new TextView(this);
public TextView(Context context,
AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.textViewStyle);
}
public TextView(Context context,
AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);//为用户自定义的TextView设置默认的style
mText = "";
//设置画笔
mTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.density = getResources().getDisplayMetrics().density;
mTextPaint.setCompatibilityScaling(
getResources().getCompatibilityInfo().applicationScale);
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setCompatibilityScaling(
getResources().getCompatibilityInfo().applicationScale);
mMovement = getDefaultMovementMethod();
mTransformation = null;
//attrs中包含了这个TextView控件在布局文件中定义的属性,比如android:background,android:layout_width等
//com.android.internal.R.styleable.TextView中包含了TextView中的针对attrs中的属性的默认的值
//也就是说这个地方能够将布局文件中设置的属性获取出来,保存到一个TypeArray中,为这个控件初始化各个属性
TypedArray a =
context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
int textColorHighlight = 0;
ColorStateList textColor = null;
ColorStateList textColorHint = null;
ColorStateList textColorLink = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;
/*
* Look the appearance up without checking first if it exists because
* almost every TextView has one and it greatly simplifies the logic
* to be able to parse the appearance first and then let specific tags
* for this View override it.
*/
TypedArray appearance = null;
//TextView_textAppearance不太了解为什么要这样做?难道是为了设置TextView的一些默认的属性?
int ap = a.getResourceId(com.android.internal.R.styleable.TextView_textAppearance, -1);
if (ap != -1) {
appearance = context.obtainStyledAttributes(ap,
com.android.internal.R.styleable.
TextAppearance);
}
if (appearance != null) {
int n = appearance.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = appearance.getIndex(i);
switch (attr) {
case com.android.internal.R.styleable.TextAppearance_textColorHighlight:
textColorHighlight = appearance.getColor(attr, textColorHighlight);
break;
case com.android.internal.R.styleable.TextAppearance_textColor:
textColor = appearance.getColorStateList(attr);
break;
case com.android.internal.R.styleable.TextAppearance_textColorHint:
textColorHint = appearance.getColorStateList(attr);
break;
case com.android.internal.R.styleable.TextAppearance_textColorLink:
textColorLink = appearance.getColorStateList(attr);
break;
case com.android.internal.R.styleable.TextAppearance_textSize:
textSize = appearance.getDimensionPixelSize(attr, textSize);
break;
case com.android.internal.R.styleable.TextAppearance_typeface:
typefaceIndex = appearance.getInt(attr, -1);
break;
case com.android.internal.R.styleable.TextAppearance_textStyle:
styleIndex = appearance.getInt(attr, -1);
break;
}
}
appearance.recycle();
}
//各类属性
boolean editable = getDefaultEditable();
CharSequence inputMethod = null;
int numeric = 0;
CharSequence digits = null;
boolean phone = false;
boolean autotext = false;
int autocap = -1;
int buffertype = 0;
boolean selectallonfocus = false;
Drawable drawableLeft = null, drawableTop = null, drawableRight = null,
drawableBottom = null;
int drawablePadding = 0;
int ellipsize = -1;
boolean singleLine = false;
int maxlength = -1;
CharSequence text = "";
CharSequence hint = null;
int shadowcolor = 0;
float dx = 0, dy = 0, r = 0;
boolean password = false;
int inputType = EditorInfo.TYPE_NULL;
int n = a.getIndexCount();
for (int i = 0; i < n; i++) {
int attr = a.getIndex(i);
//通过switch语句将用户设置的,以及默认的属性读取出来并初始化
switch (attr) {
case com.android.internal.R.styleable.TextView_editable:
editable = a.getBoolean(attr, editable);
break;
case com.android.internal.R.styleable.TextView_inputMethod:
inputMethod = a.getText(attr);
break;
case com.android.internal.R.styleable.TextView_numeric:
numeric = a.getInt(attr, numeric);
break;
//更多的case语句...
case com.android.internal.R.styleable.TextView_textSize:
textSize = a.getDimensionPixelSize(attr, textSize);//设置当前用户所设置的字体大小
break;
case com.android.internal.R.styleable.TextView_typeface:
typefaceIndex = a.getInt(attr, typefaceIndex);
break;
//更多的case语句...
}
通过上面的代码大概可以知道,每个组件基本都有3个构造器,其中只传递一个Context上下文的那个构造器一般用来在java代码中实例化使用。
比如你可以
Java代码
TextView tv = new TextView(context);
来实例化一个组件。
最终调用的是第3个构造器
Java代码
public TextView(Context context,
AttributeSet attrs,
int defStyle)
在这个构造器中为你设置了默认的属性attrs和值styles。关键不在这里,而是后面通过使用下面的代码
Java代码
TypedArray a =
context.obtainStyledAttributes(
attrs, com.android.internal.R.styleable.TextView, defStyle, 0);
来将属性和值获取出来,放到一个TypeArray中,然后再利用一个switch语句将里面的值取出来。再利用这些值来初始化各个属性。这个View最终利用这些属性将这个控件绘制出来。
如果你在布局文件中定义的一个View的话,那么你定义的值,会被传递给构造器中的attrs和styles。也是利用同样的方式来获取出你定义的值,并根据你定义的值来绘制你想要的控件。
再比如其实Button和EditText都是继承自TextView。看上去两个控件似乎差异很大,其实不然。Button的源码其实相比TextView变化的只是style而已:
‘肆’ android中常用的资源有哪些
Android 资源类型
1.字符串资源
>>1.普通字符串
>>2.字符串数组
复制代码
<resources>
<string-array name="planets_array">
<item>aaa</item>
<item>bbb</item>
</string-array>
</resources>
复制代码
获取方式:getResources().getStringArray(R.array.planets_array)
>>3.复数字符串资源
某些自然语言中,不同的数字在使用方法上会有所不同,比如one book,two books。当数量大于1时,会使用不同的名词或其它复数形式;
复制代码
<resources>
<plurals name="numberOfp">
<item quantity="one">one person</item>
<item quantity="other">more persons</item>
</plurals>
</resources>
复制代码
quantity属性的值除了one和other外,还可以是zero,two,few,many;
引用复数字符串:
// 引用数字为1的复数字符串
getResources().getQuantityString(R.pluarlas.numberOfp,1);
// 引用数字为其它值的复数字符串
getResources().getQuantityString(R.pluarlas.numberOfp,10,10);
>>4.占位符格式化字符串
常用的格式化字符串三种方法:
>>1.在字符串中使用引号
字符串中的值虽然可以随意指定,但是当遇到特殊符号时(双引号,单引号)就需要采取特殊的方法来处理这些符号。
如果是单引号(')可以使用转义符(\)或用双引号(")将整个字符串括起来,如果是双引号,可以在双引号前使用转义符(\)。
<resources>
<string name="str1">"This'll work"</string> This'll work
<string name="str2">This\'ll work</string> This'll work
<string name="str3">\"apple\"</string> "apple"
</resources>
>>2.用占位符格式化字符串
使用String.format(String,Object...)方法可以格式化带占位符的字符串,只需要在字符串中插入占位符,就可以使用String.format方法格式化字符串资源,format方法要求的占位符用%1,%,...,%n,其实第n个占位符与format方法的n+1个参数值对应;
<resources>
<!-- $s表示该占位符被字符串替换,$d表示该占位符被整数替换 -->
<string name="str1">hello,%1$s!You have %2$d new message</string>
</resources>
String str1 =String.format(getResources().getString(R.string.str1), "ly", 17);
>>3.使用HTML标签格式化字符串资源
字符串资源支持一些HTML标签,因此可以直接在字符串资源中使用这些HTML标签格式化字符串
字符串资源支持如下的HTML标签
<b>粗体字
<i>斜体定
<u>带下划线的字
有时需要同时使用HTML标签和占位符格式化字符串,如果使用String.format方法格式化字符串,会忽略字符串中的所有HTML标签。为了使format方法可以格式化带
HTML标签的确字符,需要使用Html.formHTML方法处理字符串;
<resources>
<string name="hello_world">Welcome to <b>android</b></string>
<string name="str2">Hello,%1$s! You have <b> %2d new messages </b></string> <!--同时包含占位符和html标签的字符串-->
</resources>
由于需要使用Html.formHTML方法处理字符串,因此HTML标签中的 "<" 需要使用 "<" 表示 ">" 并不需要处理
获取字符串:
String text = String.format(getResources().getString(R.string.str2), "ly", 10);
CharSequence styledText = Html.fromHtml(text);
// 如果format的某个参数包含HTML的特殊字符,如"<","&",可以使用如下方式读取字符串的值;
String escapedUsername = TextUtils.htmlEncode("");
String text1 = String.format(getResources().getString(R.string.str2), "ly", 20);
2.Layout资源
1、如果根节点是View,除了<requestFocus>标签外,不能添加任何子标签,<requestFocus>可能被添加到布局文件的任何View中,表示该标签对应的控件在显示时处于焦点状态,整个布局文件只能有一个<requestFocus>标签
2、根节点是ViewGroup,常用的布局都是ViewGroup的子类
3、重用布局文件
如果想重用某个布局文件,可以使用<include>标签
<include layout="@layout/xx_layout" />
如果想让一个布局文件被另一个布局文件引用(使用<include>标签),可以使用<merge>作为被引用布局文件的根节点,由于<merge>并不会生成任何标签(在大量引用布局文件时不至于生成大量无用的标签),但是xml文件必须要有一个根节点,因此<merge>所起的作用就是作为xml文件的根节点,以使xml文件在编译时不至于出错,可以把<merge>当成<FrameLayout>使用;
3.图像资源
在图像资源中可以存储图像文件,还可以使用xml格式的图像资源来控件图像的状态和行为;
>>1.普通图像资源
Drawable da = getResources().getDrawable(R.drawable.xxx);
>>2.xml图像资源
xml图像资源其实就是在drawable目录中指定的xml文件,此种方式可以额外指定图像的某些属性,如图像拉动、排列方式;
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher"
android:tileMode="repeat" >
</bitmap>
>>3.Nine-Patch图像资源
Nine-Patch图像资源文件必须以9.png作为文件扩展名,如abc.9.png
该图像资源的主要作用是:防止图像的某一部分被拉伸;确定将图像作为背景图的控件中内容显示的位置;
Android SDK本身提供了一个Draw 9-patch的工具,启动<sdk目录>\tools\draw9patch.bat命令启动该工具;
可以通过此工具在png图的四周绘制1个像素粗的直线,上边缘和左边缘的直线分别表示图像在水平和垂直方向可位值的范围。如果水平或垂直方向的某个区域不需要拉伸,则可不绘制相应的直线;右边缘和下边缘的直线分别表示图像所在控件中内容的显示范围,内容只在右边缘和下边缘绘制直线的区域显示,表示内容显示范围和拉伸范围的两给直线有一个重要区别就是表示内容显示范围的直线中间不能断开,而表示拉伸范围的直线中间可以断开;
Nine-Patch图像资源与普通图像资源引用方法相同,在引用时只写文件名,活力.9.png;
>>4.XML Nine-Patch图像资源
Nine-Patch图像资源也有与其对应的xml图像资源,使用<nine-patch>标签来引用Nine-Patch格式的图像,有一个设置抖动的android:dither属性;
>>5.图层资源
图层资源类似于<FrameLayout>不同的是<FrameLayout>标签中可以包含任意的控件,而图层资源每一层都只有是图像,定义图层资源必须使用<layer-list>作为资源文件的根节点,<layer-list>标签中包含多个<item>标签,每一个标签表示一个图像,最后一个<item>标签显示在最顶层;
默认情况下,图像会尽量充满显示图像的范围,图像可能会有拉伸,为了避免图像拉伸,可以在<item>标签中使用<bitmap>标签引用图像;
复制代码
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:bottom="10dip" 底端偏移的像素
android:left="10dip" 左侧偏移的像素
android:right="10dip" ...
android:top="10dip"> ...
<bitmap
android:gravity="center"
android:src="@drawable/hell" />
</item>
</layer-list>
复制代码
某些情况下,可以使用图层来代替<FrameLayout>
>>6.图像状态资源,处理控件不同状态下的显示状态
复制代码
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/bm" android:state_focused="true"></item>
<item android:drawable="@drawable/bm" android:state_pressed="true"></item>
<item android:drawable="@drawable/bm"></item>
</selector>
// android:state_focused/pressed设置为true表示当前item的drawable属性为获取焦点和按下时的drawable样式
复制代码
>>7.图像级别(Level)资源
图像资源状态只能指定几种有限的状态,可以通过图像级别指定更多的状态;图像级别是一个整数的区间,可以通过ImageView.setImageLevel或Drawable.setLevel方法切换不同状态的图像;图像级别资源是xml文件,必须以<level-list>为根节点,每一个item表示一个级别区间,下面是一个xml文件;通过ImageView.setImageLevel(level),根据level所在的区间设定显示的图像资源,如果level不在任一区间内则清空ImageView当前图像;
<level-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:maxLevel="2" android:minLevel="0" android:drawable="@drawable/hell" />
<item android:maxLevel="4" android:minLevel="3" android:drawable="@drawable/hell" />
</level-list>
>>8.淡入淡出(Cross-fade)资源
也是切换两个图像(不支持多于两个图像的切换),并且使这两个图像以淡入淡出效果进行切换,如电灯在开关时逐渐变亮或逐渐变暗;
<transition xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:drawable="@drawable/hell"/>
<item android:drawable="@drawable/hell"/>
</transition>
TransitionDrawable da = ...;
// 从第一张图片切换到第二张图片,时间效果为1秒
da.startTransition(1000);
// 从第二张图片切换到第一张图片,时间效果为1秒
da.reverseTransition(1000);
>>9.嵌入(insert)图像资源
使用场景:要显示的图像要求要小于装载图像的View(图小于View区域),也是通过xml资源定义,只有一个节点inset。
<inset xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/hell"
android:insetLeft="10dip" > <!--图像距离左边的距离,延伸-->上/下/右的距离-->
</inset>
>>10.剪切(Clip)图像资源,使用剪切图像资源可以只显示图像的一部分,如可以通过此来制作进度条;
<clip xmlns:android="http://schemas.android.com/apk/res/android"
android:clipOrientation="horizontal" // 指定截取的方向
android:drawable="@drawable/hell" // 指定要截取的图像
android:gravity="left" > // 指定截取的方式,在此为从左侧开始截取
</clip>
ClipDrawable cd = ...;
cd.setLevel(1000);
上面ClipDrawable.setLevel(level)设置截取的图像宽度,ClipDrawable预设了最大值10000(表示不进行截取),最小值为0(表示不显示);
>>11. 比例(Scale)图像资源
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:drawable="@drawable/hell"
android:scaleGravity="center" // 设置图像显示的位置
android:scaleHeight="70%" // 设置图像显示的高度
android:scaleWidth="80%" > // 设置图像显示的宽度
</scale>
>>12.形状资源
复制代码
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" > shape可以指定就矩形,oval(椭圆),line(直线),ring(圆)
<corners> 定义圆角
</corners>
<gradient
android:angle="45"
android:startColor="#000000"
android:endColor="#FFFFFF" > 定义颜色渐变,从左下角到或上角
</gradient>
<padding> 定义控件内容到边框的距离
</padding>
<stroke> 定义边线
</stroke>
<solid> 定义填充
</solid>
<size> 定义大小
</size>
</shape>
复制代码
13.菜单资源
菜单不仅可以在onCreateContextMenu或onCreateOptionsMenu方法中通过代码创建,还可以在res/menu目录中建立相应的菜单资源文件,并在上面两个方法中加载菜单资源;
菜单资源文件必须以<menu>标签作为根节点,每一个菜单项用一个<item>表示,如果要定义子菜单,可以在<item>标签中包含<menu>标签;如果想将多个菜单项划为一组,可以使用<group>包含多个<item>标签;
复制代码
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return true;
}
复制代码
查看MenuInflater.inflate(int,Menu)
复制代码
/**
* Inflate a menu hierarchy from the specified XML resource.
*
* @param menuRes Resource ID for an XML layout resource to load (e.g., <code>R.menu.main_activity</code>)
* @param menu The Menu to inflate into. The items and submenus will be added to this Menu.
*/
public void inflate(int menuRes, Menu menu) {
XmlResourceParser parser = null;
try {
parser = mContext.getResources().getLayout(menuRes);
AttributeSet attrs = Xml.asAttributeSet(parser);
parseMenu(parser, attrs, menu);
} catch ...finally {
if (parser != null) parser.close();
}
}
复制代码
14.样式与主题(style/theme)
>>1.样式style
android中样式和css中样式作用是一样的,都是用于为界面元素定义显示风格,它是一个包含一个或者多个控件属性的集合。
定义样式需要在res/values/styles.xml中进行定义,如下是一个样式的定义:
<style name="textViewStyle">
<item name="android:textSize">22sp</item>
<item name="android:textColor">#FF0000</item>
</style>
<style name="textViewStyle1" parent="textViewStyle"></style><!-- 此样式继承自textViewStyle -->
<style name="textViewStyle.Livingstone"><!-- 样式继承的另一种写法,但不可用此写法继承Android自带的定义样式? -->
<item name="android:textColor">#00FF00</item>
</style>
所有定义的样式都会在R文件中自动生成一个资源ID,加一个点表示样式继承会生成上图所示的资源id;
样式的引用:
<TextView
style="@style/textViewStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="hello" />
>>2.主题Theme
主题应用于整个应用或者activity,样式应用于具体的控件上。主题的应用与样式定义一样,不同的是主题还可以设置窗口的显示风格;主题的引用需要在清单文件中进行引用,如引用到整个应用之上就需要在Application节点中进行配置引用,而引用到单个Activity只需要在此Activity中进行配置引用;
复制代码
<style name="Livingstonetheme"><!--此定义是一个无Title的主题-->
<item name="android:windowNoTitle">true</item>
<item name="android:windowFullscreen">?android:windowNoTitle</item>
<!-- 问号表示引用此主题中android:windowNoTitle属性的值 -->
<item name="android:textSize">18sp</item>
</style>
复制代码
android系统定义了一些属性,如android:theme="@android:style/Theme.Dialog",该主题可以让Activity看起来像一个对话框,更多主题可以在文档reference->android->R.style中查看。当主题里面的样式属性值与样式里面的属性值发生冲突的时候会显示样式里面的值;
15.其它资源
在资源文件中还可以包括尺寸(dimen)、整数(integer)、布尔(bool) 、整形数组资源(integer-array)、资源数组(array)、颜色(color)
TypedArray ta = getResources().obtainTypedArray(int id); // 获取数组资源,包括integer-array、array
Final总结:
除了res/values目录中的资源名,其它目录的资源都会以文件名在R类的相应子类中生成变量;而res/values中的资源会以name属性值为变量名在R类的相应子类中生成变量;
‘伍’ android 自定义控件 属性怎么用
自定义属性设置
public class lei extends RelativeLayout {
private TextView tv1
public lei(Context context) {
super(context);
}
public lei(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.item,this);
tv1 = findViewById(R.id.tv1);
TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.lei);
String str1 = (String) array.getText(R.styleable.lei_settitle);
int str2 = array.getColor(R.styleable.lei_setbackgroudcolor,Color.BLACK);
tv1.setText(str1);
tv1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
Toast.makeText(getContext(), "toast", Toast.LENGTH_SHORT).show();
}
});
array.recycle();
}
}
布局控件
<com.example.administrator.myapplication.lei
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
cs:setbackgroudcolor="#158616"
cs:settitle="这个是标题"
cs:settitletextcolor="#FFFFFF"
cs:settextrcolor="#FFFFFF"
>
</com.example.administrator.myapplication.lei>
属性设置
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="lei" >
<attr name="setbackgroudcolor" format="color|reference"/>
<attr name="settitle" format="string|reference"/>
<attr name="settextrcolor" format="color"/>
<attr name="settitletextcolor" format="color"/>
</declare-styleable>
</resources>
‘陆’ android 左右滑屏怎么实现 哪位大神教教我
代码如下:
package kexc.scroll;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* 仿Launcher中的WorkSapce,可以左右滑动切换屏幕的类
*
*/
public class ScrollLayout extends ViewGroup {
/*
* onMeasure方法在控件的父元素正要放置它的子控件时调用。它会问一个问题,“你想要用多大地方啊?”,然后传入两个参数——
* widthMeasureSpec和heightMeasureSpec。它们指明控件可获得的空间以及关于这个空间描述的元数据。
* 比返回一个结果要好的方法是你传递View的高度和宽度到setMeasuredDimension方法里。
* 一个MeasureSpec包含一个尺寸和模式。
* 有三种可能的模式:
* UNSPECIFIED:父布局没有给子布局任何限制,子布局可以任意大小。
* EXACTLY:父布局决定子布局的确切大小。不论子布局多大,它都必须限制在这个界限里。
* AT_MOST:子布局可以根据自己的大小选择任意大小。
*/
/*
* VelocityTracker类
*
* 功能: 根据触摸位置计算每像素的移动速率。
*
* 常用方法有:
*
* public void addMovement (MotionEvent ev) 功能:添加触摸对象MotionEvent , 用于计算触摸速率。
* public void computeCurrentVelocity (int units)
* 功能:以每像素units单位考核移动速率。额,其实我也不太懂,赋予值1000即可。 参照源码 该units的意思如下: 参数 units :
* The units you would like the velocity in. A value of 1 provides pixels
* per millisecond, 1000 provides pixels per second, etc. public float
* getXVelocity () 功能:获得X轴方向的移动速率。
*/
/*
* ViewConfiguration类
*
* 功能: 获得一些关于timeouts(时间)、sizes(大小)、distances(距离)的标准常量值 。
*
* 常用方法:
*
* public int getScaledEdgeSlop()
*
* 说明:获得一个触摸移动的最小像素值。也就是说,只有超过了这个值,才代表我们该滑屏处理了。
*
* public static int getLongPressTimeout()
*
* 说明:获得一个执行长按事件监听(onLongClickListener)的值。也就是说,对某个View按下触摸时,只有超过了
*
* 这个时间值在,才表示我们该对该View回调长按事件了;否则,小于这个时间点松开手指,只执行onClick监听
*/
private static final String TAG = "ScrollLayout";
private Scroller mScroller;
private VelocityTracker mVelocityTracker;
private int mCurScreen;//当前屏幕
private int mDefaultScreen = 0;
//两种状态: 是否处于滑屏状态
private static final int TOUCH_STATE_REST = 0;//静止状态
private static final int TOUCH_STATE_SCROLLING = 1;//滑屏状态
private static final int SNAP_VELOCITY = 600; //最小的滑动速率
private int mTouchState = TOUCH_STATE_REST;
private int mTouchSlop;// change 多少像素算是发生move操作
private float mLastMotionX;
private float mLastMotionY;
public ScrollLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
// TODO Auto-generated constructor stub
}
public ScrollLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
mScroller = new Scroller(context);
mCurScreen = mDefaultScreen;
//初始化一个最小滑动距离
mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
/**
* 生成view
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// TODO Auto-generated method stub
if (changed) {
int childLeft = 0;
final int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
final View childView = getChildAt(i);
if (childView.getVisibility() != View.GONE) {
final int childWidth = childView.getMeasuredWidth();
childView.layout(childLeft, 0, childLeft + childWidth,
childView.getMeasuredHeight());
childLeft += childWidth;
}
}
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
Log.e(TAG, "onMeasure");
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
final int width = MeasureSpec.getSize(widthMeasureSpec);
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
if (widthMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ScrollLayout only canmCurScreen run at EXACTLY mode!");
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode != MeasureSpec.EXACTLY) {
throw new IllegalStateException(
"ScrollLayout only can run at EXACTLY mode!");
}
// The children are given the same width and height as the scrollLayout
final int count = getChildCount();
for (int i = 0; i < count; i++) {
getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
}
// Log.e(TAG, "moving to screen "+mCurScreen);
scrollTo(mCurScreen * width, 0);
}
/**
* According to the position of current layout scroll to the destination
* page.
*/
public void snapToDestination() {
// 判断是否超过下一屏的中间位置,如果达到就抵达下一屏,否则保持在原屏幕
// 这样的一个简单公式意思是:假设当前滑屏偏移值即 scrollCurX 加上每个屏幕一半的宽度,除以每个屏幕的宽度就是
// 我们目标屏所在位置了。 假如每个屏幕宽度为320dip, 我们滑到了500dip处,很显然我们应该到达第二屏,索引值为1
// 即(500 + 320/2)/320 = 1
final int screenWidth = getWidth();
final int destScreen = (getScrollX() + screenWidth / 2) / screenWidth;
snapToScreen(destScreen);
}
public void snapToScreen(int whichScreen) {
// get the valid layout page
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
if (getScrollX() != (whichScreen * getWidth())) {
final int delta = whichScreen * getWidth() - getScrollX();
mScroller.startScroll(getScrollX(), 0, delta, 0,
Math.abs(delta) * 5);
mCurScreen = whichScreen;
onScreenChangeListener.onScreenChange(mCurScreen);
invalidate(); // Redraw the layout
}
}
public void setToScreen(int whichScreen) {
whichScreen = Math.max(0, Math.min(whichScreen, getChildCount() - 1));
mCurScreen = whichScreen;
scrollTo(whichScreen * getWidth(), 0);
}
public int getCurScreen() {
return mCurScreen;
}
/**
* 控制view跟随手指滑动 由父视图调用用来请求子视图根据偏移值 mScrollX,mScrollY重新绘制
*/
@Override
public void computeScroll() {
// 如果返回true,表示动画还没有结束
// 因为前面startScroll,所以只有在startScroll完成时 才会为false
if (mScroller.computeScrollOffset()) {
// 产生了动画效果,根据当前值 每次滚动一点
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
/*
* 其中:onInterceptTouchEvent()主要功能是控制触摸事件的分发,例如是子视图的点击事件还是滑动事件。
* 其他所有处理过程均在onTouchEvent()方法里实现了。 1、屏幕的滑动要根据手指的移动而移动 ----
* 主要实现在onTouchEvent()方法中
*