ListView grouping and letter index navigation in android (2) reconstruction-Interface

Source: Internet
Author: User

ListView grouping and letter index navigation in android (2) reconstruction-Interface

In the previous article, we analyzed the implementation ideas of listView grouping and letter index navigation, and implemented them step by step based on the ideas. At last, we have successfully implemented all the functions. However, after careful research, we will find that the implementation is not good enough. The main problems are as follows:

1. For a widely used layout, the above implementation is not general enough. In particular, some extra fields need to be added to Bo, and these word fields do not make sense.

2. The code is incorporated into the activity.

Perform code Refactoring for the above two points. First, we optimize it into a general activity. This makes it easy to make a general View. Then we extract and refactor the code.

Thoughts and ideas

In the past, a major problem with the code was "contaminated" the original Bo, and the main cause of the pollution was to use these additional fields for data processing and generating List Group tags.

The original code is as follows:

Public class TestBo {/*** main field */private String boStr = null;/*** bo pinyin cache */private String boPinYin = null; /*** Bo tag */private String boTagFlag = null; public TestBo () {super ();} public TestBo (String str) {super (); this. boStr = str;} public String getBoStr () {return boStr;} public void setBoStr (String boStr) {this. boStr = boStr;} public String getSortStrPinyin () {return boPinYin;} public void setSortStrPinYin (String pinyin) {this. boPinYin = pinyin;} public void setTag (String tag) {this. boTagFlag = tag;} public String getTag () {return boTagFlag ;}}


In fact, the main fields that are useful in the above Bo are all additional fields. In fact, to generate a list, you only need to group the fields that the Bo provides.

Naturally, we thought of the interface. As long as the corresponding interface is implemented, the interface method should return the value of "group sorting ".

Data processing can be changed accordingly.

Rebuilding BO-Interface

First, extract the following interfaces:

Public interface BoSort {/*** @ date 2014-9-3 * @ Description: The index String * @ param * @ return String */public String getSortStr (); /*** @ date 2014-9-3 * @ Description: Obtain the pinyin alphabet of the index String. It is best to cache * @ param * @ return String */public String getSortStrPinyin (); /*** @ date 2014-9-3 * @ Description: * @ param * @ return void */public void setSortStrPinYin (String pinyin);/*** @ date 2014-9-3 * @ Description: to set a tag, You Need To Cache * @ param * @ return void */public void setTag (String tag);/*** @ date 2014-9-3 * @ Description: Get the tag. If it is null, it is not the tag * @ param * @ return String */public String getTag ();}


The corresponding Bo can implement the above interface. However, we can provide a default implementation, which is still an abstract class. Bo only needs to inherit this default implementation and implement it as the implementation method. PublicString getSortStr ();

/*** @ Date 2014-9-3 * @ Description: you only need to implement getSortStr. Do not modify */public abstract class defaultbosoribd implements BoSort {/*** bo pinyin cache */private String boPinYin = null; /*** Bo tag */private String boTagFlag = null;/*** be sure to have this constructor */public defaultbosoribd () {super ();} @ Override public String getSortStrPinyin () {return boPinYin;} @ Override public void setSortStrPinYin (String pinyin) {this. boPinYin = pinyin;} @ Override public void setTag (String tag) {this. boTagFlag = tag ;}@ Override public String getTag () {return boTagFlag ;}}

Data Processing

The overall implementation process is similar to before, and the data processing process changes slightly. We separate data processing into a class. In the process of processing, we can see that reflection is used when generating group tags, and this data processing only depends on the interface, rather than the specific Bo, reduced coupling.

Public class RulerUtil {/*** list adaptation ?? */Public static final String [] indexStr = {"#", "A", "B", "C", "D", "E", "F ", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P ", "Q", "R", "S", "T", "U", "V", "W", "X", "Y ", "Z"}; public static final char [] letters = {'A', 'B', 'C', 'D', 'E', 'F ', 'G', 'h', 'I', 'J', 'k', 'l', 'M', 'n', 'O', 'P ', 'Q', 'R', 's', 't', 'U', 'V', 'w', 'x', 'y ', 'Z'};/*** @ throws IllegalAccessException * @ throws InstantiationException * @ return returns processed data * @ Description: process data, sort, add tags */public static ArrayList
 
  
GenSortedDataAndTagLocation (List
  MyData, HashMap
  
   
TagLocation) throws InstantiationException, IllegalAccessException {ArrayList
   
    
Res = new ArrayList
    
     
(); Res. addAll (myData); // first sort Collections. sort (res, new Comparator
     
      
() {@ Override public int compare (BoSort lhs, BoSort rhs) {char firChar = checkAndGetPinyin (lhs); char secChar = checkAndGetPinyin (rhs); if (firChar <secChar) {return-1;} else if (firChar> secChar) {return 1 ;}else return 0 ;}); int size = res. size (); int I = 0; char nowTag = '\ 0'; for (I = 0; I <size; I ++) {BoSort temp = res. get (I); char tempTag = checkAndGetPinyin (temp); if (Arrays. bin ArySearch (letters, tempTag) <0) {tempTag = '#';} if (nowTag! = TempTag) {// reflection generates the label Class
      BoClass = temp. getClass (); BoSort tagBO = boClass. newInstance (); tagBO. setTag (tempTag + ""); res. add (I, tagBO); tagLocation. put (tempTag + "", I); I ++; size ++; nowTag = tempTag ;}} tagLocation. put ("#", 0); return res;} private static char checkAndGetPinyin (BoSort bo) {String pinyinStr = bo. getSortStrPinyin (); if (pinyinStr = null) {bo. setSortStrPinYin (HanziToPinyin. getPinYin (bo. getSortStr ()). toUpper Case (); pinyinStr = bo. getSortStrPinyin ();} if (pinyinStr! = Null & pinyinStr. length ()> = 1) {return pinyinStr. charAt (0) ;}return '\ 0 ';}}
     
    
   
  
 

Adaptor implementation

The implementation of Adptor is the same as before, but the adaptor only depends on the interface and does not depend on the specific Bo.

Activity Reconstruction

Construct a general abstract activity. If you need grouping and navigation, you only need to inherit and implement the return data method.

First, extract the letter index on the right to make a View.

1. RulerWidget

A separate View can be used directly in the xml layout.


/*** @ Description: The ruler navigation on the right. You need to call the setOnRulerTouch method to set the callback interface */public class RulerWidget extends LinearLayout {private static final int INDEX_LENGTH = RulerUtil. indexStr. length; public RulerWidget (Context context) {super (context); init ();} public RulerWidget (Context context, AttributeSet attrs) {super (context, attrs ); init ();} public RulerWidget (Context context, AttributeSet attrs, int defStyle) {su Per (context, attrs, defStyle); init ();} private void init () {int color = getResources (). getColor (R. color. g_ruler_letter_color); LinearLayout. layoutParams params = new LinearLayout. layoutParams (LayoutParams. WRAP_CONTENT, LayoutParams. WRAP_CONTENT); params. gravity = Gravity. CENTER_HORIZONTAL; this. bringToFront (); params. weight = 1; for (int I = 0; I <RulerUtil. indexStr. length; I ++) {final TextVie W TV = new TextView (getContext (); TV. setLayoutParams (params); TV. setTextColor (color); TV. setGravity (Gravity. CENTER); TV. setText (RulerUtil. indexStr [I]); this. addView (TV);} this. setOnTouchListener (new OnTouchListener () {@ Override public boolean onTouch (View v, MotionEvent event) {int height = v. getHeight (); float pos = event. getY (); int sectionPosition = (int) (pos/height)/(1f/INDEX_LENGTH ); If (sectionPosition <0) {sectionPosition = 0;} else if (sectionPosition> INDEX_LENGTH-1) {sectionPosition = INDEX_LENGTH-1;} switch (event. getAction () {case MotionEvent. ACTION_DOWN: if (onRulerTouch! = Null) {onRulerTouch. onDown (sectionPosition);} RulerWidget. this. setBackgroundResource (R. color. g_ruler_selected); break; case MotionEvent. ACTION_MOVE: if (onRulerTouch! = Null) {onRulerTouch. onMove (sectionPosition);} break; default: if (onRulerTouch! = Null) {onRulerTouch. onOthers ();} RulerWidget. this. setBackgroundResource (R. color. g_blank) ;}return true ;}}) ;}/ *** callback */private OnRulerTouch onRulerTouch; public void setOnRulerTouch (OnRulerTouch onRulerTouch) {this. onRulerTouch = onRulerTouch;}/*** @ date 2014-9-3 * @ Description: ruler touch callback */public interface OnRulerTouch {public void onDown (int position ); public void onMove (int position); public void onUP (); public void onOthers ();}

2. Activity

An abstract activity. The layout is similar to the previous one. Not pasted.

/*** @ Date 2014-9-3 * @ Description: The method to obtain data * public abstract List
 GetDataList (); */public abstract class RulerActivity extends Activity {protected TextView progress; protected preview SS; protected ListView; protected RulerWidget rwidget; private ruladapter erruleradapter private List;
 OriginalList; private List
 
  
DealedList; private HashMap
  
   
TagLocation = new HashMap
   
    
();/*****/@ Override protected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. g_rie); findView (); initView (); initData ();} private void findView () {noDataView = (TextView) findViewById (R. id. g_base_list_nodata); RulerTag = (TextView) findViewById (R. id. g_ruler_tag); progress = (ProgressBarWithText) findViewById (R. id. g_base_progressbar_withtext); listView = (ListView) findViewById (R. id. g_base_list); rbytes = (RulerWidget) findViewById (R. id. g_rview);} private void initView () {progress. setVisibility (View. VISIBLE); RulerTag. setVisibility (View. GONE); noDataView. setVisibility (View. GONE); listView. setVisibility (View. GONE); rloud. setVisibility (View. GONE);} private void initData () {new getdataasytask(cmd.exe cute ();}/*** @ date 2014-9-4 * @ Description: you need to implement this method to obtain data * @ param * @ return List
    */Public abstract List
    GetDataList ();/*** @ date 2014-9-3 * @ Description: * @ param * @ return void */private void handleSuccessData () {listView. setVisibility (View. VISIBLE); rible. setVisibility (View. VISIBLE); rulerAdapter = new RulerAdapter (dealedList, this); rible. setOnRulerTouch (new OnRulerTouch () {@ Override public void onUP () {}@ Override public void onOthers () {RulerTag. setVisibility (View. GONE) ;}@ Override publi C void onMove (int position) {RulerTag. setText (RulerUtil. indexStr [position]); listView. setSelection (getPosition (position);} @ Override public void onDown (int position) {RulerTag. setVisibility (View. VISIBLE); RulerTag. setText (RulerUtil. indexStr [position]); listView. setSelection (getPosition (position) ;}}); listView. setAdapter (rulerAdapter); rulerAdapter. notifyDataSetChanged ();}/*** @ Descriptio N: the position where the list is to be rolled when the touch letter navigation is obtained. If the touch letter is not saved in the tag tagLocation ing, search for it. */Private Integer getPosition (final int j) {Integer pos = null; int I = j; while (pos = null & I <= RulerUtil. indexStr. length-1) {pos = tagLocation. get (RulerUtil. indexStr [I]); I ++;} if (pos = null) {pos = dealedList. size ()-1;} return pos;} class GetDataAsyTask extends AsyncTask
    
     
{@ Override protected void onPreExecute () {super. onPreExecute (); progress. setVisibility (View. VISIBLE) ;}@ Override protected Void doInBackground (Void... params) {originalList = getDataList (); try {dealedList = RulerUtil. genSortedDataAndTagLocation (originalList, tagLocation);} catch (Exception e) {e. printStackTrace (); if (dealedList! = Null) {dealedList. clear (); dealedList = null;} if (originalList! = Null) {originalList. clear (); originalList = null;} if (tagLocation! = Null) {tagLocation. clear (); tagLocation = null ;}} return null ;}@ Override protected void onPostExecute (Void result) {progress. setVisibility (View. GONE); super. onPostExecute (result); if (dealedList = null) {noDataView. setVisibility (View. VISIBLE); return;} handleSuccessData ();}}}
    
   
  
 

Now the reconstruction is complete.

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.