package name.quanke.app.libs.emptylayout; import android.content.Context; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.util.Log; import android.view.Gravity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import java.util.ArrayList; import java.util.List; /** * 空页面 错误页面 数据加载中 展示 * * Created by quanke(http://quanke.name) on 2016/4/5. */ public class EmptyLayout extends LinearLayout{ private Animation mLoadingAnimation; private ViewGroup mLoadingView; private ViewGroup mEmptyView; private ViewGroup mErrorView; private TextView mLoadingMessageView; private TextView mEmptyMessageView; private TextView mErrorMessageView; private RelativeLayout mEmptyRelativeLayout; private int mErrorMessageViewId; private int mEmptyMessageViewId; private int mLoadingMessageViewId; private LayoutInflater mInflater; private boolean mViewsAdded; private int mLoadingAnimationViewId; private View.OnClickListener mLoadingButtonClickListener; private View.OnClickListener mEmptyButtonClickListener; private View.OnClickListener mErrorButtonClickListener; // --------------------------- // static variables // --------------------------- /** * The empty state */ public final static int TYPE_EMPTY = 1; /** * The loading state */ public final static int TYPE_LOADING = 2; /** * The error state */ public final static int TYPE_ERROR = 3; // --------------------------- // default values // --------------------------- private int mEmptyType = TYPE_LOADING; private int mErrorDrawable = R.drawable.ic_error; private int mEmptyDrawable = R.drawable.ic_empty; private int mLoadingDrawable = R.drawable.ic_loading; private String mErrorMessage = "哎呀!发生了一些错误"; private String mEmptyMessage = "啥也没有"; private String mLoadingMessage = "请等一等啦ლ(╹◡╹ლ)"; private int mLoadingViewButtonId = R.id.buttonLoading; private int mErrorViewButtonId = R.id.buttonError; private int mEmptyViewButtonId = R.id.buttonEmpty; private boolean mShowEmptyButton = true; private boolean mShowLoadingButton = true; private boolean mShowErrorButton = true; private List<View> childViews; public EmptyLayout(Context context) { super(context); init(); } public EmptyLayout(Context context, AttributeSet attrs) { super(context, attrs); init(); } public EmptyLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init(){ childViews = new ArrayList<>(); // getChildViews(); mInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); } // --------------------------- // getters and setters // --------------------------- /** * Gets the loading layout * @return the loading layout */ public ViewGroup getLoadingView() { return mLoadingView; } /** * Sets loading layout * @param loadingView */ public void setLoadingView(ViewGroup loadingView) { this.mLoadingView = loadingView; } /** * Sets loading layout resource * @param res */ public void setLoadingViewRes(int res){ this.mLoadingView = (ViewGroup) mInflater.inflate(res, null); } /** * Gets the empty layout * @return the empty layout */ public ViewGroup getEmptyView() { return mEmptyView; } /** * Sets empty layout * @param emptyView */ public void setEmptyView(ViewGroup emptyView) { this.mEmptyView = emptyView; } /** * Sets empty layout resource * @param res */ public void setEmptyViewRes(int res){ this.mEmptyView = (ViewGroup) mInflater.inflate(res, null); } /** * Gets the error layout * @return the error layout */ public ViewGroup getErrorView() { return mErrorView; } /** * Sets error layout * @param errorView */ public void setErrorView(ViewGroup errorView) { this.mErrorView = errorView; } /** * Sets error layout resource * @param res */ public void setErrorViewRes(int res){ this.mErrorView = (ViewGroup) mInflater.inflate(res, null); } /** * Gets the loading animation * @return the loading animation */ public Animation getLoadingAnimation() { return mLoadingAnimation; } /** * Sets the loading animation * @param animation */ public void setLoadingAnimation(Animation animation) { this.mLoadingAnimation = animation; } /** * Sets the resource of loading animation * @param animationResource */ public void setLoadingAnimationRes(int animationResource) { mLoadingAnimation = AnimationUtils.loadAnimation(getContext(), animationResource); } /** * @return */ public int getEmptyType() { return mEmptyType; } /** * @param emptyType */ public void setEmptyType(int emptyType) { this.mEmptyType = emptyType; changeEmptyType(); } /** * * @return */ public String getErrorMessage() { return mErrorMessage; } /** * * @param errorMessage the error message * @param messageViewId */ public void setErrorMessage(String errorMessage, int messageViewId) { this.mErrorMessage = errorMessage; this.mErrorMessageViewId = messageViewId; } /** * * @param errorMessage the error message */ public void setErrorMessage(String errorMessage) { this.mErrorMessage = errorMessage; } /** * * @return */ public String getEmptyMessage() { return mEmptyMessage; } /** * * @param emptyMessage the message * @param messageViewId */ public void setEmptyMessage(String emptyMessage, int messageViewId) { this.mEmptyMessage = emptyMessage; this.mEmptyMessageViewId = messageViewId; } /** * * @param emptyMessage the message */ public void setEmptyMessage(String emptyMessage) { this.mEmptyMessage = emptyMessage; } /** * Gets the message which will be shown when the list is being loaded * @return */ public String getLoadingMessage() { return mLoadingMessage; } /** * @param loadingMessage the message * @param messageViewId */ public void setLoadingMessage(String loadingMessage, int messageViewId) { this.mLoadingMessage = loadingMessage; this.mLoadingMessageViewId = messageViewId; } /** * * @param loadingMessage the message */ public void setLoadingMessage(String loadingMessage) { this.mLoadingMessage = loadingMessage; } /** * * @return */ public int getLoadingAnimationViewId() { return mLoadingAnimationViewId; } /** * * @param loadingAnimationViewId the id of the view */ public void setLoadingAnimationViewId(int loadingAnimationViewId) { this.mLoadingAnimationViewId = loadingAnimationViewId; } /** * Gets the OnClickListener which perform when LoadingView was click * @return */ public View.OnClickListener getLoadingButtonClickListener() { return mLoadingButtonClickListener; } /** * Sets the OnClickListener to LoadingView * @param loadingButtonClickListener OnClickListener Object */ public void setLoadingButtonClickListener(View.OnClickListener loadingButtonClickListener) { this.mLoadingButtonClickListener = loadingButtonClickListener; } /** * Gets the OnClickListener which perform when EmptyView was click * @return */ public View.OnClickListener getEmptyButtonClickListener() { return mEmptyButtonClickListener; } /** * Sets the OnClickListener to EmptyView * @param emptyButtonClickListener OnClickListener Object */ public void setEmptyButtonClickListener(View.OnClickListener emptyButtonClickListener) { this.mEmptyButtonClickListener = emptyButtonClickListener; } /** * Gets the OnClickListener which perform when ErrorView was click * @return */ public View.OnClickListener getErrorButtonClickListener() { return mErrorButtonClickListener; } /** * Sets the OnClickListener to ErrorView * @param errorButtonClickListener OnClickListener Object */ public void setErrorButtonClickListener(View.OnClickListener errorButtonClickListener) { this.mErrorButtonClickListener = errorButtonClickListener; } /** * Gets if a button is shown in the empty view * @return if a button is shown in the empty view */ public boolean isEmptyButtonShown() { return mShowEmptyButton; } /** * Sets if a button will be shown in the empty view * @param showEmptyButton will a button be shown in the empty view */ public void setShowEmptyButton(boolean showEmptyButton) { this.mShowEmptyButton = showEmptyButton; } /** * Gets if a button is shown in the loading view * @return if a button is shown in the loading view */ public boolean isLoadingButtonShown() { return mShowLoadingButton; } /** * Sets if a button will be shown in the loading view * @param showLoadingButton will a button be shown in the loading view */ public void setShowLoadingButton(boolean showLoadingButton) { this.mShowLoadingButton = showLoadingButton; } /** * Gets if a button is shown in the error view * @return if a button is shown in the error view */ public boolean isErrorButtonShown() { return mShowErrorButton; } /** * Sets if a button will be shown in the error view * @param showErrorButton will a button be shown in the error view */ public void setShowErrorButton(boolean showErrorButton) { this.mShowErrorButton = showErrorButton; } /** * Gets the ID of the button in the loading view * @return the ID of the button in the loading view */ public int getmLoadingViewButtonId() { return mLoadingViewButtonId; } /** * Sets the ID of the button in the loading view. This ID is required if you want the button the loading view to be click-able. * @param loadingViewButtonId the ID of the button in the loading view */ public void setLoadingViewButtonId(int loadingViewButtonId) { this.mLoadingViewButtonId = loadingViewButtonId; } /** * Gets the ID of the button in the error view * @return the ID of the button in the error view */ public int getErrorViewButtonId() { return mErrorViewButtonId; } /** * Sets the ID of the button in the error view. This ID is required if you want the button the error view to be click-able. * @param errorViewButtonId the ID of the button in the error view */ public void setErrorViewButtonId(int errorViewButtonId) { this.mErrorViewButtonId = errorViewButtonId; } /** * Gets the ID of the button in the empty view * @return the ID of the button in the empty view */ public int getEmptyViewButtonId() { return mEmptyViewButtonId; } /** * Sets the ID of the button in the empty view. This ID is required if you want the button the empty view to be click-able. * @param emptyViewButtonId the ID of the button in the empty view */ public void setEmptyViewButtonId(int emptyViewButtonId) { this.mEmptyViewButtonId = emptyViewButtonId; } public int getErrorDrawable() { return mErrorDrawable; } /** * 设置错误的图片 * @param mErrorDrawable 错误图片资源id */ public void setErrorDrawable(int mErrorDrawable) { this.mErrorDrawable = mErrorDrawable; } public int getEmptyDrawable() { return mEmptyDrawable; } /** * 设置空的图片 * @param mEmptyDrawable 错误空资源id */ public void setEmptyDrawable(int mEmptyDrawable) { this.mEmptyDrawable = mEmptyDrawable; } public int getLoadingDrawable() { return mLoadingDrawable; } /** * 设置Loading的图片 * @param mLoadingDrawable 错误Loading资源id */ public void setLoadingDrawable(int mLoadingDrawable) { this.mLoadingDrawable = mLoadingDrawable; } private void getChildViews(){ int childCount = getChildCount(); Log.d("EmptyLayout","ChildCount:"+childCount); View view; for (int i=0;i<childCount;i++){ view = getChildAt(i); if (isEmptyView(view)){ continue; } childViews.add(view); } } private void hideChildView(){ for (View view: childViews ) { if (isEmptyView(view)){ continue; } view.setVisibility(GONE); } } /** * 判断view 对象是否是EmptyView * @param view * @return */ private boolean isEmptyView(View view){ if ((view == null||mEmptyRelativeLayout == view||view == mLoadingView||view == mEmptyView||view == mErrorView)){ return true; } return false; } private void showChildView(){ for (View view: childViews ) { if (isEmptyView(view)){ continue; } view.setVisibility(VISIBLE); } } /** * 隐藏EmptyView */ private void hideEmptyView(){ if (mLoadingView != null){ mLoadingView.setVisibility(GONE); } if (mEmptyView != null){ mEmptyView.setVisibility(GONE); } if (mErrorView != null){ mErrorView.setVisibility(GONE); } } /** * 展示错误信息 * @param resId 图片资源id * @param text */ public void showError(int resId,String text){ setErrorDrawable(resId); setEmptyMessage(text); showError(); } public void showError(){ getChildViews(); hideChildView(); this.mEmptyType = TYPE_ERROR; changeEmptyType(); } /** * 展示空信息 * @param resId 图片资源id * @param text */ public void showEmpty(int resId,String text){ setEmptyDrawable(resId); setEmptyMessage(text); showEmpty(); } public void showEmpty(){ getChildViews(); hideChildView(); this.mEmptyType = TYPE_EMPTY; changeEmptyType(); } /** * 展示加载中 * @param resId 图片资源id * @param text */ public void showLoading(int resId,String text){ setLoadingDrawable(resId); setLoadingMessage(text); showLoading(); } public void showLoading(){ getChildViews(); hideChildView(); this.mEmptyType = TYPE_LOADING; changeEmptyType(); } /** *隐藏EmptyLayout */ public void hide(){ showChildView(); hideEmptyView(); } private void changeEmptyType() { setDefaultValues(); refreshMessages(); // insert views in the root view if (!mViewsAdded) { RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); lp.addRule(RelativeLayout.CENTER_IN_PARENT); mEmptyRelativeLayout = new RelativeLayout(getContext()); mEmptyRelativeLayout.setGravity(Gravity.CENTER); mEmptyRelativeLayout.setLayoutParams(lp); if (mEmptyView!=null) mEmptyRelativeLayout.addView(mEmptyView); if (mLoadingView!=null) mEmptyRelativeLayout.addView(mLoadingView); if (mErrorView!=null) mEmptyRelativeLayout.addView(mErrorView); mViewsAdded = true; mEmptyRelativeLayout.setVisibility(VISIBLE); addView(mEmptyRelativeLayout); } // change empty type View loadingAnimationView = null; if (mLoadingAnimationViewId > 0) loadingAnimationView = findViewById(mLoadingAnimationViewId); switch (mEmptyType) { case TYPE_EMPTY: if (mEmptyView!=null) mEmptyView.setVisibility(View.VISIBLE); if (mErrorView!=null) mErrorView.setVisibility(View.GONE); if (mLoadingView!=null) { mLoadingView.setVisibility(View.GONE); if (loadingAnimationView!=null && loadingAnimationView.getAnimation()!=null) loadingAnimationView.getAnimation().cancel(); } break; case TYPE_ERROR: if (mEmptyView!=null) mEmptyView.setVisibility(View.GONE); if (mErrorView!=null) mErrorView.setVisibility(View.VISIBLE); if (mLoadingView!=null) { mLoadingView.setVisibility(View.GONE); if (loadingAnimationView!=null && loadingAnimationView.getAnimation()!=null) loadingAnimationView.getAnimation().cancel(); } break; case TYPE_LOADING: if (mEmptyView!=null) mEmptyView.setVisibility(View.GONE); if (mErrorView!=null) mErrorView.setVisibility(View.GONE); if (mLoadingView!=null) { mLoadingView.setVisibility(View.VISIBLE); if (mLoadingAnimation != null && loadingAnimationView!=null) { loadingAnimationView.startAnimation(mLoadingAnimation); } else if (loadingAnimationView!=null) { loadingAnimationView.startAnimation(getRotateAnimation()); } } break; default: break; } } private void refreshMessages() { if (mEmptyMessageViewId>0 && mEmptyMessage!=null) { mEmptyMessageView = ((TextView)mEmptyView.findViewById(mEmptyMessageViewId)); mEmptyMessageView.setText(mEmptyMessage); setTopDrawables(mEmptyMessageView, mEmptyDrawable); } if (mLoadingMessageViewId>0 && mLoadingMessage!=null) { mLoadingMessageView = ((TextView)mLoadingView.findViewById(mLoadingMessageViewId)); mLoadingMessageView .setText(mLoadingMessage); // setTopDrawables(mLoadingMessageView,mLoadingDrawable);// loading 不能已经有loading image view ,不能直接设置TopDrawable } if (mErrorMessageViewId>0 && mErrorMessage!=null){ mErrorMessageView = ((TextView)mErrorView.findViewById(mErrorMessageViewId)); mErrorMessageView.setText(mErrorMessage); setTopDrawables(mErrorMessageView,mErrorDrawable); } } private void setTopDrawables(TextView textView,int resId){ Drawable drawable = getResources().getDrawable(resId); drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());//必须设置图片大小,否则不显示 textView.setCompoundDrawables(null,drawable,null,null); } private void setDefaultValues() { if (mEmptyView==null) { mEmptyView = (ViewGroup) mInflater.inflate(R.layout.view_empty, null); if (!(mEmptyMessageViewId>0)) mEmptyMessageViewId = R.id.textViewMessage; if (mShowEmptyButton && mEmptyViewButtonId>0 && mEmptyButtonClickListener!=null) { View emptyViewButton = mEmptyView.findViewById(mEmptyViewButtonId); if (emptyViewButton != null) { emptyViewButton.setOnClickListener(mEmptyButtonClickListener); emptyViewButton.setVisibility(View.VISIBLE); } } else if (mEmptyViewButtonId>0) { View emptyViewButton = mEmptyView.findViewById(mEmptyViewButtonId); emptyViewButton.setVisibility(View.GONE); } } if (mLoadingView==null) { mLoadingView = (ViewGroup) mInflater.inflate(R.layout.view_loading, null); mLoadingAnimationViewId = R.id.imageViewLoading; if (!(mLoadingMessageViewId>0)) mLoadingMessageViewId = R.id.textViewMessage; if (mShowLoadingButton && mLoadingViewButtonId>0 && mLoadingButtonClickListener!=null) { View loadingViewButton = mLoadingView.findViewById(mLoadingViewButtonId); if (loadingViewButton != null) { loadingViewButton.setOnClickListener(mLoadingButtonClickListener); loadingViewButton.setVisibility(View.VISIBLE); } } else if (mLoadingViewButtonId>0) { View loadingViewButton = mLoadingView.findViewById(mLoadingViewButtonId); loadingViewButton.setVisibility(View.GONE); } } if (mErrorView==null) { mErrorView = (ViewGroup) mInflater.inflate(R.layout.view_error, null); if (!(mErrorMessageViewId>0)) mErrorMessageViewId = R.id.textViewMessage; if (mShowErrorButton && mErrorViewButtonId>0 && mErrorButtonClickListener!=null) { View errorViewButton = mErrorView.findViewById(mErrorViewButtonId); if (errorViewButton != null) { errorViewButton.setOnClickListener(mErrorButtonClickListener); errorViewButton.setVisibility(View.VISIBLE); } } else if (mErrorViewButtonId>0) { View errorViewButton = mErrorView.findViewById(mErrorViewButtonId); errorViewButton.setVisibility(View.GONE); } } } private static Animation getRotateAnimation() { final RotateAnimation rotateAnimation = new RotateAnimation(0, 360, Animation.RELATIVE_TO_SELF, .5f, Animation.RELATIVE_TO_SELF, .5f); rotateAnimation.setDuration(1500); rotateAnimation.setInterpolator(new LinearInterpolator()); rotateAnimation.setRepeatCount(Animation.INFINITE); return rotateAnimation; } // showEmpty // showLoading // showError // setLoadingView // setEmptyView // setErrorView // setLoadingAnimation // setErrorMessage // setLoadingMessage // setEmptyMessage // setEmptyViewButtonClickListener // setLoadingViewButtonClickListener // setErrorViewButtonClickListener // setShowEmptyButton // setShowLoadingButton // setShowErrorButton }