├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bigkoo │ │ └── quicksidebardemo │ │ ├── CityListAdapter.java │ │ ├── DividerDecoration.java │ │ ├── MainActivity.java │ │ ├── constants │ │ └── DataConstants.java │ │ └── model │ │ └── City.java │ └── res │ ├── layout │ ├── activity_main.xml │ ├── view_header.xml │ └── view_item.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── preview └── quicksidebardemo.gif ├── quicksidebar ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── bigkoo │ │ └── quicksidebar │ │ ├── QuickSideBarTipsView.java │ │ ├── QuickSideBarView.java │ │ ├── listener │ │ └── OnQuickSideBarTouchListener.java │ │ └── tipsview │ │ └── QuickSideBarTipsItemView.java │ └── res │ └── values │ ├── array.xml │ ├── attrs.xml │ └── dimen.xml └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | # built application files 2 | *.apk 3 | *.ap_ 4 | 5 | # files for the dex VM 6 | *.dex 7 | 8 | # Java class files 9 | *.class 10 | 11 | # generated files 12 | bin/ 13 | gen/ 14 | 15 | # Local configuration file (sdk path, etc) 16 | local.properties 17 | 18 | # Eclipse project files 19 | .classpath 20 | .project 21 | 22 | # Android Studio 23 | .idea/ 24 | .gradle 25 | /*/local.properties 26 | /*/out 27 | build 28 | /*/*/production 29 | *.iml 30 | *.iws 31 | *.ipr 32 | *~ 33 | *.swp 34 | # built application files 35 | *.apk 36 | *.ap_ 37 | 38 | # files for the dex VM 39 | *.dex 40 | 41 | # Java class files 42 | *.class 43 | 44 | # generated files 45 | bin/ 46 | gen/ 47 | 48 | # Local configuration file (sdk path, etc) 49 | local.properties 50 | 51 | # Eclipse project files 52 | .classpath 53 | .project 54 | 55 | # Android Studio 56 | .idea/ 57 | .gradle 58 | /*/local.properties 59 | /*/out 60 | build 61 | /*/*/production 62 | *.iml 63 | *.iws 64 | *.ipr 65 | *~ 66 | *.swp 67 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Android-QuickSideBar 2 | ========== 3 | 帮助快速查阅对应分组的侧边栏,可以配合任意列表,demo中给出配合RecyclerView(浮动分组使用stickyheadersrecyclerview)。 4 | 5 | #### 使用gradle 依赖: 6 | ```java 7 | compile 'com.bigkoo:quicksidebar:1.0.3' 8 | ``` 9 | 10 | ## Demo 图片 11 | ![](https://github.com/saiwu-bigkoo/Android-QuickSideBar/blob/master/preview/quicksidebardemo.gif) 12 | 13 | ##### Config in xml 14 | 15 | ```xml 16 | 17 | 21 | 22 | 26 | 27 | 28 | 29 | 30 | 31 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 57 | 58 | ``` 59 | 60 | ##### config in java code 61 | 62 | ```java 63 | //联动请看 64 | OnQuickSideBarTouchListener 65 | ``` 66 | >## 更新说明 67 | >v1.0.3 68 | - 宽高计算使用Measured
69 | - 修复默认的字母表写错字母问题
70 | 71 | >v1.0.2 72 | - 修复选择字母与实际手指触碰错位问题
73 | - 字母表由item平均高度变为固定高度并居中
74 | 75 | >v1.0.1 76 | - 解决属性和其他开源库冲突问题
77 | 78 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 23 5 | buildToolsVersion "23.0.2" 6 | 7 | defaultConfig { 8 | applicationId "com.bigkoo.quicksidebardemo" 9 | minSdkVersion 14 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | lintOptions { 21 | abortOnError false 22 | } 23 | 24 | } 25 | 26 | dependencies { 27 | compile fileTree(dir: 'libs', include: ['*.jar']) 28 | compile 'com.android.support:appcompat-v7:23.2.0' 29 | compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4' 30 | //recyclerview分组,顶部浮动 31 | compile 'com.timehop.stickyheadersrecyclerview:library:0.4.3@aar' 32 | compile 'com.android.support:recyclerview-v7:23.2.0' 33 | compile project(':quicksidebar') 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/soyoung/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/quicksidebardemo/CityListAdapter.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebardemo; 2 | 3 | import android.support.v7.widget.RecyclerView; 4 | 5 | import com.bigkoo.quicksidebardemo.model.City; 6 | 7 | import java.util.ArrayList; 8 | import java.util.Arrays; 9 | import java.util.Collection; 10 | 11 | 12 | /** 13 | * Adapter holding a list of animal names of type String. Note that each item must be unique. 14 | */ 15 | public abstract class CityListAdapter 16 | extends RecyclerView.Adapter { 17 | private ArrayList items = new ArrayList(); 18 | 19 | public CityListAdapter() { 20 | setHasStableIds(true); 21 | } 22 | 23 | public void add(City object) { 24 | items.add(object); 25 | notifyDataSetChanged(); 26 | } 27 | 28 | public void add(int index, City object) { 29 | items.add(index, object); 30 | notifyDataSetChanged(); 31 | } 32 | 33 | public void addAll(Collection collection) { 34 | if (collection != null) { 35 | items.addAll(collection); 36 | notifyDataSetChanged(); 37 | } 38 | } 39 | 40 | public void addAll(City... items) { 41 | addAll(Arrays.asList(items)); 42 | } 43 | 44 | public void clear() { 45 | items.clear(); 46 | notifyDataSetChanged(); 47 | } 48 | 49 | public void remove(String object) { 50 | items.remove(object); 51 | notifyDataSetChanged(); 52 | } 53 | 54 | public City getItem(int position) { 55 | return items.get(position); 56 | } 57 | 58 | @Override 59 | public long getItemId(int position) { 60 | return getItem(position).hashCode(); 61 | } 62 | 63 | @Override 64 | public int getItemCount() { 65 | return items.size(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/quicksidebardemo/DividerDecoration.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebardemo; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Rect; 7 | import android.graphics.drawable.Drawable; 8 | import android.support.v7.widget.LinearLayoutManager; 9 | import android.support.v7.widget.RecyclerView; 10 | import android.view.View; 11 | 12 | /** 13 | * RecyclerView分割条 14 | */ 15 | public class DividerDecoration extends RecyclerView.ItemDecoration { 16 | 17 | private static final int[] ATTRS = new int[]{ 18 | android.R.attr.listDivider 19 | }; 20 | 21 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; 22 | 23 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; 24 | 25 | private Drawable mDivider; 26 | 27 | public DividerDecoration(Context context) { 28 | final TypedArray a = context.obtainStyledAttributes(ATTRS); 29 | mDivider = a.getDrawable(0); 30 | a.recycle(); 31 | } 32 | 33 | private int getOrientation(RecyclerView parent) { 34 | LinearLayoutManager layoutManager; 35 | try { 36 | layoutManager = (LinearLayoutManager) parent.getLayoutManager(); 37 | } catch (ClassCastException e) { 38 | throw new IllegalStateException("DividerDecoration can only be used with a " + 39 | "LinearLayoutManager.", e); 40 | } 41 | return layoutManager.getOrientation(); 42 | } 43 | 44 | @Override 45 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { 46 | super.onDraw(c, parent, state); 47 | 48 | if (getOrientation(parent) == VERTICAL_LIST) { 49 | drawVertical(c, parent); 50 | } else { 51 | drawHorizontal(c, parent); 52 | } 53 | } 54 | 55 | public void drawVertical(Canvas c, RecyclerView parent) { 56 | final int left = parent.getPaddingLeft(); 57 | final int right = parent.getWidth() - parent.getPaddingRight(); 58 | final int recyclerViewTop = parent.getPaddingTop(); 59 | final int recyclerViewBottom = parent.getHeight() - parent.getPaddingBottom(); 60 | final int childCount = parent.getChildCount(); 61 | for (int i = 0; i < childCount; i++) { 62 | final View child = parent.getChildAt(i); 63 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 64 | .getLayoutParams(); 65 | final int top = Math.max(recyclerViewTop, child.getBottom() + params.bottomMargin); 66 | final int bottom = Math.min(recyclerViewBottom, top + mDivider.getIntrinsicHeight()); 67 | mDivider.setBounds(left, top, right, bottom); 68 | mDivider.draw(c); 69 | } 70 | } 71 | 72 | public void drawHorizontal(Canvas c, RecyclerView parent) { 73 | final int top = parent.getPaddingTop(); 74 | final int bottom = parent.getHeight() - parent.getPaddingBottom(); 75 | final int recyclerViewLeft = parent.getPaddingLeft(); 76 | final int recyclerViewRight = parent.getWidth() - parent.getPaddingRight(); 77 | final int childCount = parent.getChildCount(); 78 | for (int i = 0; i < childCount; i++) { 79 | final View child = parent.getChildAt(i); 80 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child 81 | .getLayoutParams(); 82 | final int left = Math.max(recyclerViewLeft, child.getRight() + params.rightMargin); 83 | final int right = Math.min(recyclerViewRight, left + mDivider.getIntrinsicHeight()); 84 | mDivider.setBounds(left, top, right, bottom); 85 | mDivider.draw(c); 86 | } 87 | } 88 | 89 | @Override 90 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { 91 | super.getItemOffsets(outRect, view, parent, state); 92 | if (getOrientation(parent) == VERTICAL_LIST) { 93 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); 94 | } else { 95 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); 96 | } 97 | } 98 | } -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/quicksidebardemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebardemo; 2 | 3 | import android.graphics.Color; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.os.Bundle; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.view.LayoutInflater; 9 | import android.view.View; 10 | import android.view.ViewGroup; 11 | import android.widget.TextView; 12 | 13 | import com.bigkoo.quicksidebar.QuickSideBarTipsView; 14 | import com.bigkoo.quicksidebar.QuickSideBarView; 15 | import com.bigkoo.quicksidebar.listener.OnQuickSideBarTouchListener; 16 | import com.bigkoo.quicksidebardemo.constants.DataConstants; 17 | import com.bigkoo.quicksidebardemo.model.City; 18 | import com.google.gson.Gson; 19 | import com.google.gson.reflect.TypeToken; 20 | import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersAdapter; 21 | import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; 22 | 23 | import java.lang.reflect.Type; 24 | import java.security.SecureRandom; 25 | import java.util.ArrayList; 26 | import java.util.Arrays; 27 | import java.util.HashMap; 28 | import java.util.LinkedList; 29 | 30 | public class MainActivity extends AppCompatActivity implements OnQuickSideBarTouchListener { 31 | RecyclerView recyclerView; 32 | HashMap letters = new HashMap<>(); 33 | QuickSideBarView quickSideBarView; 34 | QuickSideBarTipsView quickSideBarTipsView; 35 | @Override 36 | protected void onCreate(Bundle savedInstanceState) { 37 | super.onCreate(savedInstanceState); 38 | setContentView(R.layout.activity_main); 39 | recyclerView = (RecyclerView) findViewById(R.id.recyclerView); 40 | quickSideBarView = (QuickSideBarView) findViewById(R.id.quickSideBarView); 41 | quickSideBarTipsView = (QuickSideBarTipsView) findViewById(R.id.quickSideBarTipsView); 42 | 43 | //设置监听 44 | quickSideBarView.setOnQuickSideBarTouchListener(this); 45 | 46 | 47 | //设置列表数据和浮动header 48 | final LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); 49 | recyclerView.setLayoutManager(layoutManager); 50 | 51 | // Add the sticky headers decoration 52 | CityListWithHeadersAdapter adapter = new CityListWithHeadersAdapter(); 53 | 54 | //GSON解释出来 55 | Type listType = new TypeToken>(){}.getType(); 56 | Gson gson = new Gson(); 57 | LinkedList cities = gson.fromJson(DataConstants.cityDataList, listType); 58 | 59 | ArrayList customLetters = new ArrayList<>(); 60 | 61 | int position = 0; 62 | for(City city: cities){ 63 | String letter = city.getFirstLetter(); 64 | //如果没有这个key则加入并把位置也加入 65 | if(!letters.containsKey(letter)){ 66 | letters.put(letter,position); 67 | customLetters.add(letter); 68 | } 69 | position++; 70 | } 71 | 72 | //不自定义则默认26个字母 73 | quickSideBarView.setLetters(customLetters); 74 | adapter.addAll(cities); 75 | recyclerView.setAdapter(adapter); 76 | 77 | final StickyRecyclerHeadersDecoration headersDecor = new StickyRecyclerHeadersDecoration(adapter); 78 | recyclerView.addItemDecoration(headersDecor); 79 | 80 | // Add decoration for dividers between list items 81 | recyclerView.addItemDecoration(new DividerDecoration(this)); 82 | } 83 | 84 | 85 | @Override 86 | public void onLetterChanged(String letter, int position, float y) { 87 | quickSideBarTipsView.setText(letter, position, y); 88 | //有此key则获取位置并滚动到该位置 89 | if(letters.containsKey(letter)) { 90 | recyclerView.scrollToPosition(letters.get(letter)); 91 | } 92 | } 93 | 94 | @Override 95 | public void onLetterTouching(boolean touching) { 96 | //可以自己加入动画效果渐显渐隐 97 | quickSideBarTipsView.setVisibility(touching? View.VISIBLE:View.INVISIBLE); 98 | } 99 | 100 | private class CityListWithHeadersAdapter extends CityListAdapter 101 | implements StickyRecyclerHeadersAdapter { 102 | @Override 103 | public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 104 | View view = LayoutInflater.from(parent.getContext()) 105 | .inflate(R.layout.view_item, parent, false); 106 | return new RecyclerView.ViewHolder(view) { 107 | }; 108 | } 109 | 110 | @Override 111 | public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { 112 | TextView textView = (TextView) holder.itemView; 113 | textView.setText(getItem(position).getCityName()); 114 | } 115 | 116 | @Override 117 | public long getHeaderId(int position) { 118 | return getItem(position).getFirstLetter().charAt(0); 119 | } 120 | 121 | @Override 122 | public RecyclerView.ViewHolder onCreateHeaderViewHolder(ViewGroup parent) { 123 | View view = LayoutInflater.from(parent.getContext()) 124 | .inflate(R.layout.view_header, parent, false); 125 | return new RecyclerView.ViewHolder(view) { 126 | }; 127 | } 128 | 129 | @Override 130 | public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder, int position) { 131 | TextView textView = (TextView) holder.itemView; 132 | textView.setText(String.valueOf(getItem(position).getFirstLetter())); 133 | holder.itemView.setBackgroundColor(getRandomColor()); 134 | } 135 | 136 | private int getRandomColor() { 137 | SecureRandom rgen = new SecureRandom(); 138 | return Color.HSVToColor(150, new float[]{ 139 | rgen.nextInt(359), 1, 1 140 | }); 141 | } 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/quicksidebardemo/constants/DataConstants.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebardemo.constants; 2 | 3 | /** 4 | * Created by Sai on 16/3/25. 5 | */ 6 | public class DataConstants { 7 | public static final String cityDataList = "[{\"cityName\":\"广州\",\"firstLetter\":\"☆\"},{\"cityName\":\"北京\",\"firstLetter\":\"☆\"},{\"cityName\":\"河源\",\"firstLetter\":\"☆\"},{\"cityName\":\"襄阳\",\"firstLetter\":\"☆\"},{\"cityName\":\"上海\",\"firstLetter\":\"☆\"},{\"cityName\":\"深圳\",\"firstLetter\":\"☆\"},{\"cityName\":\"鞍山\",\"firstLetter\":\"A\"},{\"cityName\":\"安庆\",\"firstLetter\":\"A\"},{\"cityName\":\"安阳\",\"firstLetter\":\"A\"},{\"cityName\":\"阿坝\",\"firstLetter\":\"A\"},{\"cityName\":\"安顺\",\"firstLetter\":\"A\"},{\"cityName\":\"安康\",\"firstLetter\":\"A\"},{\"cityName\":\"阿里\",\"firstLetter\":\"A\"},{\"cityName\":\"阿勒泰\",\"firstLetter\":\"A\"},{\"cityName\":\"阿克苏\",\"firstLetter\":\"A\"},{\"cityName\":\"阿拉尔\",\"firstLetter\":\"A\"},{\"cityName\":\"阿拉善盟\",\"firstLetter\":\"A\"},{\"cityName\":\"澳门\",\"firstLetter\":\"A\"},{\"cityName\":\"北京\",\"firstLetter\":\"B\"},{\"cityName\":\"保定\",\"firstLetter\":\"B\"},{\"cityName\":\"本溪\",\"firstLetter\":\"B\"},{\"cityName\":\"白城\",\"firstLetter\":\"B\"},{\"cityName\":\"白山\",\"firstLetter\":\"B\"},{\"cityName\":\"蚌埠\",\"firstLetter\":\"B\"},{\"cityName\":\"亳州\",\"firstLetter\":\"B\"},{\"cityName\":\"滨州\",\"firstLetter\":\"B\"},{\"cityName\":\"白银\",\"firstLetter\":\"B\"},{\"cityName\":\"巴中\",\"firstLetter\":\"B\"},{\"cityName\":\"毕节\",\"firstLetter\":\"B\"},{\"cityName\":\"白沙\",\"firstLetter\":\"B\"},{\"cityName\":\"保亭\",\"firstLetter\":\"B\"},{\"cityName\":\"保山\",\"firstLetter\":\"B\"},{\"cityName\":\"宝鸡\",\"firstLetter\":\"B\"},{\"cityName\":\"百色\",\"firstLetter\":\"B\"},{\"cityName\":\"北海\",\"firstLetter\":\"B\"},{\"cityName\":\"博尔塔拉\",\"firstLetter\":\"B\"},{\"cityName\":\"巴音郭楞\",\"firstLetter\":\"B\"},{\"cityName\":\"包头\",\"firstLetter\":\"B\"},{\"cityName\":\"巴彦淖尔\",\"firstLetter\":\"B\"},{\"cityName\":\"重庆\",\"firstLetter\":\"C\"},{\"cityName\":\"承德\",\"firstLetter\":\"C\"},{\"cityName\":\"沧州\",\"firstLetter\":\"C\"},{\"cityName\":\"长治\",\"firstLetter\":\"C\"},{\"cityName\":\"朝阳\",\"firstLetter\":\"C\"},{\"cityName\":\"常州\",\"firstLetter\":\"C\"},{\"cityName\":\"滁州\",\"firstLetter\":\"C\"},{\"cityName\":\"巢湖\",\"firstLetter\":\"C\"},{\"cityName\":\"池州\",\"firstLetter\":\"C\"},{\"cityName\":\"长沙\",\"firstLetter\":\"C\"},{\"cityName\":\"郴州\",\"firstLetter\":\"C\"},{\"cityName\":\"常德\",\"firstLetter\":\"C\"},{\"cityName\":\"潮州\",\"firstLetter\":\"C\"},{\"cityName\":\"成都\",\"firstLetter\":\"C\"},{\"cityName\":\"澄迈\",\"firstLetter\":\"C\"},{\"cityName\":\"昌江\",\"firstLetter\":\"C\"},{\"cityName\":\"楚雄\",\"firstLetter\":\"C\"},{\"cityName\":\"崇左\",\"firstLetter\":\"C\"},{\"cityName\":\"昌都\",\"firstLetter\":\"C\"},{\"cityName\":\"昌吉\",\"firstLetter\":\"C\"},{\"cityName\":\"赤峰\",\"firstLetter\":\"C\"},{\"cityName\":\"大同\",\"firstLetter\":\"D\"},{\"cityName\":\"大连\",\"firstLetter\":\"D\"},{\"cityName\":\"丹东\",\"firstLetter\":\"D\"},{\"cityName\":\"大兴安岭\",\"firstLetter\":\"D\"},{\"cityName\":\"大庆\",\"firstLetter\":\"D\"},{\"cityName\":\"德州\",\"firstLetter\":\"D\"},{\"cityName\":\"东营\",\"firstLetter\":\"D\"},{\"cityName\":\"东营\",\"firstLetter\":\"D\"},{\"cityName\":\"东莞\",\"firstLetter\":\"D\"},{\"cityName\":\"定西\",\"firstLetter\":\"D\"},{\"cityName\":\"达州\",\"firstLetter\":\"D\"},{\"cityName\":\"德阳\",\"firstLetter\":\"D\"},{\"cityName\":\"儋州\",\"firstLetter\":\"D\"},{\"cityName\":\"东方\",\"firstLetter\":\"D\"},{\"cityName\":\"定安\",\"firstLetter\":\"D\"},{\"cityName\":\"德宏\",\"firstLetter\":\"D\"},{\"cityName\":\"大理\",\"firstLetter\":\"D\"},{\"cityName\":\"迪庆\",\"firstLetter\":\"D\"},{\"cityName\":\"鄂州\",\"firstLetter\":\"E\"},{\"cityName\":\"恩施\",\"firstLetter\":\"E\"},{\"cityName\":\"鄂尔多斯\",\"firstLetter\":\"E\"},{\"cityName\":\"抚顺\",\"firstLetter\":\"F\"},{\"cityName\":\"阜新\",\"firstLetter\":\"F\"},{\"cityName\":\"阜阳\",\"firstLetter\":\"F\"},{\"cityName\":\"福州\",\"firstLetter\":\"F\"},{\"cityName\":\"抚州\",\"firstLetter\":\"F\"},{\"cityName\":\"佛山\",\"firstLetter\":\"F\"},{\"cityName\":\"防城港\",\"firstLetter\":\"F\"},{\"cityName\":\"赣州\",\"firstLetter\":\"G\"},{\"cityName\":\"广州\",\"firstLetter\":\"G\"},{\"cityName\":\"甘南\",\"firstLetter\":\"G\"},{\"cityName\":\"广安\",\"firstLetter\":\"G\"},{\"cityName\":\"甘孜\",\"firstLetter\":\"G\"},{\"cityName\":\"广元\",\"firstLetter\":\"G\"},{\"cityName\":\"贵阳\",\"firstLetter\":\"G\"},{\"cityName\":\"果洛\",\"firstLetter\":\"G\"},{\"cityName\":\"桂林\",\"firstLetter\":\"G\"},{\"cityName\":\"贵港\",\"firstLetter\":\"G\"},{\"cityName\":\"固原\",\"firstLetter\":\"G\"},{\"cityName\":\"高雄\",\"firstLetter\":\"G\"},{\"cityName\":\"邯郸\",\"firstLetter\":\"H\"},{\"cityName\":\"衡水\",\"firstLetter\":\"H\"},{\"cityName\":\"葫芦岛\",\"firstLetter\":\"H\"},{\"cityName\":\"哈尔滨\",\"firstLetter\":\"H\"},{\"cityName\":\"鹤岗\",\"firstLetter\":\"H\"},{\"cityName\":\"黑河\",\"firstLetter\":\"H\"},{\"cityName\":\"淮安\",\"firstLetter\":\"H\"},{\"cityName\":\"杭州\",\"firstLetter\":\"H\"},{\"cityName\":\"湖州\",\"firstLetter\":\"H\"},{\"cityName\":\"合肥\",\"firstLetter\":\"H\"},{\"cityName\":\"淮南\",\"firstLetter\":\"H\"},{\"cityName\":\"淮北\",\"firstLetter\":\"H\"},{\"cityName\":\"黄山\",\"firstLetter\":\"H\"},{\"cityName\":\"菏泽\",\"firstLetter\":\"H\"},{\"cityName\":\"鹤壁\",\"firstLetter\":\"H\"},{\"cityName\":\"黄冈\",\"firstLetter\":\"H\"},{\"cityName\":\"黄石\",\"firstLetter\":\"H\"},{\"cityName\":\"衡阳\",\"firstLetter\":\"H\"},{\"cityName\":\"怀化\",\"firstLetter\":\"H\"},{\"cityName\":\"惠州\",\"firstLetter\":\"H\"},{\"cityName\":\"河源\",\"firstLetter\":\"H\"},{\"cityName\":\"海口\",\"firstLetter\":\"H\"},{\"cityName\":\"红河\",\"firstLetter\":\"H\"},{\"cityName\":\"海北\",\"firstLetter\":\"H\"},{\"cityName\":\"海东\",\"firstLetter\":\"H\"},{\"cityName\":\"黄南\",\"firstLetter\":\"H\"},{\"cityName\":\"海南\",\"firstLetter\":\"H\"},{\"cityName\":\"海西\",\"firstLetter\":\"H\"},{\"cityName\":\"汉中\",\"firstLetter\":\"H\"},{\"cityName\":\"贺州\",\"firstLetter\":\"H\"},{\"cityName\":\"河池\",\"firstLetter\":\"H\"},{\"cityName\":\"哈密\",\"firstLetter\":\"H\"},{\"cityName\":\"和田\",\"firstLetter\":\"H\"},{\"cityName\":\"呼伦贝尔\",\"firstLetter\":\"H\"},{\"cityName\":\"呼和浩特\",\"firstLetter\":\"H\"},{\"cityName\":\"晋中\",\"firstLetter\":\"J\"},{\"cityName\":\"晋城\",\"firstLetter\":\"J\"},{\"cityName\":\"锦州\",\"firstLetter\":\"J\"},{\"cityName\":\"吉林\",\"firstLetter\":\"J\"},{\"cityName\":\"鸡西\",\"firstLetter\":\"J\"},{\"cityName\":\"佳木斯\",\"firstLetter\":\"J\"},{\"cityName\":\"嘉兴\",\"firstLetter\":\"J\"},{\"cityName\":\"金华\",\"firstLetter\":\"J\"},{\"cityName\":\"九江\",\"firstLetter\":\"J\"},{\"cityName\":\"吉安\",\"firstLetter\":\"J\"},{\"cityName\":\"景德镇\",\"firstLetter\":\"J\"},{\"cityName\":\"济南\",\"firstLetter\":\"J\"},{\"cityName\":\"济宁\",\"firstLetter\":\"J\"},{\"cityName\":\"济源\",\"firstLetter\":\"J\"},{\"cityName\":\"焦作\",\"firstLetter\":\"J\"},{\"cityName\":\"荆州\",\"firstLetter\":\"J\"},{\"cityName\":\"荆门\",\"firstLetter\":\"J\"},{\"cityName\":\"揭阳\",\"firstLetter\":\"J\"},{\"cityName\":\"江门\",\"firstLetter\":\"J\"},{\"cityName\":\"金昌\",\"firstLetter\":\"J\"},{\"cityName\":\"嘉峪关\",\"firstLetter\":\"J\"},{\"cityName\":\"酒泉\",\"firstLetter\":\"J\"},{\"cityName\":\"基隆\",\"firstLetter\":\"J\"},{\"cityName\":\"嘉义\",\"firstLetter\":\"J\"},{\"cityName\":\"开封\",\"firstLetter\":\"K\"},{\"cityName\":\"昆明\",\"firstLetter\":\"K\"},{\"cityName\":\"克州\",\"firstLetter\":\"K\"},{\"cityName\":\"克拉玛依\",\"firstLetter\":\"K\"},{\"cityName\":\"喀什\",\"firstLetter\":\"K\"},{\"cityName\":\"廊坊\",\"firstLetter\":\"L\"},{\"cityName\":\"临汾\",\"firstLetter\":\"L\"},{\"cityName\":\"吕梁\",\"firstLetter\":\"L\"},{\"cityName\":\"辽阳\",\"firstLetter\":\"L\"},{\"cityName\":\"辽源\",\"firstLetter\":\"L\"},{\"cityName\":\"连云港\",\"firstLetter\":\"L\"},{\"cityName\":\"丽水\",\"firstLetter\":\"L\"},{\"cityName\":\"六安\",\"firstLetter\":\"L\"},{\"cityName\":\"龙岩\",\"firstLetter\":\"L\"},{\"cityName\":\"临沂\",\"firstLetter\":\"L\"},{\"cityName\":\"莱芜\",\"firstLetter\":\"L\"},{\"cityName\":\"聊城\",\"firstLetter\":\"L\"},{\"cityName\":\"洛阳\",\"firstLetter\":\"L\"},{\"cityName\":\"漯河\",\"firstLetter\":\"L\"},{\"cityName\":\"娄底\",\"firstLetter\":\"L\"},{\"cityName\":\"兰州\",\"firstLetter\":\"L\"},{\"cityName\":\"陇南\",\"firstLetter\":\"L\"},{\"cityName\":\"泸州\",\"firstLetter\":\"L\"},{\"cityName\":\"乐山\",\"firstLetter\":\"L\"},{\"cityName\":\"凉山\",\"firstLetter\":\"L\"},{\"cityName\":\"六盘水\",\"firstLetter\":\"L\"},{\"cityName\":\"临高\",\"firstLetter\":\"L\"},{\"cityName\":\"乐东\",\"firstLetter\":\"L\"},{\"cityName\":\"陵水\",\"firstLetter\":\"L\"},{\"cityName\":\"临沧\",\"firstLetter\":\"L\"},{\"cityName\":\"丽江\",\"firstLetter\":\"L\"},{\"cityName\":\"来宾\",\"firstLetter\":\"L\"},{\"cityName\":\"柳州\",\"firstLetter\":\"L\"},{\"cityName\":\"拉萨\",\"firstLetter\":\"L\"},{\"cityName\":\"林芝\",\"firstLetter\":\"L\"},{\"cityName\":\"牡丹江\",\"firstLetter\":\"M\"},{\"cityName\":\"马鞍山\",\"firstLetter\":\"M\"},{\"cityName\":\"茂名\",\"firstLetter\":\"M\"},{\"cityName\":\"梅州\",\"firstLetter\":\"M\"},{\"cityName\":\"绵阳\",\"firstLetter\":\"M\"},{\"cityName\":\"眉山\",\"firstLetter\":\"M\"},{\"cityName\":\"南京\",\"firstLetter\":\"N\"},{\"cityName\":\"南通\",\"firstLetter\":\"N\"},{\"cityName\":\"宁波\",\"firstLetter\":\"N\"},{\"cityName\":\"宁德\",\"firstLetter\":\"N\"},{\"cityName\":\"南平\",\"firstLetter\":\"N\"},{\"cityName\":\"南昌\",\"firstLetter\":\"N\"},{\"cityName\":\"南阳\",\"firstLetter\":\"N\"},{\"cityName\":\"宁夏\",\"firstLetter\":\"N\"},{\"cityName\":\"南充\",\"firstLetter\":\"N\"},{\"cityName\":\"内江\",\"firstLetter\":\"N\"},{\"cityName\":\"怒江\",\"firstLetter\":\"N\"},{\"cityName\":\"南宁\",\"firstLetter\":\"N\"},{\"cityName\":\"那曲\",\"firstLetter\":\"N\"},{\"cityName\":\"盘锦\",\"firstLetter\":\"P\"},{\"cityName\":\"莆田\",\"firstLetter\":\"P\"},{\"cityName\":\"萍乡\",\"firstLetter\":\"P\"},{\"cityName\":\"平顶山\",\"firstLetter\":\"P\"},{\"cityName\":\"濮阳\",\"firstLetter\":\"P\"},{\"cityName\":\"平凉\",\"firstLetter\":\"P\"},{\"cityName\":\"攀枝花\",\"firstLetter\":\"P\"},{\"cityName\":\"普洱\",\"firstLetter\":\"P\"},{\"cityName\":\"秦皇岛\",\"firstLetter\":\"Q\"},{\"cityName\":\"齐齐哈尔\",\"firstLetter\":\"Q\"},{\"cityName\":\"七台河\",\"firstLetter\":\"Q\"},{\"cityName\":\"衢州\",\"firstLetter\":\"Q\"},{\"cityName\":\"泉州\",\"firstLetter\":\"Q\"},{\"cityName\":\"青岛\",\"firstLetter\":\"Q\"},{\"cityName\":\"潜江\",\"firstLetter\":\"Q\"},{\"cityName\":\"清远\",\"firstLetter\":\"Q\"},{\"cityName\":\"庆阳\",\"firstLetter\":\"Q\"},{\"cityName\":\"黔南\",\"firstLetter\":\"Q\"},{\"cityName\":\"黔东南\",\"firstLetter\":\"Q\"},{\"cityName\":\"黔西南\",\"firstLetter\":\"Q\"},{\"cityName\":\"琼海\",\"firstLetter\":\"Q\"},{\"cityName\":\"琼中\",\"firstLetter\":\"Q\"},{\"cityName\":\"曲靖\",\"firstLetter\":\"Q\"},{\"cityName\":\"日照\",\"firstLetter\":\"R\"},{\"cityName\":\"日喀\",\"firstLetter\":\"R\"},{\"cityName\":\"上海\",\"firstLetter\":\"S\"},{\"cityName\":\"石家庄\",\"firstLetter\":\"S\"},{\"cityName\":\"朔州\",\"firstLetter\":\"S\"},{\"cityName\":\"沈阳\",\"firstLetter\":\"S\"},{\"cityName\":\"四平\",\"firstLetter\":\"S\"},{\"cityName\":\"松原\",\"firstLetter\":\"S\"},{\"cityName\":\"双鸭山\",\"firstLetter\":\"S\"},{\"cityName\":\"绥化\",\"firstLetter\":\"S\"},{\"cityName\":\"苏州\",\"firstLetter\":\"S\"},{\"cityName\":\"宿迁\",\"firstLetter\":\"S\"},{\"cityName\":\"绍兴\",\"firstLetter\":\"S\"},{\"cityName\":\"宿州\",\"firstLetter\":\"S\"},{\"cityName\":\"厦门\",\"firstLetter\":\"S\"},{\"cityName\":\"三明\",\"firstLetter\":\"S\"},{\"cityName\":\"上饶\",\"firstLetter\":\"S\"},{\"cityName\":\"商丘\",\"firstLetter\":\"S\"},{\"cityName\":\"三门峡\",\"firstLetter\":\"S\"},{\"cityName\":\"神农架\",\"firstLetter\":\"S\"},{\"cityName\":\"十堰\",\"firstLetter\":\"S\"},{\"cityName\":\"随州\",\"firstLetter\":\"S\"},{\"cityName\":\"邵阳\",\"firstLetter\":\"S\"},{\"cityName\":\"汕尾\",\"firstLetter\":\"S\"},{\"cityName\":\"韶关\",\"firstLetter\":\"S\"},{\"cityName\":\"汕头\",\"firstLetter\":\"S\"},{\"cityName\":\"深圳\",\"firstLetter\":\"S\"},{\"cityName\":\"遂宁\",\"firstLetter\":\"S\"},{\"cityName\":\"三亚\",\"firstLetter\":\"S\"},{\"cityName\":\"商洛\",\"firstLetter\":\"S\"},{\"cityName\":\"山南\",\"firstLetter\":\"S\"},{\"cityName\":\"石嘴山\",\"firstLetter\":\"S\"},{\"cityName\":\"石河子\",\"firstLetter\":\"S\"},{\"cityName\":\"天津\",\"firstLetter\":\"T\"},{\"cityName\":\"唐山\",\"firstLetter\":\"T\"},{\"cityName\":\"太原\",\"firstLetter\":\"T\"},{\"cityName\":\"铁岭\",\"firstLetter\":\"T\"},{\"cityName\":\"通化\",\"firstLetter\":\"T\"},{\"cityName\":\"泰州\",\"firstLetter\":\"T\"},{\"cityName\":\"台州\",\"firstLetter\":\"T\"},{\"cityName\":\"铜陵\",\"firstLetter\":\"T\"},{\"cityName\":\"泰安\",\"firstLetter\":\"T\"},{\"cityName\":\"天门\",\"firstLetter\":\"T\"},{\"cityName\":\"天水\",\"firstLetter\":\"T\"},{\"cityName\":\"铜仁\",\"firstLetter\":\"T\"},{\"cityName\":\"屯昌\",\"firstLetter\":\"T\"},{\"cityName\":\"铜川\",\"firstLetter\":\"T\"},{\"cityName\":\"塔城\",\"firstLetter\":\"T\"},{\"cityName\":\"吐鲁番\",\"firstLetter\":\"T\"},{\"cityName\":\"图木舒克\",\"firstLetter\":\"T\"},{\"cityName\":\"通辽\",\"firstLetter\":\"T\"},{\"cityName\":\"台北\",\"firstLetter\":\"T\"},{\"cityName\":\"台中\",\"firstLetter\":\"T\"},{\"cityName\":\"台南\",\"firstLetter\":\"T\"},{\"cityName\":\"无锡\",\"firstLetter\":\"W\"},{\"cityName\":\"温州\",\"firstLetter\":\"W\"},{\"cityName\":\"芜湖\",\"firstLetter\":\"W\"},{\"cityName\":\"潍坊\",\"firstLetter\":\"W\"},{\"cityName\":\"威海\",\"firstLetter\":\"W\"},{\"cityName\":\"武汉\",\"firstLetter\":\"W\"},{\"cityName\":\"武威\",\"firstLetter\":\"W\"},{\"cityName\":\"五指山\",\"firstLetter\":\"W\"},{\"cityName\":\"文昌\",\"firstLetter\":\"W\"},{\"cityName\":\"万宁\",\"firstLetter\":\"W\"},{\"cityName\":\"文山\",\"firstLetter\":\"W\"},{\"cityName\":\"渭南\",\"firstLetter\":\"W\"},{\"cityName\":\"梧州\",\"firstLetter\":\"W\"},{\"cityName\":\"吴忠\",\"firstLetter\":\"W\"},{\"cityName\":\"乌鲁木齐\",\"firstLetter\":\"W\"},{\"cityName\":\"五家渠\",\"firstLetter\":\"W\"},{\"cityName\":\"乌海\",\"firstLetter\":\"W\"},{\"cityName\":\"乌兰察布\",\"firstLetter\":\"W\"},{\"cityName\":\"邢台\",\"firstLetter\":\"X\"},{\"cityName\":\"忻州\",\"firstLetter\":\"X\"},{\"cityName\":\"徐州\",\"firstLetter\":\"X\"},{\"cityName\":\"宣城\",\"firstLetter\":\"X\"},{\"cityName\":\"新余\",\"firstLetter\":\"X\"},{\"cityName\":\"新乡\",\"firstLetter\":\"X\"},{\"cityName\":\"许昌\",\"firstLetter\":\"X\"},{\"cityName\":\"信阳\",\"firstLetter\":\"X\"},{\"cityName\":\"襄阳\",\"firstLetter\":\"X\"},{\"cityName\":\"孝感\",\"firstLetter\":\"X\"},{\"cityName\":\"咸宁\",\"firstLetter\":\"X\"},{\"cityName\":\"仙桃\",\"firstLetter\":\"X\"},{\"cityName\":\"湘潭\",\"firstLetter\":\"X\"},{\"cityName\":\"湘西\",\"firstLetter\":\"X\"},{\"cityName\":\"西双版纳\",\"firstLetter\":\"X\"},{\"cityName\":\"西宁\",\"firstLetter\":\"X\"},{\"cityName\":\"西安\",\"firstLetter\":\"X\"},{\"cityName\":\"咸阳\",\"firstLetter\":\"X\"},{\"cityName\":\"锡林郭勒盟\",\"firstLetter\":\"X\"},{\"cityName\":\"兴安盟\",\"firstLetter\":\"X\"},{\"cityName\":\"新竹\",\"firstLetter\":\"X\"},{\"cityName\":\"香港\",\"firstLetter\":\"X\"},{\"cityName\":\"阳泉\",\"firstLetter\":\"Y\"},{\"cityName\":\"运城\",\"firstLetter\":\"Y\"},{\"cityName\":\"营口\",\"firstLetter\":\"Y\"},{\"cityName\":\"延边\",\"firstLetter\":\"Y\"},{\"cityName\":\"伊春\",\"firstLetter\":\"Y\"},{\"cityName\":\"扬州\",\"firstLetter\":\"Y\"},{\"cityName\":\"盐城\",\"firstLetter\":\"Y\"},{\"cityName\":\"鹰潭\",\"firstLetter\":\"Y\"},{\"cityName\":\"宜春\",\"firstLetter\":\"Y\"},{\"cityName\":\"烟台\",\"firstLetter\":\"Y\"},{\"cityName\":\"宜昌\",\"firstLetter\":\"Y\"},{\"cityName\":\"岳阳\",\"firstLetter\":\"Y\"},{\"cityName\":\"益阳\",\"firstLetter\":\"Y\"},{\"cityName\":\"永州\",\"firstLetter\":\"Y\"},{\"cityName\":\"阳江\",\"firstLetter\":\"Y\"},{\"cityName\":\"云浮\",\"firstLetter\":\"Y\"},{\"cityName\":\"宜宾\",\"firstLetter\":\"Y\"},{\"cityName\":\"雅安\",\"firstLetter\":\"Y\"},{\"cityName\":\"玉溪\",\"firstLetter\":\"Y\"},{\"cityName\":\"玉树\",\"firstLetter\":\"Y\"},{\"cityName\":\"延安\",\"firstLetter\":\"Y\"},{\"cityName\":\"榆林\",\"firstLetter\":\"Y\"},{\"cityName\":\"玉林\",\"firstLetter\":\"Y\"},{\"cityName\":\"银川\",\"firstLetter\":\"Y\"},{\"cityName\":\"伊犁\",\"firstLetter\":\"Y\"},{\"cityName\":\"张家口\",\"firstLetter\":\"Z\"},{\"cityName\":\"镇江\",\"firstLetter\":\"Z\"},{\"cityName\":\"舟山\",\"firstLetter\":\"Z\"},{\"cityName\":\"漳州\",\"firstLetter\":\"Z\"},{\"cityName\":\"淄博\",\"firstLetter\":\"Z\"},{\"cityName\":\"枣庄\",\"firstLetter\":\"Z\"},{\"cityName\":\"郑州\",\"firstLetter\":\"Z\"},{\"cityName\":\"周口\",\"firstLetter\":\"Z\"},{\"cityName\":\"驻马店\",\"firstLetter\":\"Z\"},{\"cityName\":\"株洲\",\"firstLetter\":\"Z\"},{\"cityName\":\"张家界\",\"firstLetter\":\"Z\"},{\"cityName\":\"珠海\",\"firstLetter\":\"Z\"},{\"cityName\":\"肇庆\",\"firstLetter\":\"Z\"},{\"cityName\":\"湛江\",\"firstLetter\":\"Z\"},{\"cityName\":\"中山\",\"firstLetter\":\"Z\"},{\"cityName\":\"张掖\",\"firstLetter\":\"Z\"},{\"cityName\":\"自贡\",\"firstLetter\":\"Z\"},{\"cityName\":\"资阳\",\"firstLetter\":\"Z\"},{\"cityName\":\"遵义\",\"firstLetter\":\"Z\"},{\"cityName\":\"昭通\",\"firstLetter\":\"Z\"},{\"cityName\":\"中卫\",\"firstLetter\":\"Z\"}]"; 8 | } 9 | -------------------------------------------------------------------------------- /app/src/main/java/com/bigkoo/quicksidebardemo/model/City.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebardemo.model; 2 | 3 | /** 4 | * Created by Sai on 16/3/28. 5 | */ 6 | public class City { 7 | 8 | /** 9 | * cityName : 鞍山 10 | * firstLetter : A 11 | */ 12 | 13 | private String cityName; 14 | private String firstLetter; 15 | 16 | public void setCityName(String cityName) { 17 | this.cityName = cityName; 18 | } 19 | 20 | public void setFirstLetter(String firstLetter) { 21 | this.firstLetter = firstLetter; 22 | } 23 | 24 | public String getCityName() { 25 | return cityName; 26 | } 27 | 28 | public String getFirstLetter() { 29 | return firstLetter; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 11 | 12 | 13 | 21 | 22 | 23 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/layout/view_item.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | QuickSideBarDemo 3 | [{"cityName":"鞍山","firstLetter":"A"},{"cityName":"安庆","firstLetter":"A"},{"cityName":"安阳","firstLetter":"A"},{"cityName":"阿坝","firstLetter":"A"},{"cityName":"安顺","firstLetter":"A"},{"cityName":"安康","firstLetter":"A"},{"cityName":"阿里","firstLetter":"A"},{"cityName":"阿勒泰","firstLetter":"A"},{"cityName":"阿克苏","firstLetter":"A"},{"cityName":"阿拉尔","firstLetter":"A"},{"cityName":"阿拉善盟","firstLetter":"A"},{"cityName":"澳门","firstLetter":"A"},{"cityName":"北京","firstLetter":"B"},{"cityName":"保定","firstLetter":"B"},{"cityName":"本溪","firstLetter":"B"},{"cityName":"白城","firstLetter":"B"},{"cityName":"白山","firstLetter":"B"},{"cityName":"蚌埠","firstLetter":"B"},{"cityName":"亳州","firstLetter":"B"},{"cityName":"滨州","firstLetter":"B"},{"cityName":"白银","firstLetter":"B"},{"cityName":"巴中","firstLetter":"B"},{"cityName":"毕节","firstLetter":"B"},{"cityName":"白沙","firstLetter":"B"},{"cityName":"保亭","firstLetter":"B"},{"cityName":"保山","firstLetter":"B"},{"cityName":"宝鸡","firstLetter":"B"},{"cityName":"百色","firstLetter":"B"},{"cityName":"北海","firstLetter":"B"},{"cityName":"博尔塔拉","firstLetter":"B"},{"cityName":"巴音郭楞","firstLetter":"B"},{"cityName":"包头","firstLetter":"B"},{"cityName":"巴彦淖尔","firstLetter":"B"},{"cityName":"重庆","firstLetter":"C"},{"cityName":"承德","firstLetter":"C"},{"cityName":"沧州","firstLetter":"C"},{"cityName":"长治","firstLetter":"C"},{"cityName":"朝阳","firstLetter":"C"},{"cityName":"常州","firstLetter":"C"},{"cityName":"滁州","firstLetter":"C"},{"cityName":"巢湖","firstLetter":"C"},{"cityName":"池州","firstLetter":"C"},{"cityName":"长沙","firstLetter":"C"},{"cityName":"郴州","firstLetter":"C"},{"cityName":"常德","firstLetter":"C"},{"cityName":"潮州","firstLetter":"C"},{"cityName":"成都","firstLetter":"C"},{"cityName":"澄迈","firstLetter":"C"},{"cityName":"昌江","firstLetter":"C"},{"cityName":"楚雄","firstLetter":"C"},{"cityName":"崇左","firstLetter":"C"},{"cityName":"昌都","firstLetter":"C"},{"cityName":"昌吉","firstLetter":"C"},{"cityName":"赤峰","firstLetter":"C"},{"cityName":"大同","firstLetter":"D"},{"cityName":"大连","firstLetter":"D"},{"cityName":"丹东","firstLetter":"D"},{"cityName":"大兴安岭","firstLetter":"D"},{"cityName":"大庆","firstLetter":"D"},{"cityName":"德州","firstLetter":"D"},{"cityName":"东营","firstLetter":"D"},{"cityName":"东营","firstLetter":"D"},{"cityName":"东莞","firstLetter":"D"},{"cityName":"定西","firstLetter":"D"},{"cityName":"达州","firstLetter":"D"},{"cityName":"德阳","firstLetter":"D"},{"cityName":"儋州","firstLetter":"D"},{"cityName":"东方","firstLetter":"D"},{"cityName":"定安","firstLetter":"D"},{"cityName":"德宏","firstLetter":"D"},{"cityName":"大理","firstLetter":"D"},{"cityName":"迪庆","firstLetter":"D"},{"cityName":"鄂州","firstLetter":"E"},{"cityName":"恩施","firstLetter":"E"},{"cityName":"鄂尔多斯","firstLetter":"E"},{"cityName":"抚顺","firstLetter":"F"},{"cityName":"阜新","firstLetter":"F"},{"cityName":"阜阳","firstLetter":"F"},{"cityName":"福州","firstLetter":"F"},{"cityName":"抚州","firstLetter":"F"},{"cityName":"佛山","firstLetter":"F"},{"cityName":"防城港","firstLetter":"F"},{"cityName":"赣州","firstLetter":"G"},{"cityName":"广州","firstLetter":"G"},{"cityName":"甘南","firstLetter":"G"},{"cityName":"广安","firstLetter":"G"},{"cityName":"甘孜","firstLetter":"G"},{"cityName":"广元","firstLetter":"G"},{"cityName":"贵阳","firstLetter":"G"},{"cityName":"果洛","firstLetter":"G"},{"cityName":"桂林","firstLetter":"G"},{"cityName":"贵港","firstLetter":"G"},{"cityName":"固原","firstLetter":"G"},{"cityName":"高雄","firstLetter":"G"},{"cityName":"邯郸","firstLetter":"H"},{"cityName":"衡水","firstLetter":"H"},{"cityName":"葫芦岛","firstLetter":"H"},{"cityName":"哈尔滨","firstLetter":"H"},{"cityName":"鹤岗","firstLetter":"H"},{"cityName":"黑河","firstLetter":"H"},{"cityName":"淮安","firstLetter":"H"},{"cityName":"杭州","firstLetter":"H"},{"cityName":"湖州","firstLetter":"H"},{"cityName":"合肥","firstLetter":"H"},{"cityName":"淮南","firstLetter":"H"},{"cityName":"淮北","firstLetter":"H"},{"cityName":"黄山","firstLetter":"H"},{"cityName":"菏泽","firstLetter":"H"},{"cityName":"鹤壁","firstLetter":"H"},{"cityName":"黄冈","firstLetter":"H"},{"cityName":"黄石","firstLetter":"H"},{"cityName":"衡阳","firstLetter":"H"},{"cityName":"怀化","firstLetter":"H"},{"cityName":"惠州","firstLetter":"H"},{"cityName":"河源","firstLetter":"H"},{"cityName":"海口","firstLetter":"H"},{"cityName":"红河","firstLetter":"H"},{"cityName":"海北","firstLetter":"H"},{"cityName":"海东","firstLetter":"H"},{"cityName":"黄南","firstLetter":"H"},{"cityName":"海南","firstLetter":"H"},{"cityName":"海西","firstLetter":"H"},{"cityName":"汉中","firstLetter":"H"},{"cityName":"贺州","firstLetter":"H"},{"cityName":"河池","firstLetter":"H"},{"cityName":"哈密","firstLetter":"H"},{"cityName":"和田","firstLetter":"H"},{"cityName":"呼伦贝尔","firstLetter":"H"},{"cityName":"呼和浩特","firstLetter":"H"},{"cityName":"晋中","firstLetter":"J"},{"cityName":"晋城","firstLetter":"J"},{"cityName":"锦州","firstLetter":"J"},{"cityName":"吉林","firstLetter":"J"},{"cityName":"鸡西","firstLetter":"J"},{"cityName":"佳木斯","firstLetter":"J"},{"cityName":"嘉兴","firstLetter":"J"},{"cityName":"金华","firstLetter":"J"},{"cityName":"九江","firstLetter":"J"},{"cityName":"吉安","firstLetter":"J"},{"cityName":"景德镇","firstLetter":"J"},{"cityName":"济南","firstLetter":"J"},{"cityName":"济宁","firstLetter":"J"},{"cityName":"济源","firstLetter":"J"},{"cityName":"焦作","firstLetter":"J"},{"cityName":"荆州","firstLetter":"J"},{"cityName":"荆门","firstLetter":"J"},{"cityName":"揭阳","firstLetter":"J"},{"cityName":"江门","firstLetter":"J"},{"cityName":"金昌","firstLetter":"J"},{"cityName":"嘉峪关","firstLetter":"J"},{"cityName":"酒泉","firstLetter":"J"},{"cityName":"基隆","firstLetter":"J"},{"cityName":"嘉义","firstLetter":"J"},{"cityName":"开封","firstLetter":"K"},{"cityName":"昆明","firstLetter":"K"},{"cityName":"克州","firstLetter":"K"},{"cityName":"克拉玛依","firstLetter":"K"},{"cityName":"喀什","firstLetter":"K"},{"cityName":"廊坊","firstLetter":"L"},{"cityName":"临汾","firstLetter":"L"},{"cityName":"吕梁","firstLetter":"L"},{"cityName":"辽阳","firstLetter":"L"},{"cityName":"辽源","firstLetter":"L"},{"cityName":"连云港","firstLetter":"L"},{"cityName":"丽水","firstLetter":"L"},{"cityName":"六安","firstLetter":"L"},{"cityName":"龙岩","firstLetter":"L"},{"cityName":"临沂","firstLetter":"L"},{"cityName":"莱芜","firstLetter":"L"},{"cityName":"聊城","firstLetter":"L"},{"cityName":"洛阳","firstLetter":"L"},{"cityName":"漯河","firstLetter":"L"},{"cityName":"娄底","firstLetter":"L"},{"cityName":"兰州","firstLetter":"L"},{"cityName":"陇南","firstLetter":"L"},{"cityName":"泸州","firstLetter":"L"},{"cityName":"乐山","firstLetter":"L"},{"cityName":"凉山","firstLetter":"L"},{"cityName":"六盘水","firstLetter":"L"},{"cityName":"临高","firstLetter":"L"},{"cityName":"乐东","firstLetter":"L"},{"cityName":"陵水","firstLetter":"L"},{"cityName":"临沧","firstLetter":"L"},{"cityName":"丽江","firstLetter":"L"},{"cityName":"来宾","firstLetter":"L"},{"cityName":"柳州","firstLetter":"L"},{"cityName":"拉萨","firstLetter":"L"},{"cityName":"林芝","firstLetter":"L"},{"cityName":"牡丹江","firstLetter":"M"},{"cityName":"马鞍山","firstLetter":"M"},{"cityName":"茂名","firstLetter":"M"},{"cityName":"梅州","firstLetter":"M"},{"cityName":"绵阳","firstLetter":"M"},{"cityName":"眉山","firstLetter":"M"},{"cityName":"南京","firstLetter":"N"},{"cityName":"南通","firstLetter":"N"},{"cityName":"宁波","firstLetter":"N"},{"cityName":"宁德","firstLetter":"N"},{"cityName":"南平","firstLetter":"N"},{"cityName":"南昌","firstLetter":"N"},{"cityName":"南阳","firstLetter":"N"},{"cityName":"宁夏","firstLetter":"N"},{"cityName":"南充","firstLetter":"N"},{"cityName":"内江","firstLetter":"N"},{"cityName":"怒江","firstLetter":"N"},{"cityName":"南宁","firstLetter":"N"},{"cityName":"那曲","firstLetter":"N"},{"cityName":"盘锦","firstLetter":"P"},{"cityName":"莆田","firstLetter":"P"},{"cityName":"萍乡","firstLetter":"P"},{"cityName":"平顶山","firstLetter":"P"},{"cityName":"濮阳","firstLetter":"P"},{"cityName":"平凉","firstLetter":"P"},{"cityName":"攀枝花","firstLetter":"P"},{"cityName":"普洱","firstLetter":"P"},{"cityName":"秦皇岛","firstLetter":"Q"},{"cityName":"齐齐哈尔","firstLetter":"Q"},{"cityName":"七台河","firstLetter":"Q"},{"cityName":"衢州","firstLetter":"Q"},{"cityName":"泉州","firstLetter":"Q"},{"cityName":"青岛","firstLetter":"Q"},{"cityName":"潜江","firstLetter":"Q"},{"cityName":"清远","firstLetter":"Q"},{"cityName":"庆阳","firstLetter":"Q"},{"cityName":"黔南","firstLetter":"Q"},{"cityName":"黔东南","firstLetter":"Q"},{"cityName":"黔西南","firstLetter":"Q"},{"cityName":"琼海","firstLetter":"Q"},{"cityName":"琼中","firstLetter":"Q"},{"cityName":"曲靖","firstLetter":"Q"},{"cityName":"日照","firstLetter":"R"},{"cityName":"日喀","firstLetter":"R"},{"cityName":"上海","firstLetter":"S"},{"cityName":"石家庄","firstLetter":"S"},{"cityName":"朔州","firstLetter":"S"},{"cityName":"沈阳","firstLetter":"S"},{"cityName":"四平","firstLetter":"S"},{"cityName":"松原","firstLetter":"S"},{"cityName":"双鸭山","firstLetter":"S"},{"cityName":"绥化","firstLetter":"S"},{"cityName":"苏州","firstLetter":"S"},{"cityName":"宿迁","firstLetter":"S"},{"cityName":"绍兴","firstLetter":"S"},{"cityName":"宿州","firstLetter":"S"},{"cityName":"厦门","firstLetter":"S"},{"cityName":"三明","firstLetter":"S"},{"cityName":"上饶","firstLetter":"S"},{"cityName":"商丘","firstLetter":"S"},{"cityName":"三门峡","firstLetter":"S"},{"cityName":"神农架","firstLetter":"S"},{"cityName":"十堰","firstLetter":"S"},{"cityName":"随州","firstLetter":"S"},{"cityName":"邵阳","firstLetter":"S"},{"cityName":"汕尾","firstLetter":"S"},{"cityName":"韶关","firstLetter":"S"},{"cityName":"汕头","firstLetter":"S"},{"cityName":"深圳","firstLetter":"S"},{"cityName":"遂宁","firstLetter":"S"},{"cityName":"三亚","firstLetter":"S"},{"cityName":"商洛","firstLetter":"S"},{"cityName":"山南","firstLetter":"S"},{"cityName":"石嘴山","firstLetter":"S"},{"cityName":"石河子","firstLetter":"S"},{"cityName":"天津","firstLetter":"T"},{"cityName":"唐山","firstLetter":"T"},{"cityName":"太原","firstLetter":"T"},{"cityName":"铁岭","firstLetter":"T"},{"cityName":"通化","firstLetter":"T"},{"cityName":"泰州","firstLetter":"T"},{"cityName":"台州","firstLetter":"T"},{"cityName":"铜陵","firstLetter":"T"},{"cityName":"泰安","firstLetter":"T"},{"cityName":"天门","firstLetter":"T"},{"cityName":"天水","firstLetter":"T"},{"cityName":"铜仁","firstLetter":"T"},{"cityName":"屯昌","firstLetter":"T"},{"cityName":"铜川","firstLetter":"T"},{"cityName":"塔城","firstLetter":"T"},{"cityName":"吐鲁番","firstLetter":"T"},{"cityName":"图木舒克","firstLetter":"T"},{"cityName":"通辽","firstLetter":"T"},{"cityName":"台北","firstLetter":"T"},{"cityName":"台中","firstLetter":"T"},{"cityName":"台南","firstLetter":"T"},{"cityName":"无锡","firstLetter":"W"},{"cityName":"温州","firstLetter":"W"},{"cityName":"芜湖","firstLetter":"W"},{"cityName":"潍坊","firstLetter":"W"},{"cityName":"威海","firstLetter":"W"},{"cityName":"武汉","firstLetter":"W"},{"cityName":"武威","firstLetter":"W"},{"cityName":"五指山","firstLetter":"W"},{"cityName":"文昌","firstLetter":"W"},{"cityName":"万宁","firstLetter":"W"},{"cityName":"文山","firstLetter":"W"},{"cityName":"渭南","firstLetter":"W"},{"cityName":"梧州","firstLetter":"W"},{"cityName":"吴忠","firstLetter":"W"},{"cityName":"乌鲁木齐","firstLetter":"W"},{"cityName":"五家渠","firstLetter":"W"},{"cityName":"乌海","firstLetter":"W"},{"cityName":"乌兰察布","firstLetter":"W"},{"cityName":"邢台","firstLetter":"X"},{"cityName":"忻州","firstLetter":"X"},{"cityName":"徐州","firstLetter":"X"},{"cityName":"宣城","firstLetter":"X"},{"cityName":"新余","firstLetter":"X"},{"cityName":"新乡","firstLetter":"X"},{"cityName":"许昌","firstLetter":"X"},{"cityName":"信阳","firstLetter":"X"},{"cityName":"襄阳","firstLetter":"X"},{"cityName":"孝感","firstLetter":"X"},{"cityName":"咸宁","firstLetter":"X"},{"cityName":"仙桃","firstLetter":"X"},{"cityName":"湘潭","firstLetter":"X"},{"cityName":"湘西","firstLetter":"X"},{"cityName":"西双版纳","firstLetter":"X"},{"cityName":"西宁","firstLetter":"X"},{"cityName":"西安","firstLetter":"X"},{"cityName":"咸阳","firstLetter":"X"},{"cityName":"锡林郭勒盟","firstLetter":"X"},{"cityName":"兴安盟","firstLetter":"X"},{"cityName":"新竹","firstLetter":"X"},{"cityName":"香港","firstLetter":"X"},{"cityName":"阳泉","firstLetter":"Y"},{"cityName":"运城","firstLetter":"Y"},{"cityName":"营口","firstLetter":"Y"},{"cityName":"延边","firstLetter":"Y"},{"cityName":"伊春","firstLetter":"Y"},{"cityName":"扬州","firstLetter":"Y"},{"cityName":"盐城","firstLetter":"Y"},{"cityName":"鹰潭","firstLetter":"Y"},{"cityName":"宜春","firstLetter":"Y"},{"cityName":"烟台","firstLetter":"Y"},{"cityName":"宜昌","firstLetter":"Y"},{"cityName":"岳阳","firstLetter":"Y"},{"cityName":"益阳","firstLetter":"Y"},{"cityName":"永州","firstLetter":"Y"},{"cityName":"阳江","firstLetter":"Y"},{"cityName":"云浮","firstLetter":"Y"},{"cityName":"宜宾","firstLetter":"Y"},{"cityName":"雅安","firstLetter":"Y"},{"cityName":"玉溪","firstLetter":"Y"},{"cityName":"玉树","firstLetter":"Y"},{"cityName":"延安","firstLetter":"Y"},{"cityName":"榆林","firstLetter":"Y"},{"cityName":"玉林","firstLetter":"Y"},{"cityName":"银川","firstLetter":"Y"},{"cityName":"伊犁","firstLetter":"Y"},{"cityName":"张家口","firstLetter":"Z"},{"cityName":"镇江","firstLetter":"Z"},{"cityName":"舟山","firstLetter":"Z"},{"cityName":"漳州","firstLetter":"Z"},{"cityName":"淄博","firstLetter":"Z"},{"cityName":"枣庄","firstLetter":"Z"},{"cityName":"郑州","firstLetter":"Z"},{"cityName":"周口","firstLetter":"Z"},{"cityName":"驻马店","firstLetter":"Z"},{"cityName":"株洲","firstLetter":"Z"},{"cityName":"张家界","firstLetter":"Z"},{"cityName":"珠海","firstLetter":"Z"},{"cityName":"肇庆","firstLetter":"Z"},{"cityName":"湛江","firstLetter":"Z"},{"cityName":"中山","firstLetter":"Z"},{"cityName":"张掖","firstLetter":"Z"},{"cityName":"自贡","firstLetter":"Z"},{"cityName":"资阳","firstLetter":"Z"},{"cityName":"遵义","firstLetter":"Z"},{"cityName":"昭通","firstLetter":"Z"},{"cityName":"中卫","firstLetter":"Z"} 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:1.5.0' 9 | classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.0' 10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.3' 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | } 20 | } 21 | 22 | task clean(type: Delete) { 23 | delete rootProject.buildDir 24 | } 25 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m 13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 14 | 15 | # When configured, Gradle will run in incubating parallel mode. 16 | # This option should only be used with decoupled projects. More details, visit 17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 18 | # org.gradle.parallel=true -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Wed Oct 21 11:34:03 PDT 2015 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /preview/quicksidebardemo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/saiwu-bigkoo/Android-QuickSideBar/eb57d39562ee957a35323fcbf42c625be6799f9c/preview/quicksidebardemo.gif -------------------------------------------------------------------------------- /quicksidebar/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /quicksidebar/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | apply plugin: 'com.jfrog.bintray' 4 | 5 | version = "1.0.3" 6 | 7 | android { 8 | compileSdkVersion 23 9 | buildToolsVersion "23.0.2" 10 | 11 | defaultConfig { 12 | minSdkVersion 9 13 | targetSdkVersion 23 14 | versionCode 1 15 | versionName "1.0" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | 24 | lintOptions { 25 | abortOnError false 26 | } 27 | 28 | } 29 | 30 | def siteUrl = 'https://github.com/saiwu-bigkoo/Android-QuickSideBar' // #CONFIG# // project homepage 31 | def gitUrl = 'https://github.com/saiwu-bigkoo/Android-QuickSideBar.git' // #CONFIG# // project git 32 | group = "com.bigkoo" 33 | 34 | install { 35 | repositories.mavenInstaller { 36 | // This generates POM.xml with proper parameters 37 | pom { 38 | project { 39 | packaging 'aar' 40 | name 'QuickSideBar For Android' // #CONFIG# // project title 41 | url siteUrl 42 | // Set your license 43 | licenses { 44 | license { 45 | name 'The Apache Software License, Version 2.0' 46 | url 'http://www.apache.org/licenses/LICENSE-2.0.txt' 47 | } 48 | } 49 | developers { 50 | developer { 51 | id 'sai' // #CONFIG# // your user id (you can write your nickname) 52 | name 'sai.wu' // #CONFIG# // your user name 53 | email 'sai.wu@bigkoo.com' // #CONFIG# // your email 54 | } 55 | } 56 | scm { 57 | connection gitUrl 58 | developerConnection gitUrl 59 | url siteUrl 60 | } 61 | } 62 | } 63 | } 64 | } 65 | 66 | task sourcesJar(type: Jar) { 67 | from android.sourceSets.main.java.srcDirs 68 | classifier = 'sources' 69 | } 70 | 71 | task javadoc(type: Javadoc) { 72 | source = android.sourceSets.main.java.srcDirs 73 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator)) 74 | } 75 | 76 | task javadocJar(type: Jar, dependsOn: javadoc) { 77 | classifier = 'javadoc' 78 | from javadoc.destinationDir 79 | } 80 | 81 | artifacts { 82 | archives javadocJar 83 | archives sourcesJar 84 | } 85 | 86 | Properties properties = new Properties() 87 | properties.load(project.rootProject.file('local.properties').newDataInputStream()) 88 | bintray { 89 | user = properties.getProperty("bintray.user") 90 | key = properties.getProperty("bintray.apikey") 91 | configurations = ['archives'] 92 | pkg { 93 | repo = "maven" 94 | name = "QuickSideBar" // #CONFIG# project name in jcenter 95 | websiteUrl = siteUrl 96 | vcsUrl = gitUrl 97 | licenses = ["Apache-2.0"] 98 | publish = true 99 | } 100 | } 101 | 102 | dependencies { 103 | } 104 | -------------------------------------------------------------------------------- /quicksidebar/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/soyoung/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | -------------------------------------------------------------------------------- /quicksidebar/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /quicksidebar/src/main/java/com/bigkoo/quicksidebar/QuickSideBarTipsView.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebar; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.ViewGroup; 6 | import android.widget.RelativeLayout; 7 | 8 | import com.bigkoo.quicksidebar.tipsview.QuickSideBarTipsItemView; 9 | 10 | /** 11 | * Created by Sai on 16/3/26. 12 | */ 13 | public class QuickSideBarTipsView extends RelativeLayout { 14 | private QuickSideBarTipsItemView mTipsView; 15 | 16 | public QuickSideBarTipsView(Context context) { 17 | this(context, null); 18 | } 19 | 20 | public QuickSideBarTipsView(Context context, AttributeSet attrs) { 21 | this(context, attrs, 0); 22 | } 23 | 24 | public QuickSideBarTipsView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | init(context, attrs); 27 | } 28 | 29 | private void init(Context context, AttributeSet attrs) { 30 | mTipsView = new QuickSideBarTipsItemView(context,attrs); 31 | LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); 32 | addView(mTipsView,layoutParams); 33 | } 34 | 35 | 36 | public void setText(String text,int poistion, float y){ 37 | mTipsView.setText(text); 38 | LayoutParams layoutParams = (LayoutParams) mTipsView.getLayoutParams(); 39 | layoutParams.topMargin = (int)(y - getWidth()/2.8); 40 | mTipsView.setLayoutParams(layoutParams); 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /quicksidebar/src/main/java/com/bigkoo/quicksidebar/QuickSideBarView.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebar; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.graphics.Rect; 8 | import android.graphics.Typeface; 9 | import android.util.AttributeSet; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | 13 | import com.bigkoo.quicksidebar.listener.OnQuickSideBarTouchListener; 14 | 15 | import java.util.Arrays; 16 | import java.util.List; 17 | 18 | /** 19 | * 快速选择侧边栏 20 | * Created by Sai on 16/3/25. 21 | */ 22 | public class QuickSideBarView extends View { 23 | 24 | private OnQuickSideBarTouchListener listener; 25 | private List mLetters; 26 | private int mChoose = -1; 27 | private Paint mPaint = new Paint(); 28 | private float mTextSize; 29 | private float mTextSizeChoose; 30 | private int mTextColor; 31 | private int mTextColorChoose; 32 | private int mWidth; 33 | private int mHeight; 34 | private float mItemHeight; 35 | private float mItemStartY; 36 | 37 | public QuickSideBarView(Context context) { 38 | this(context, null); 39 | } 40 | 41 | public QuickSideBarView(Context context, AttributeSet attrs) { 42 | this(context, attrs, 0); 43 | } 44 | 45 | public QuickSideBarView(Context context, AttributeSet attrs, int defStyle) { 46 | super(context, attrs, defStyle); 47 | init(context, attrs); 48 | } 49 | 50 | private void init(Context context, AttributeSet attrs) { 51 | mLetters = Arrays.asList(context.getResources().getStringArray(R.array.quickSideBarLetters)); 52 | 53 | mTextColor = context.getResources().getColor(android.R.color.black); 54 | mTextColorChoose = context.getResources().getColor(android.R.color.black); 55 | mTextSize = context.getResources().getDimensionPixelSize(R.dimen.textSize_quicksidebar); 56 | mTextSizeChoose = context.getResources().getDimensionPixelSize(R.dimen.textSize_quicksidebar_choose); 57 | mItemHeight = context.getResources().getDimension(R.dimen.height_quicksidebaritem); 58 | if (attrs != null) { 59 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.QuickSideBarView); 60 | 61 | mTextColor = a.getColor(R.styleable.QuickSideBarView_sidebarTextColor, mTextColor); 62 | mTextColorChoose = a.getColor(R.styleable.QuickSideBarView_sidebarTextColorChoose, mTextColorChoose); 63 | mTextSize = a.getDimension(R.styleable.QuickSideBarView_sidebarTextSize, mTextSize); 64 | mTextSizeChoose = a.getDimension(R.styleable.QuickSideBarView_sidebarTextSizeChoose, mTextSizeChoose); 65 | mItemHeight = a.getDimension(R.styleable.QuickSideBarView_sidebarItemHeight, mItemHeight); 66 | a.recycle(); 67 | } 68 | } 69 | 70 | protected void onDraw(Canvas canvas) { 71 | super.onDraw(canvas); 72 | for (int i = 0; i < mLetters.size(); i++) { 73 | mPaint.setColor(mTextColor); 74 | 75 | mPaint.setAntiAlias(true); 76 | mPaint.setTextSize(mTextSize); 77 | if (i == mChoose) { 78 | mPaint.setColor(mTextColorChoose); 79 | mPaint.setFakeBoldText(true); 80 | mPaint.setTypeface(Typeface.DEFAULT_BOLD); 81 | mPaint.setTextSize(mTextSizeChoose); 82 | } 83 | 84 | 85 | //计算位置 86 | Rect rect = new Rect(); 87 | mPaint.getTextBounds(mLetters.get(i), 0, mLetters.get(i).length(), rect); 88 | float xPos = (int) ((mWidth - rect.width()) * 0.5); 89 | float yPos = mItemHeight * i + (int) ((mItemHeight - rect.height()) * 0.5) + mItemStartY; 90 | 91 | 92 | canvas.drawText(mLetters.get(i), xPos, yPos, mPaint); 93 | mPaint.reset(); 94 | } 95 | 96 | } 97 | 98 | @Override 99 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 100 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 101 | mHeight = getMeasuredHeight(); 102 | mWidth = getMeasuredWidth(); 103 | mItemStartY = (mHeight - mLetters.size()*mItemHeight)/2; 104 | } 105 | 106 | @Override 107 | public boolean dispatchTouchEvent(MotionEvent event) { 108 | final int action = event.getAction(); 109 | final float y = event.getY(); 110 | final int oldChoose = mChoose; 111 | final int newChoose = (int) ((y - mItemStartY) / mItemHeight); 112 | switch (action) { 113 | case MotionEvent.ACTION_UP: 114 | mChoose = -1; 115 | if (listener != null) { 116 | listener.onLetterTouching(false); 117 | } 118 | invalidate(); 119 | break; 120 | default: 121 | if (oldChoose != newChoose) { 122 | if (newChoose >= 0 && newChoose < mLetters.size()) { 123 | mChoose = newChoose; 124 | if (listener != null) { 125 | //计算位置 126 | Rect rect = new Rect(); 127 | mPaint.getTextBounds(mLetters.get(mChoose), 0, mLetters.get(mChoose).length(), rect); 128 | float yPos = mItemHeight * mChoose + (int) ((mItemHeight - rect.height()) * 0.5) + mItemStartY; 129 | listener.onLetterChanged(mLetters.get(newChoose), mChoose, yPos); 130 | } 131 | } 132 | invalidate(); 133 | } 134 | //如果是cancel也要调用onLetterUpListener 通知 135 | if (event.getAction() == MotionEvent.ACTION_CANCEL) { 136 | if (listener != null) { 137 | listener.onLetterTouching(false); 138 | } 139 | } else if (event.getAction() == MotionEvent.ACTION_DOWN) {//按下调用 onLetterDownListener 140 | if (listener != null) { 141 | listener.onLetterTouching(true); 142 | } 143 | } 144 | 145 | break; 146 | } 147 | return true; 148 | } 149 | 150 | public OnQuickSideBarTouchListener getListener() { 151 | return listener; 152 | } 153 | 154 | public void setOnQuickSideBarTouchListener(OnQuickSideBarTouchListener listener) { 155 | this.listener = listener; 156 | } 157 | 158 | public List getLetters() { 159 | return mLetters; 160 | } 161 | 162 | /** 163 | * 设置字母表 164 | * @param letters 165 | */ 166 | public void setLetters(List letters) { 167 | this.mLetters = letters; 168 | invalidate(); 169 | } 170 | } 171 | 172 | -------------------------------------------------------------------------------- /quicksidebar/src/main/java/com/bigkoo/quicksidebar/listener/OnQuickSideBarTouchListener.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebar.listener; 2 | 3 | /** 4 | * Created by Sai on 16/3/25. 5 | */ 6 | public interface OnQuickSideBarTouchListener { 7 | void onLetterChanged(String letter,int position,float y); 8 | void onLetterTouching(boolean touching); 9 | } 10 | -------------------------------------------------------------------------------- /quicksidebar/src/main/java/com/bigkoo/quicksidebar/tipsview/QuickSideBarTipsItemView.java: -------------------------------------------------------------------------------- 1 | package com.bigkoo.quicksidebar.tipsview; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.content.res.TypedArray; 6 | import android.graphics.Canvas; 7 | import android.graphics.Paint; 8 | import android.graphics.Path; 9 | import android.graphics.Rect; 10 | import android.graphics.RectF; 11 | import android.os.Build; 12 | import android.text.TextUtils; 13 | import android.util.AttributeSet; 14 | import android.view.View; 15 | 16 | import com.bigkoo.quicksidebar.R; 17 | 18 | /** 19 | * Created by Sai on 16/3/28. 20 | */ 21 | public class QuickSideBarTipsItemView extends View { 22 | private int mCornerRadius; 23 | 24 | private Path mBackgroundPath = new Path(); 25 | private RectF mBackgroundRect = new RectF(); 26 | private Paint mBackgroundPaint; 27 | 28 | private String mText =""; 29 | 30 | private Paint mTextPaint; 31 | private int mWidth; 32 | private int mItemHeight; 33 | private float mTextSize; 34 | private int mTextColor; 35 | private int mBackgroundColor; 36 | private int mCenterTextStartX; 37 | private int mCenterTextStartY; 38 | 39 | 40 | public QuickSideBarTipsItemView(Context context) { 41 | this(context, null); 42 | } 43 | 44 | public QuickSideBarTipsItemView(Context context, AttributeSet attrs) { 45 | this(context, attrs, 0); 46 | } 47 | 48 | public QuickSideBarTipsItemView(Context context, AttributeSet attrs, int defStyleAttr) { 49 | super(context, attrs, defStyleAttr); 50 | init(context, attrs); 51 | } 52 | 53 | private void init(Context context, AttributeSet attrs) { 54 | 55 | mTextColor = context.getResources().getColor(android.R.color.black); 56 | mBackgroundColor = context.getResources().getColor(android.R.color.darker_gray); 57 | mTextSize = context.getResources().getDimension(R.dimen.textSize_quicksidebartips); 58 | if (attrs != null) { 59 | TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.QuickSideBarView); 60 | 61 | mTextColor = a.getColor(R.styleable.QuickSideBarView_sidebarTextColor, mTextColor); 62 | mBackgroundColor = a.getColor(R.styleable.QuickSideBarView_sidebarBackgroundColor, mBackgroundColor); 63 | mTextSize = a.getDimension(R.styleable.QuickSideBarView_sidebarTextSize, mTextSize); 64 | a.recycle(); 65 | } 66 | 67 | mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 68 | mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 69 | mBackgroundPaint.setColor(mBackgroundColor); 70 | mTextPaint.setColor(mTextColor); 71 | mTextPaint.setTextSize(mTextSize); 72 | } 73 | 74 | @Override 75 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 76 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 77 | mWidth = getWidth(); 78 | mItemHeight = mWidth; 79 | mCornerRadius = (int) (mWidth * 0.5); 80 | 81 | } 82 | 83 | protected void onDraw(Canvas canvas) { 84 | super.onDraw(canvas); 85 | if (TextUtils.isEmpty(mText))return; 86 | canvas.drawColor(getResources().getColor(android.R.color.transparent)); 87 | float[] radii; 88 | 89 | mBackgroundRect.set(0, 0, mWidth, mItemHeight); 90 | if (isRtl()) { 91 | radii = new float[]{mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, 0, 0}; 92 | } else { 93 | 94 | radii = new float[]{mCornerRadius, mCornerRadius, mCornerRadius, mCornerRadius, 0, 0, mCornerRadius, mCornerRadius}; 95 | } 96 | 97 | mBackgroundPath.addRoundRect(mBackgroundRect, radii, Path.Direction.CW); 98 | 99 | canvas.drawPath(mBackgroundPath, mBackgroundPaint); 100 | canvas.drawText(mText, mCenterTextStartX, mCenterTextStartY, mTextPaint); 101 | 102 | } 103 | 104 | public void setText(String text) { 105 | mText = text; 106 | 107 | Rect rect = new Rect(); 108 | mTextPaint.getTextBounds(mText, 0, mText.length(), rect); 109 | mCenterTextStartX = (int)((mWidth - rect.width()) * 0.5); 110 | mCenterTextStartY = mItemHeight - rect.height(); 111 | invalidate(); 112 | } 113 | 114 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1) 115 | public boolean isRtl() { 116 | return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) && 117 | (getContext().getResources().getConfiguration().getLayoutDirection() == View.LAYOUT_DIRECTION_RTL); 118 | } 119 | 120 | 121 | } 122 | -------------------------------------------------------------------------------- /quicksidebar/src/main/res/values/array.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A 5 | B 6 | C 7 | D 8 | E 9 | F 10 | G 11 | H 12 | I 13 | J 14 | K 15 | L 16 | M 17 | N 18 | O 19 | P 20 | Q 21 | R 22 | S 23 | T 24 | U 25 | V 26 | W 27 | X 28 | Y 29 | Z 30 | 31 | -------------------------------------------------------------------------------- /quicksidebar/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /quicksidebar/src/main/res/values/dimen.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 10sp 4 | 15sp 5 | 20sp 6 | 45dp 7 | 20dp 8 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':quicksidebar' 2 | --------------------------------------------------------------------------------