Android to create a different Emptyview

Source: Internet
Author: User

Everyone is very familiar with the ListView, visual also often use a ListView method setEmptyView , to set when the data load or data load failure of a reminder effect, this method is simple to use, but if you provide a complex layout, such as:

After the data load fails, add a Button user who can choose to reload the data.

Well, you might do this, find the button, and then set the Click event for the button, OK ... A two can endure, that much? For example, I encountered this situation, in the test phase, the boss let a refresh function, if this method, estimated now I am still working overtime (2015/7/27 23:00), that there is a more convenient way, a few lines of code can be done? And you don't have to write about those annoying things setOnClickListener ? Can you provide a more than just a limitation ListView EmptyView , because I am not only in the ListView use.

The answer is yes, this blog, we're going to implement a component like this, in between implementations, let's look at ListView how a relationship with his emptyview is first anchored to the ListView.setEmptyView method:

  @android . View. Remotableviewmethod public  void  setemptyview  (View emptyview) {memptyview = Emptyview; //If not explicitly specified this view are important for accessibility.  if  (Emptyview! = null  && emptyview.getimportantforaccessibility () = = Important_for_accessibility_auto) {emptyview.setimportantforaccessibility (important_for_accessibility_yes); } final  T adapter = Getadapter (); final  boolean  empty = ((adapter = = null ) | | Adapter.isempty ()); Updateemptystatus (empty); }

Continue to follow the codeupdateEmptyStatus

Private void Updateemptystatus(BooleanEmpty) {if(Isinfiltermode ()) {empty =false; }if(empty) {if(Memptyview! =NULL) {memptyview.setvisibility (view.visible);        Setvisibility (View.gone); }Else{//If The caller just removed our empty view, make sure the list view is visibleSetvisibility (view.visible); }//We are now GONE, so pending layouts would not be dispatched.        // Force One, here, make sure, the state of the list matches        // The state of the adapter.        if(mdatachanged) { This. OnLayout (false, Mleft, Mtop, Mright, Mbottom); }    }Else{if(Memptyview! =NULL) memptyview.setvisibility (View.gone);    Setvisibility (view.visible); }}

Alas, there is nothing, look at the code 31~37 line, is based on whether the data is empty, to control the display Memptyview and the ListView itself.
Since the principle is simple, then we can fully implement one ourselves. However, our principle is exactly the opposite of that of the ListView:

The ListView is implemented by binding a Emptyview
We do this by Emptyview binding the ListView (other view also OK).
Our emptyview provides a common way to load in-time reminders during load, load failure reminders loading fails, and provides a button for user refresh to use.

After the analysis, the next is the code, first we inherit one RelativeLayout to achieve such a layout:

publicclass EmptyView extends RelativeLayout {    private String mText;    private String mLoadingText;    private TextView mTextView;    private Button mButton;  private View mBindView;...}

Simply say the effect of the 4 variables.
mTextThe text that represents the reminder when the data is empty.
mLoadingTextRepresents the text of a reminder in the load.
mTextViewDisplays the reminder text.
mButtonProvides a button for the user to refresh.
mBindViewWe want to bind the view.

OK, continue the code:

public  class  emptyview  extends  relativelayout  { ... public  emptyview  (context context, AttributeSet attrs) {super  (context, attrs); TypedArray ta = context.obtainstyledattributes (attrs, R.styleable.emptyview, 0 ,        Span class= "Hljs-number" >0 );        String Text = ta.getstring (r.styleable.emptyview_android_text);        String ButtonText = ta.getstring (R.styleable.emptyview_buttontext);        Mloadingtext = ta.getstring (R.styleable.emptyview_loadingtext);        Ta.recycle ();    Init (text, buttontext); }...}

For the sake of flexibility, these textual content we define can be used in the xml configuration, eh? Why is there a buttontext, this of course is the text on the button.
Continue with the code, and you can see that the method is called init .
Take a look at:

 Public  class emptyview extends relativelayout {...Private void Init(string text, String buttontext) {if(Textutils.isempty (text)) Text ="No Data";if(Textutils.isempty (buttontext)) ButtonText ="Retry";if(Textutils.isempty (mloadingtext)) Mloadingtext ="Loading in ...";        MText = text; Mtextview =NewTextView (GetContext ());        Mtextview.settext (text); Layoutparams Textviewparams =NewLayoutparams (Layoutparams.wrap_content, layoutparams.wrap_content);        Textviewparams.addrule (relativelayout.center_in_parent);        Mtextview.setid (R.id.id_empty_text);        AddView (Mtextview, textviewparams); Mbutton =NewButton (GetContext ());        Mbutton.settext (ButtonText); Layoutparams Buttonparams =NewLayoutparams (Layoutparams.wrap_content, layoutparams.wrap_content);        Buttonparams.addrule (relativelayout.center_horizontal);        Buttonparams.addrule (Relativelayout.below, R.id.id_empty_text);    AddView (Mbutton, buttonparams); }    ...}

In the init method, come up, we go to determine whether the text is empty, if it is empty, provide the default text. The next new one TextView Button is added to the control, TextView and Button is arranged up and down. At this point, the layout has been completed, how to control it? What effect do we want?

The method is called when the data is loaded loading , displaying the text that is being loaded.
When the data is loaded into, hide the view.
When the data load fails, the load fails to display the text, and a button is provided to refresh the data.

OK, we follow the entry of each one to achieve, the first is loading .

publicclass EmptyView extends RelativeLayout {    ...    publicvoidloading() {    ifnull) mBindView.setVisibility(View.GONE);        setVisibility(View.VISIBLE);        mButton.setVisibility(View.INVISIBLE);        mTextView.setText(mLoadingText);    }    ...}

loadingThe method is simple, first to determine mBindView whether it is empty, to hide it, and then to make the control visible and continue to Button be invisible, because we do not allow clicks to occur when loading. Finally, let's TextView show the text that is loading.
Keep looking at the method of loading success, this is even easier.

publicclass EmptyView extends RelativeLayout {    ...    publicvoidsuccess() {        setVisibility(View.GONE);    ifnull) mBindView.setVisibility(View.VISIBLE);    }    ...}

There are only two lines of code that let the control hide so that the bound view is displayed.
So the load failed? Same simple!

publicclass EmptyView extends RelativeLayout {    ...    publicvoidempty() {    ifnull) mBindView.setVisibility(View.GONE);        setVisibility(View.VISIBLE);        mButton.setVisibility(View.VISIBLE);        mTextView.setText(mText);    }    ...}

Not much to say, the only thing to note is that we let Button the show.
At this point, our entire effect is completed, when loading the data call loading method to display the loaded text, loading failed, call empty to display the loading failed text and refresh the button, after the successful loading directly hide the control!
The control is done, and we don't know mBindView how to get it, but it's also very simple. We need to invoke the method in the code bindView(View view) to specify.

publicclass EmptyView extends RelativeLayout {    ...    publicvoidbindView(View view) {        mBindView = view;    }    ...}

Haha, the last question left, what do button click events do? Do you want to add an event when you use it onClick ? Hey, that's too much trouble, you know, I have a lot of files to change, I hope a line of code can be done!

Highlights have come:

 Public  class emptyview extends relativelayout {... Public void ButtonClick(FinalObject Base,FinalString method,FinalObject ... parameters) {Mbutton.setonclicklistener (NewOnclicklistener () { Public void OnClick(View v) {intlength = Parameters.length; class<?>[] Paramstypes =Newclass<?>[length]; for(inti =0; i < length;                i++) {Paramstypes[i] = Parameters[i].getclass (); }Try{Method M = Base.getclass (). Getdeclaredmethod (method, paramstypes); M.setaccessible (true);                M.invoke (base, parameters); }Catch(Exception e)                {E.printstacktrace ();    }            }        }); }    ...}

Using reflection to do this, we just need to specify which method on which object to invoke, and then pass in the parameter if required.
This code briefly, first we set a click event for the button, in response to the event, the first step through the parameters, get the type of the parameter. Then the method is reflected according to the method name, and finally invoke executes directly. This makes it very convenient for us to use and accomplish our 一行代码搞定 goal.
So excited, let's test it out:
Look at the xml layout first.

<relativelayout xmlns:android="Http://schemas.android.com/apk/res/android" xmlns:tools= "http://schemas.android.com/tools"android:layout_width="Match_ Parent "android:layout_height="match_parent "tools:context=". Mainactivity ">                    <loader.org.emptyview.EmptyViewandroid:id="@+id/empty_view"android: Layout_width="Match_parent"android:layout_height="match_parent"/>                            <TextViewandroid:id= "@+id/name"android:layout_width=" Match_parent "android:layout_height=" wrap_content "/>                        </relativelayout>

Instead of using one, we'll ListView TextView look at how it's Activity called in:

 Public  class mainactivity extends appcompatactivity {    PrivateEmptyview Memptyview;PrivateTextView Mtextview;@Override    protected void onCreate(Bundle savedinstancestate) {Super. OnCreate (Savedinstancestate);        Setcontentview (R.layout.activity_main);        Memptyview = (Emptyview) Findviewbyid (R.id.empty_view);        Mtextview = (TextView) Findviewbyid (r.id.name); Memptyview.bindview (Mtextview);//Set BindViewMemptyview.buttonclick ( This,"LoadData");//What method to invoke when button is clickedLoadData (); }/** * Load data * /    Private void LoadData() {memptyview.loading ();//Load in        //2s results        NewHandler (). postdelayed (NewRunnable () {@Override             Public void Run() {Random r =NewRandom ();intres = R.nextint (2);//Failure                if(res = =0) {memptyview.empty ();//Display failed}Else{//SuccessMemptyview.success (); Mtextview.settext ("Success"); }            }        }, -); }}

First, we're mEmptyView.bindView(mTextView) going to set it up to bind view , of course it is TextView .
Next, by mEmptyView.buttonClick(this, "loadData") Setting the button click on which method to execute, here is the method on the current object loadData , and no parameters.
In the getData analog delay after 2s to obtain data, the success of the data failure is random, when failed, call empty method, after successful call success method.
Haha, it is that simple, to see the effect of the code:


ok~ok~, very perfect.

Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.

Android to create a different Emptyview

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.