当前位置: 代码迷 >> Android >> [Android] 高速实现一个通用EmptyView
  详细解决方案

[Android] 高速实现一个通用EmptyView

热度:57   发布时间:2016-04-27 23:23:37.0
[Android] 快速实现一个通用EmptyView

好的APP应当具备良好的交互, 最好能贴心的满足用户的需求. 而人性化的提醒就是其中之一. 某些APP中经常会看到这样的场景, 当加载内容失败, 或者获取内容失败时, 界面会变成一个可与用后交互的场景. 允许用户点击屏幕或者界面中某个按钮, 尝试重新获取内容或者检测网络连接等等.  Android的ListView中有类似setEmptyView(...) 的方法, 当列表中没有数据, 就会显示该 emptyView. 但并非所有的View都有这样的接口方法, 为此我们可以自己去实现可通用的"emptyView". 


这里通过简单的例子提供一种思路, 当然不是唯一的. 我们可以根据自己的想法实现各种各样的emptyView本质还是调用view.setVisibility(...).

效果图如下, 看起来好简单吧! 



So 直接上代码喇!

将EmptyView封装在某个常用布局文件中, 比如RelativeLayout, 当然也可以是LinearLayout等等.

public class CustomRelativeLayout extends RelativeLayout{    public static interface RetryListener{        void retry();    }    private ProgressBar progressBar = null;    private Button btn_refresh = null;    private TextView tv_tip = null;    private boolean isNormal = true;    private RetryListener retryListener = null;    private final static int tvTipId = 0x1001;    public CustomRelativeLayout(Context context) {        this(context, null);    }    public CustomRelativeLayout(Context context, AttributeSet attrs) {        this(context, attrs, 0);    }    public CustomRelativeLayout(Context context, AttributeSet attrs,                                int defStyle) {        super(context, attrs, defStyle);    }    /**     * 设置加载界面     */    protected void setInProgress()    {        if(progressBar == null)        {            int size = (int) TypedValue                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 45, getResources().getDisplayMetrics());            progressBar = new ProgressBar(getContext());            RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(size,size);            lp.addRule(RelativeLayout.CENTER_IN_PARENT);            progressBar.setLayoutParams(lp);            addView(progressBar);        }        if(getChildCount() > 0)        {            int childCount = getChildCount();            if(childCount >0)            {                for(int i=(childCount-1); i>=0; i--)                {                    getChildAt(i).setVisibility(View.GONE);                }            }        }        if(btn_refresh != null)            btn_refresh.setVisibility(View.GONE);        if(tv_tip != null)            tv_tip.setVisibility(View.GONE);        progressBar.setVisibility(View.VISIBLE);    }    /**     * 显示加载失败界面,隐藏所有正常的View元素     */    protected void setChildrenGone()    {        if(btn_refresh == null)        {            btn_refresh = new Button(getContext());            tv_tip = new TextView(getContext());            tv_tip.setText("网络连接失败");            tv_tip.setGravity(Gravity.CENTER);            tv_tip.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);            btn_refresh.setText("刷新");            btn_refresh.setOnClickListener(new OnClickListener() {                @Override                public void onClick(View v) {                    if(retryListener != null)                    {                        retryListener.retry();                    }                    else                    {                        Toast.makeText(getContext(), "暂无数据", Toast.LENGTH_SHORT).show();                    }                }            });            int btnWidth = (int)TypedValue                    .applyDimension(TypedValue.COMPLEX_UNIT_DIP, 80, getResources().getDisplayMetrics());            RelativeLayout.LayoutParams lp                    = new RelativeLayout.LayoutParams(btnWidth, LayoutParams.WRAP_CONTENT);            lp.addRule(RelativeLayout.CENTER_IN_PARENT);            lp.setMargins(0, 10, 0, 0);            btn_refresh.setLayoutParams(lp);            btn_refresh.setId(tvTipId);            btn_refresh.setVisibility(View.GONE);            addView(btn_refresh);            RelativeLayout.LayoutParams lp_tv                    = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);            lp_tv.addRule(RelativeLayout.ABOVE, tvTipId);            tv_tip.setLayoutParams(lp_tv);            addView(tv_tip);        }        if(getChildCount() > 0)        {            int childCount = getChildCount();            if(childCount >0)            {                for(int i=(childCount-1); i>=0; i--)                {                    getChildAt(i).setVisibility(View.GONE);                }            }        }        if(progressBar != null)            progressBar.setVisibility(View.GONE);        isNormal = false;        btn_refresh.setVisibility(View.VISIBLE);        tv_tip.setVisibility(View.VISIBLE);    }    /**     * 显示正常View元素     */    protected void setChildrenVisible()    {        if(getChildCount() > 0)        {            int childCount = getChildCount();            if(childCount >0)            {                for(int i=(childCount-1); i>=0; i--)                {                    getChildAt(i).setVisibility(View.VISIBLE);                }            }            if(progressBar != null)                progressBar.setVisibility(View.GONE);            if(btn_refresh != null)                btn_refresh.setVisibility(View.GONE);            if(tv_tip != null)                tv_tip.setVisibility(View.GONE);            isNormal = true;        }    }    protected boolean isNormalView()    {        return isNormal;    }    public void setRetryListener(RetryListener listener)    {        this.retryListener = listener;    }}

提供一个RetryListener接口, 作为点击 "刷新" 按钮后的事件.


然后模拟加载中并且加载失败的界面, 点击按钮后迟延3秒, 假设获取数据成功, 更新view后显示正常的界面.

public class MainActivity extends Activity {    private Button btn_start = null;    private static CustomRelativeLayout cuLayout = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        init();    }    private static Handler mHandler = new Handler()    {       @Override        public void handleMessage(Message msg)       {           if(msg.what == 0x1)           {               cuLayout.setChildrenVisible();           }           else if(msg.what == 0x2)           {               cuLayout.setChildrenGone();           }           super.handleMessage(msg);       }    };    private void init()    {        btn_start = (Button) findViewById(R.id.btn_start);        cuLayout = (CustomRelativeLayout) findViewById(R.id.container);        cuLayout.setRetryListener(new CustomRelativeLayout.RetryListener(){            public void retry()            {                cuLayout.setInProgress();                mHandler.sendEmptyMessageDelayed(0x1,3000);            }        });        btn_start.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                cuLayout.setChildrenGone();            }        });        cuLayout.setInProgress();        mHandler.sendEmptyMessageDelayed(0x2,2000);    }}

布局文件:

<com.alextam.progressview.CustomRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/container"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <RelativeLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="#FFFFFF"        >        <ImageView            android:layout_width="match_parent"            android:layout_height="250dp"            android:src="@mipmap/movie"            />        <Button            android:id="@+id/btn_start"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:text="ACTION"            />    </RelativeLayout></com.alextam.progressview.CustomRelativeLayout>

就是这么简单喇, 相信看完后也能定制出自己喜爱的界面哦! 另外, 作为EmptyView和加载view, 并不推荐使用复杂的元素. 最好简单而好看的View元素就够了. 因为仅仅是充当辅助的作用, 轻量化, 几乎不占内存是前提.



版权声明:本文为博主原创文章,未经博主允许不得转载。

  相关解决方案