Android - 自定义控件(三)

有些较复杂的布局,在一个应用中可能会被使用多次,并且这些布局在使用过程中还可能会需要一些动画的效果,另外,布局中的部分控件可能还需要处理和用户交互的逻辑。

比如在用户注册或是发送信息时,可能都会需要为用户提供选择图片的方式,再比如,一个需要联网的操作执行时,需要给用户一个类似正在加载之类的提示,在加载数据成功或失败时,也需要给用户相应的提示,类似这些场景,我们都可以考虑自定义一个控件,对这些通用的布局的界面、展示动画、隐藏动画及布局中的控件的业务逻辑等进行封装,达到复用的目的。

一、一个自定义layout用以实现弹出个性化的提示框

 
比如需要选择图片时,可以弹出这样的一个提示框供用户选择获取图片的方式,同样,在其他情况下也可能有类似的需求,于是,可以考虑使用自定义控件来达到复用和可扩展的目的。
public class LayerBottom extends RelativeLayout {
	private View viewBlackBack;
	private View viewContent;
	private Animation animationShow;
	private Animation animationHide;
	private Animation animationBackShow;
	private Animation animationBackHide;
	public LayerBottom(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView();
	}
	private void initView() {
		setVisibility(View.INVISIBLE);
		viewBlackBack = new View(getContext());
		viewBlackBack.setBackgroundColor(Color.parseColor("#55000000"));
		RelativeLayout.LayoutParams lpBack = new RelativeLayout.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 
				android.view.ViewGroup.LayoutParams.MATCH_PARENT);
		addView(viewBlackBack, lpBack);
	}
	/**是否是显示状态 */
	public boolean isShow() {
		return (getVisibility() == View.VISIBLE);
	}
	/** 指定弹层布局文件id*/
	public void setContent(int resourceId) {
		if (getChildCount() > 1) {
			removeView(getChildAt(1));
		}
		viewContent = LayoutInflater.from(getContext()).inflate(resourceId, null);
		RelativeLayout.LayoutParams lpContent = new RelativeLayout.LayoutParams(android.view.ViewGroup.LayoutParams.MATCH_PARENT, 
				android.view.ViewGroup.LayoutParams.WRAP_CONTENT);
		lpContent.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
		addView(viewContent, lpContent);
	}
	/** 打开弹层 */
	public void showLayer() {
		if (getVisibility() == View.INVISIBLE || getVisibility() == View.GONE) {
			setVisibility(View.VISIBLE);
		}
		showBackBlack();
		if (animationShow == null) {
			animationShow = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0,
					Animation.RELATIVE_TO_SELF, 1.0f, Animation.RELATIVE_TO_SELF, 0.0f);
		}
		animationShow.setDuration(500);
		viewContent.startAnimation(animationShow);
	}
	/** 隐藏弹层*/
	public void hideLayer() {
		hideBackBlack();
		if (animationHide == null) {
			animationHide = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, 
					Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f);
		}
		animationHide.setDuration(500);
		viewContent.startAnimation(animationHide);
		animationHide.setAnimationListener(new AnimationListener() {
			@Override
			public void onAnimationStart(Animation animation) {
			}
			@Override
			public void onAnimationRepeat(Animation animation) {
			}
			@Override
			public void onAnimationEnd(Animation animation) {
				if (getVisibility() == View.VISIBLE) {
					setVisibility(View.INVISIBLE);
				}
			}
		});
	}
	private void showBackBlack() {
		if (animationBackShow == null) {
			animationBackShow = new AlphaAnimation(0.0f, 1.0f);
			animationBackShow.setAnimationListener(new AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {
					viewBlackBack.setVisibility(View.VISIBLE);
					viewContent.setVisibility(View.VISIBLE);
				}
				@Override
				public void onAnimationRepeat(Animation arg0) {
				}
				@Override
				public void onAnimationEnd(Animation arg0) {
				}
			});
		}
		animationBackShow.setDuration(500);
		viewBlackBack.startAnimation(animationBackShow);
	}
	private void hideBackBlack() {
		if (animationBackHide == null) {
			animationBackHide = new AlphaAnimation(1.0f, 0.0f);
			animationBackHide.setAnimationListener(new AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {
				}
				@Override
				public void onAnimationRepeat(Animation animation) {
				}
				@Override
				public void onAnimationEnd(Animation animation) {
					viewBlackBack.setVisibility(View.INVISIBLE);
					viewContent.setVisibility(View.INVISIBLE);
				}
			});
		}
		animationBackHide.setDuration(500);
		viewBlackBack.startAnimation(animationBackHide);
	}
	@Override
	public boolean onTouchEvent(MotionEvent event) {//保证后面的UI不可点击
		return true;
	}
}

在xml文件中引用:

<com.hwgt.custom.view.LayerBottom
	android:id="@+id/layer_bottom_img"
	android:layout_width="match_parent"
	android:layout_height="match_parent"/>

然后,在activity中: 

//用来显示图片获取方式的布局(从底部弹出)
private LayerBottom layerBottomImg;
layerBottomImg = (LayerBottom) findViewById(R.id.layer_bottom_img);
layerBottomImg.setContent(R.layout.layer_bottom_item_bg);
... ... 
layerBottomImg.showLayer();//弹出弹框
layerBottomImg.hideLayer();//隐藏弹框

布局文件layer_bottom_item_bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="match_parent"
	android:layout_height="wrap_content"
	android:layout_alignParentBottom="true"
	android:background="#ffffff"
	android:orientation="vertical"
	android:gravity="center">
	<LinearLayout
		android:id="@+id/ll_layer_take_picture"
		android:layout_width="match_parent"
		android:layout_height="53dp"
		android:gravity="center_vertical|center_horizontal"
		android:orientation="vertical"
		android:background="@drawable/ll_layer_item_select_bg">
		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="拍照"
			android:textSize="17dp"
			android:textColor="#222222"/>
	</LinearLayout>
	<View
		android:layout_width="match_parent"
		android:layout_height="1dp"
		android:background="#ededed"/>
	<LinearLayout
		android:id="@+id/ll_layer_select"
		android:layout_width="match_parent"
		android:layout_height="53dp"
		android:gravity="center_vertical|center_horizontal"
		android:orientation="vertical"
		android:background="@drawable/ll_layer_item_select_bg">
		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="从手机相册选择"
			android:textSize="17dp"
			android:textColor="#222222"/>
	</LinearLayout>
	<View
		android:layout_width="match_parent"
		android:layout_height="12dp"
		android:background="#ededed"/>
	<LinearLayout
		android:id="@+id/ll_layer_cancle"
		android:layout_width="match_parent"
		android:layout_height="53dp"
		android:gravity="center_vertical|center_horizontal"
		android:orientation="vertical"
		android:background="@drawable/ll_layer_item_select_bg">
		<TextView
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="取消"
			android:textSize="17dp"
			android:textColor="#222222"/>
	</LinearLayout>
</LinearLayout>

drawable中的ll_layer_item_select_bg.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
	<item
		android:drawable="@drawable/layer_item_press"
		android:state_pressed="true"/>
	<item
		android:drawable="@drawable/layer_item_no_press"
		android:state_enabled="false"/>
	<item android:drawable="@drawable/layer_item_no_press"/>
</selector>

drawable中的layer_item_press.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<shape
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">
	<solid android:color="#ededed"/>
	<corners android:radius="0dp"/>
</shape>

drawable中的layer_item_no_press.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<shape
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:shape="rectangle">
	<solid android:color="#ffffff"/>
	<corners android:radius="0dp"/>
</shape>

 

二、通用的加载状态提示界面

 

 

 

posted on 2016-04-22 11:41  快乐的码农  阅读(334)  评论(0)    收藏  举报