前言
最近看到一本书,是开发安卓的一些小技巧和基础知识,大家一起查漏补缺吧!只有一部分,其他的有点老了,还有一些不感兴趣,没继续看了,所以只有9个知识点哦
1. 使用weight和weightsum属性实现视图居中
<LinearLayout
......
android:gravity="center"
android:orientation="horizontal"
android:weightSum="1" > //
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5" //确保按钮占据50%空间
......
/>
</LinearLayout>
2. 在include里使用android:layout_*属性,重写include布局属性,实现复用
footer布局:
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:gravity="center"
android:text="@string/footer_text" />
include footer:
<RelativeLayout
<include
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="30dp"
layout="@layout/footer" />
......
/RelativeLayout>
3. ViewStub实现view的延迟加载
场景:让用户自己决定是否显示地图信息
地图view
<com.google.android.maps.MapView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
......
/>
使用ViewStub
<ViewStub
android:id="@+id/map_stub"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:inflatedId="@+id/map_view"
android:layout="@layout/map" />
在Activity中调用
private View mViewStub;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mViewStub = findViewById(R.id.map_stub);
}
public void onShowMap(View v) {
mViewStub.setVisibility(View.VISIBLE);
}
......
inflatedId是调用ViewStub的inflate()方法或setVisibility()方法是返回的ID,这个ID便是被填充的View的ID,避免了使用findViewById()方法
4.定制ViewGroup
绘制布局由两个遍历过程组成:测量过程和布局过程。测量过程由measure(int, int)方法完成,该方法从上到下遍历视图树。在递归遍历过程中,每个视图都会向下层传递尺寸和规格。当measure方法遍历结束,每个视图都保存了各自的尺寸信息。第二个过程由layout(int,int,int,int)方法完成,该方法也是由上而下遍历视图树,在遍历过程中,每个父视图通过测量过程的结果定位所有子视图的位置信息。
为了理解这个概念,下面分析ViewGroup的绘制过程,第一步是测量ViewGroup的宽度和高度,在onMeasure方法中完成这个步骤。在该方法中,ViewGroup通过遍历所有子视图计算它的大小。最后一步操作,在onLayout()方法中完成,利用上一步计算出的测量信息,布局所有子视图。
作者实现了如下布局:
1>在values下创建attrs.xml,自定义属性
<resources>
<declare-styleable name="CascadeLayout">
<attr name="horizontal_spacing" format="dimension" />
<attr name="vertical_spacing" format="dimension" />
</declare-styleable>
<declare-styleable name="CascadeLayout_LayoutParams">
<attr name="layout_vertical_spacing" format="dimension" />//属性名前缀是layout_,因此该属性会被添加到LayoutParams的属性表中
</declare-styleable>
</resources>
2>布局
<FrameLayout
xmlns:anyname="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<com.XX.view.CascadeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
anyname:horizontal_spacing="30dp"
anyname:vertical_spacing="20dp" >
<View
android:layout_width="100dp"
android:layout_height="150dp"
anyname:layout_vertical_spacing="90dp"
android:background="#FF0000" />
<View
android:layout_width="100dp"
android:layout_height="150dp"
android:background="#00FF00" />
<View
android:layout_width="100dp"
android:layout_height="150dp"
android:background="#0000FF" />
</com.XX.view.CascadeLayout>
</FrameLayout>
3>自定义CascadeLayout
public class CascadeLayout extends ViewGroup {
private int mHorizontalSpacing;
private int mVerticalSpacing;
public CascadeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CascadeLayout);
try {
mHorizontalSpacing = a.getDimensionPixelSize(
R.styleable.CascadeLayout_horizontal_spacing,
getResources().getDimensionPixelSize(
R.dimen.cascade_horizontal_spacing));
mVerticalSpacing = a.getDimensionPixelSize(
R.styleable.CascadeLayout_vertical_spacing, getResources()
.getDimensionPixelSize(R.dimen.cascade_vertical_spacing));
} finally {
a.recycle();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 使用宽和高计算布局的最终大小以及子视图的x和y轴位置
int width = getPaddingLeft();
int height = getPaddingTop();
int verticalSpacing;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
verticalSpacing = mVerticalSpacing;
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec); //令每个子视图测量自身
LayoutParams lp = (LayoutParams) child.getLayoutParams();
width = getPaddingLeft() + mHorizontalSpacing * i;
// 在LayoutParams中保存每个子视图的x、y坐标
lp.x = width;
lp.y = height;
if (lp.verticalSpacing >= 0) {
verticalSpacing = lp.verticalSpacing;
}
width += child.getMeasuredWidth();
height += verticalSpacing;
}
width += getPaddingRight();
height += getChildAt(getChildCount() - 1).getMeasuredHeight()
+ getPaddingBottom();
setMeasuredDimension(resolveSize(width, widthMeasureSpec),
resolveSize(height, heightMeasureSpec)); // 用计算所得宽高设置整个布局的测量尺寸
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.layout(lp.x, lp.y, lp.x + child.getMeasuredWidth(), lp.y
+ child.getMeasuredHeight());
}
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof LayoutParams;
}
@Override
protected LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
return new LayoutParams(p.width, p.height);
}
public static class LayoutParams extends ViewGroup.LayoutParams {
int x;
int y;
public int verticalSpacing;
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs,
R.styleable.CascadeLayout_LayoutParams);
try {
verticalSpacing = a
.getDimensionPixelSize(
R.styleable.CascadeLayout_LayoutParams_layout_vertical_spacing,
-1);
} finally {
a.recycle();
}
}
public LayoutParams(int w, int h) {
super(w, h);
}
}
}
5. TextSwitcher和ImageSwitcher实现平滑过渡
TextSwitcher: 为文本标签添加动画效果
ImageSwitcher : 为图片切换添加动画效果
mTextSwitcher.setFactory(new ViewFactory() {
@Override
public View makeView() {
TextView t = new TextView(MainActivity.this);
t.setGravity(Gravity.CENTER);
return t;
}
});
mTextSwitcher.setInAnimation(this, android.R.anim.fade_in);
mTextSwitcher.setOutAnimation(this, android.R.anim.fade_out);
mTextSwitcher.setText("hello");
6. 避免在Edittext中验证日期
在应用程序中使用Android内置资源是一个借用设备样式的好方法,如
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@android:drawable/edit_text"
/>
7. 格式化TextView的文本,如链接、不同样式文本等
链接:
textView1.setText(Html.fromHtml("<![CDATA[Visit <a href=\"http://manning.com/\">Manning home page</a>]]>"));
textView1.setMovementMethod(LinkMovementMethod.getInstance());
不同样式
final Spannable text2 = new SpannableString(
getString(R.string.text2));
text2.setSpan(new BackgroundColorSpan(Color.RED), 1, 4, 0);
text2.setSpan(new ForegroundColorSpan(Color.BLUE), 5, 9, 0);
XX.setText(text2);
8. 横竖屏
设置android:configChanges="orientation"就不会重启Activity,而是调用onConfigurationChanged()方法
9. 移除窗口默认背景提高应用程序启动速度
<resources>
<style name="Theme.NoBackground" parent="android:Theme">
<item name="android:windowBackground">@null</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>
9.更改toast显示位置
Toast toast = Toast.makeText(this, "Upper Left!",
Toast.LENGTH_SHORT);
toast.setGravity(Gravity.TOP | Gravity.LEFT, 0, 0);
toast.show();
网友评论