├── .gitignore ├── .gitmodules ├── README.md ├── demo ├── AndroidManifest.xml ├── assets │ └── fonts │ │ ├── Roboto-Bold.ttf │ │ └── Roboto-Regular.ttf ├── libs │ └── android-support-v4.jar ├── proguard-project.txt ├── project.properties ├── res │ ├── drawable-hdpi │ │ ├── ic_action_github.png │ │ ├── ic_launcher.png │ │ ├── la_rioja_highlighted.png │ │ ├── la_rioja_normal.png │ │ ├── mendoza_highlighted.png │ │ ├── mendoza_normal.png │ │ ├── san_juan_highlighted.png │ │ ├── san_juan_normal.png │ │ ├── san_luis_highlighted.png │ │ └── san_luis_normal.png │ ├── drawable-mdpi │ │ ├── ic_action_github.png │ │ ├── ic_launcher.png │ │ ├── la_rioja_highlighted.png │ │ ├── la_rioja_normal.png │ │ ├── mendoza_highlighted.png │ │ ├── mendoza_normal.png │ │ ├── san_juan_highlighted.png │ │ ├── san_juan_normal.png │ │ ├── san_luis_highlighted.png │ │ └── san_luis_normal.png │ ├── drawable-xhdpi │ │ ├── ic_action_github.png │ │ ├── ic_launcher.png │ │ ├── la_rioja_highlighted.png │ │ ├── la_rioja_normal.png │ │ ├── mendoza_highlighted.png │ │ ├── mendoza_normal.png │ │ ├── san_juan_highlighted.png │ │ ├── san_juan_normal.png │ │ ├── san_luis_highlighted.png │ │ └── san_luis_normal.png │ ├── drawable │ │ ├── la_rioja.xml │ │ ├── mendoza.xml │ │ ├── san_juan.xml │ │ ├── san_luis.xml │ │ └── shadow_menu.xml │ ├── layout │ │ ├── content_frame.xml │ │ ├── menu_frame.xml │ │ └── my_custom_cell.xml │ ├── menu │ │ └── main_menu.xml │ └── values │ │ ├── colors.xml │ │ ├── dimens.xml │ │ ├── strings.xml │ │ └── styles.xml └── src │ └── com │ └── nakardo │ └── atableview │ └── demo │ ├── activities │ └── MainActivity.java │ ├── cells │ └── MyCustomCell.java │ ├── fragments │ ├── BaseListFragment.java │ ├── MenuFragment.java │ ├── MultipleStylesListFragment.java │ └── SimpleListFragment.java │ └── interfaces │ └── TableViewConfigurationInterface.java └── library ├── AndroidManifest.xml ├── libs └── android-support-v4.jar ├── project.properties ├── res ├── color │ ├── atv_default_cell_text_selector.xml │ ├── atv_subtitle_cell_detail_text_selector.xml │ ├── atv_subtitle_cell_text_selector.xml │ ├── atv_value1_cell_detail_text_selector.xml │ ├── atv_value1_cell_title_text_selector.xml │ ├── atv_value2_cell_detail_text_selector.xml │ └── atv_value2_cell_title_text_selector.xml ├── drawable-hdpi │ ├── checkmark_highlighted.png │ ├── checkmark_normal.png │ ├── disclosure_button_normal.png │ ├── disclosure_button_pressed.png │ ├── disclosure_highlighted.png │ ├── disclosure_normal.png │ ├── group_background.png │ └── plain_header_background.9.png ├── drawable-mdpi │ ├── checkmark_highlighted.png │ ├── checkmark_normal.png │ ├── disclosure_button_normal.png │ ├── disclosure_button_pressed.png │ ├── disclosure_highlighted.png │ ├── disclosure_normal.png │ ├── group_background.png │ └── plain_header_background.9.png ├── drawable-xhdpi │ ├── checkmark_highlighted.png │ ├── checkmark_normal.png │ ├── disclosure_button_normal.png │ ├── disclosure_button_pressed.png │ ├── disclosure_highlighted.png │ ├── disclosure_normal.png │ ├── group_background.png │ └── plain_header_background.9.png ├── drawable │ ├── checkmark.xml │ ├── disclosure.xml │ └── disclosure_button.xml ├── layout │ ├── atv_cell_default.xml │ ├── atv_cell_subtitle.xml │ ├── atv_cell_value1.xml │ ├── atv_cell_value2.xml │ ├── atv_grouped_footer.xml │ ├── atv_grouped_header.xml │ └── atv_plain_header_footer.xml └── values │ ├── colors.xml │ ├── dimens.xml │ ├── ids.xml │ └── styles.xml └── src └── com └── nakardo └── atableview ├── foundation └── NSIndexPath.java ├── internal ├── ATableViewAdapter.java ├── ATableViewCellAccessoryView.java ├── ATableViewCellClickListener.java ├── ATableViewCellContainerView.java ├── ATableViewCellDrawable.java ├── ATableViewHeaderFooterCell.java └── ATableViewPlainFooterDrawable.java ├── protocol ├── ATableViewDataSource.java ├── ATableViewDataSourceExt.java └── ATableViewDelegate.java ├── uikit └── UILabel.java ├── utils └── DrawableUtils.java └── view ├── ATableView.java └── ATableViewCell.java /.gitignore: -------------------------------------------------------------------------------- 1 | # os x 2 | .DS_Store 3 | 4 | # built application files 5 | *.apk 6 | *.ap_ 7 | 8 | # files for the dex VM 9 | *.dex 10 | 11 | # Java class files 12 | *.class 13 | 14 | # generated files 15 | bin/ 16 | gen/ 17 | 18 | # Local configuration file (sdk path, etc) 19 | local.properties 20 | 21 | # Eclipse project files 22 | .settings 23 | .classpath 24 | .project 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "external/SlidingMenu"] 2 | path = external/SlidingMenu 3 | url = git@github.com:jfeinstein10/SlidingMenu.git 4 | [submodule "external/ActionBarSherlock"] 5 | path = external/ActionBarSherlock 6 | url = git@github.com:JakeWharton/ActionBarSherlock.git 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # THIS PROJECT IS NO LONGER MAINTAINED 2 | > Please refer to Android [docs](https://developer.android.com/training/material/lists-cards.html) to customize lists depending on your needs. 3 | 4 | # ATableView 5 | 6 | ![ATableView](http://oi45.tinypic.com/vshn2x.jpg) 7 | 8 | ## Summary 9 | 10 | ATableView intends to imitate same object model proposed on UIKit for building tables, so it's not only limited on theming Android ListView. If you've some background on iOS development you may jump over some of the sections below, you'll find a lot of similarities with the native framework. 11 | 12 | If not, you should be good with the examples included here and the demo project. 13 | 14 | ## Updates 15 | 16 | Documentation is a little outdated, please use it only for reference and stay close to the examples included on the demo project. Feel free to submit a bug if you find any issues using it. 17 | 18 | ## How to use it 19 | 20 | ### Creating tables 21 | 22 | ```java 23 | @Override 24 | public void onCreate(Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.main); 27 | 28 | // ATableViewStyle.Plain & Grouped supported. 29 | ATableView tableView = new ATableView(ATableViewStyle.Grouped, this); 30 | 31 | // don't forget to set the datasource, otherwise you'll get an exception. 32 | // it must be an object extending ATableViewDataSource, or ATableViewDataSourceExt (more on this later). 33 | tableView.setDataSource(new SampleATableViewDataSource()); 34 | 35 | // delegates are optional, it must extend ATableViewDelegate. 36 | tableView.setDelegate(new SampleATableViewDelegate()); 37 | 38 | FrameLayout container = (FrameLayout)findViewById(android.R.id.content); 39 | container.addView(tableView); 40 | } 41 | ``` 42 | 43 | ### Implementing a data source 44 | 45 | It's your responsability to implement the required methods when extending `ATableViewDataSource`. The following are supported: 46 | 47 | ```java 48 | public ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath); [Required] 49 | public int numberOfRowsInSection(ATableView tableView, int section); [Required] 50 | public int numberOfSectionsInTableView(ATableView tableView); 51 | ``` 52 | 53 | More on how this methods works can be found on the iOS [UITableViewDataSource Protocol Reference](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewDataSource_Protocol/Reference/Reference.html). 54 | 55 | #### Example 56 | 57 | ```java 58 | @Override 59 | public ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 60 | final String cellIdentifier = "CellIdentifier"; 61 | 62 | // ATableViewCellStyle.Default, Subtitle, Value1 & Value2 supported. 63 | ATableViewCellStyle style = ATableViewCellStyle.Default; 64 | 65 | // reuse cells. if the table has different row types it will result on performance issues. 66 | // Use ATableViewDataSourceExt on this cases. 67 | // please notice we ask the datasource for a cell instead the table as we do on ios. 68 | ATableViewCell cell = dequeueReusableCellWithIdentifier(cellIdentifier); 69 | if (cell == null) { 70 | cell = new ATableViewCell(style, cellIdentifier, MainActivity.this); 71 | // ATableViewCellSelectionStyle.Blue, Gray & None supported. It defaults to Blue. 72 | cell.setSelectionStyle(ATableViewCellSelectionStyle.Blue); 73 | } 74 | 75 | // set title. 76 | cell.getTextLabel().setText("Buenos Aires"); 77 | 78 | // set detail text. careful, detail text is not present on every cell style. 79 | // null references are not as neat as in obj-c. 80 | TextView detailTextLabel = cell.getDetailTextLabel(); 81 | if (detailTextLabel != null) { 82 | detailTextLabel.setText("Argentina"); 83 | } 84 | 85 | return cell; 86 | } 87 | 88 | @Override 89 | public int numberOfRowsInSection(ATableView tableView, int section) { 90 | // return number of rows for this section. 91 | if (section == 1) { 92 | return 4; 93 | } 94 | 95 | return 2; 96 | } 97 | 98 | @Override 99 | public int numberOfSectionsInTableView(ATableView tableView) { 100 | // defaults to 1. 101 | return 2; 102 | } 103 | ``` 104 | 105 | ### Table styles (ATableViewStyle) 106 | 107 | All [UITableViewStyle](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/c/tdef/UITableViewStyle) styles are supported. These are: 108 | 109 | * ATableViewStyle.Plain 110 | * ATableViewStyle.Grouped 111 | 112 | ### Creating cells 113 | 114 | You can use cell styles included by default, or extend `ATableViewCell` to create your own cells. 115 | 116 | ### Cell styles (ATableViewCellStyle) 117 | 118 | All [UITableViewCellStyles](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/c/tdef/UITableViewCellStyle) styles are supported. These are: 119 | 120 | * ATableViewCellStyle.Default 121 | * ATableViewCellStyle.Subtitle 122 | * ATableViewCellStyle.Value1 123 | * ATableViewCellStyle.Value2 124 | 125 | ![ATableViewCellStyle](http://oi45.tinypic.com/auyv8.jpg) 126 | 127 | ### Cell selection styles (ATableViewCellSelectionStyle) 128 | 129 | All [UITableViewCellSelectionStyle](http://developer.apple.com/library/ios/#documentation/uikit/reference/UITableViewCell_Class/Reference/Reference.html#//apple_ref/doc/c_ref/UITableViewCellSelectionStyle) styles are supported These are: 130 | 131 | * ATableViewCellSelectionStyle.None 132 | * ATableViewCellSelectionStyle.Blue (Default) 133 | * ATableViewCellSelectionStyle.Gray 134 | 135 | ![ATableViewCellSelectionStyle](http://oi47.tinypic.com/2l8c2e8.jpg) 136 | 137 | ### Adding images to cells (imageView) 138 | 139 | imageView is shown automatically when an image is defined for it, otherwise is hidden by default on each cell. 140 | 141 | ![imageView](http://i45.tinypic.com/34508zd.jpg) 142 | 143 | #### Example 144 | 145 | ```java 146 | Drawable drawable = getResources().getDrawable(R.drawable.some_image); 147 | cell.getImageView().setImageDrawable(drawable); 148 | ``` 149 | 150 | ### Creating custom cells 151 | 152 | Creating custom cells is as simple as extending `ATableViewCellStyle` and indicate the layout you want your cell to use. 153 | 154 | #### Example 155 | 156 | ```java 157 | public class MyCustomCell extends ATableViewCell { 158 | private UILabel mCustomLabel; 159 | 160 | protected int getLayout(ATableViewCellStyle style) { 161 | // here it goes your custom cell layout. 162 | return R.layout.my_custom_cell; 163 | } 164 | 165 | public MyCustomCell(ATableViewCellStyle style, String reuseIdentifier, Context context) { 166 | super(style, reuseIdentifier, context); 167 | mCustomLabel = (UILabel)findViewById(R.id.custom_cell_label); 168 | } 169 | 170 | public UILabel getCustomLabel() { 171 | return mCustomLabel; 172 | } 173 | } 174 | ``` 175 | 176 | ### Implementing a delegate 177 | 178 | Adding a delegate to the table is optional. [UITableViewDelegate](http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableViewDelegate_Protocol/Reference/Reference.html) defines many methods to describe how the table should look and behave. Only a few of them are currently supported on `ATableViewDelegate`. These are: 179 | 180 | ```java 181 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath); 182 | public int heightForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath); 183 | ``` 184 | 185 | #### Example 186 | 187 | ```java 188 | @Override 189 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 190 | // do something when the row is selected. rows are identified by its indexPath. 191 | } 192 | 193 | @Override 194 | public int heightForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 195 | // return height size on dip. defaults to 44 if not implemented. 196 | return 54; 197 | } 198 | ``` 199 | 200 | ### Table data source additional methods (ATableViewDataSourceExt) 201 | 202 | On the case you need to use different cell styles on the same table, you should extend `ATableViewDataSourceExt` to avoid performance issues when scrolling. This is necessary since Android ListView uses different pools for reusing cells, a pool for each cell type. `ATableViewDataSourceExt` is used to specify how many rows and pools should be created to run smoothly. 203 | 204 | You'll have additionally to implement the following methods: 205 | 206 | ```java 207 | public int numberOfRowStyles(); [Required] 208 | public int styleForRowAtIndexPath(NSIndexPath indexPath); [Required] 209 | ``` 210 | 211 | #### Example 212 | 213 | ```java 214 | @Override 215 | public int numberOfRowStyles() { 216 | // number of different rows on the table. 217 | return 4; 218 | } 219 | 220 | @Override 221 | public int styleForRowAtIndexPath(NSIndexPath indexPath) { 222 | // integer identifying the style for a cell at a given indexPath. 223 | return myOwnImplementationGetStyle(indexPath); 224 | } 225 | ``` 226 | 227 | ## Extra stuff 228 | 229 | ### UILabel 230 | 231 | UILabel uses internally [Roboto](http://developer.android.com/design/style/typography.html) font, which make labels look-alike in iOS and it's rendered great by Android. Roboto font is available from ICS and above, so it should be included on your project `/assets` folder in order to make it work for any version. 232 | 233 | Both **Roboto-Regular.ttf** and **Roboto-Bold.ttf** are included on the demo project. On the case you don't include these files, text will render using the default font available. 234 | 235 | ## License 236 | 237 | Copyright 2012 Diego Acosta - Contact me at diegonake@gmail.com / @nakardo 238 | 239 | Released under the [Apache 2.0.](http://www.apache.org/licenses/LICENSE-2.0.html) license. 240 | 241 | Roboto font by Google Android - Licensed under the Apache License. 242 | 243 | Awesome Android PSD images by [slaveoffear](http://slaveoffear.deviantart.com). 244 | -------------------------------------------------------------------------------- /demo/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 10 | 11 | 15 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /demo/assets/fonts/Roboto-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/assets/fonts/Roboto-Bold.ttf -------------------------------------------------------------------------------- /demo/assets/fonts/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/assets/fonts/Roboto-Regular.ttf -------------------------------------------------------------------------------- /demo/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/libs/android-support-v4.jar -------------------------------------------------------------------------------- /demo/proguard-project.txt: -------------------------------------------------------------------------------- 1 | # To enable ProGuard in your project, edit project.properties 2 | # to define the proguard.config property as described in that file. 3 | # 4 | # Add project specific ProGuard rules here. 5 | # By default, the flags in this file are appended to flags specified 6 | # in ${sdk.dir}/tools/proguard/proguard-android.txt 7 | # You can edit the include path and order by changing the ProGuard 8 | # include property in project.properties. 9 | # 10 | # For more details, see 11 | # http://developer.android.com/guide/developing/tools/proguard.html 12 | 13 | # Add any project specific keep options here: 14 | 15 | # If your project uses WebView with JS, uncomment the following 16 | # and specify the fully qualified class name to the JavaScript interface 17 | # class: 18 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 19 | # public *; 20 | #} 21 | -------------------------------------------------------------------------------- /demo/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-14 15 | android.library.reference.1=../library 16 | android.library.reference.2=../external/SlidingMenu/library 17 | -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/ic_action_github.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/la_rioja_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/la_rioja_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/la_rioja_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/la_rioja_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/mendoza_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/mendoza_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/mendoza_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/mendoza_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/san_juan_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/san_juan_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/san_juan_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/san_juan_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/san_luis_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/san_luis_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-hdpi/san_luis_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-hdpi/san_luis_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/ic_action_github.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/la_rioja_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/la_rioja_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/la_rioja_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/la_rioja_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/mendoza_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/mendoza_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/mendoza_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/mendoza_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/san_juan_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/san_juan_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/san_juan_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/san_juan_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/san_luis_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/san_luis_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-mdpi/san_luis_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-mdpi/san_luis_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/ic_action_github.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/ic_action_github.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/la_rioja_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/la_rioja_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/la_rioja_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/la_rioja_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/mendoza_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/mendoza_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/mendoza_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/mendoza_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/san_juan_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/san_juan_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/san_juan_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/san_juan_normal.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/san_luis_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/san_luis_highlighted.png -------------------------------------------------------------------------------- /demo/res/drawable-xhdpi/san_luis_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/demo/res/drawable-xhdpi/san_luis_normal.png -------------------------------------------------------------------------------- /demo/res/drawable/la_rioja.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/res/drawable/mendoza.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/res/drawable/san_juan.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/res/drawable/san_luis.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /demo/res/drawable/shadow_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | -------------------------------------------------------------------------------- /demo/res/layout/content_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | -------------------------------------------------------------------------------- /demo/res/layout/menu_frame.xml: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /demo/res/layout/my_custom_cell.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 10 | 11 | 15 | 16 | 21 | 22 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /demo/res/menu/main_menu.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 7 | -------------------------------------------------------------------------------- /demo/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #768DB0 4 | -------------------------------------------------------------------------------- /demo/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 15dp 4 | 70dp 5 | -------------------------------------------------------------------------------- /demo/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ATableView Demos 4 | https://github.com/dmacosta/ATableView 5 | -------------------------------------------------------------------------------- /demo/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | 16 | 20 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/activities/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.activities; 2 | 3 | import android.content.Intent; 4 | import android.net.Uri; 5 | import android.os.Bundle; 6 | import android.support.v4.app.Fragment; 7 | import android.util.Log; 8 | import android.view.KeyEvent; 9 | 10 | import com.actionbarsherlock.app.SherlockFragmentActivity; 11 | import com.actionbarsherlock.view.Menu; 12 | import com.actionbarsherlock.view.MenuItem; 13 | import com.nakardo.atableview.demo.R; 14 | import com.nakardo.atableview.demo.fragments.MenuFragment; 15 | import com.nakardo.atableview.demo.fragments.MenuFragment.TableViewDemoInterface; 16 | import com.nakardo.atableview.demo.fragments.MultipleStylesListFragment; 17 | import com.nakardo.atableview.demo.interfaces.TableViewConfigurationInterface; 18 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 19 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSeparatorStyle; 20 | import com.slidingmenu.lib.SlidingMenu; 21 | 22 | public class MainActivity extends SherlockFragmentActivity 23 | implements TableViewConfigurationInterface, TableViewDemoInterface { 24 | 25 | private TableViewConfigurationInterface mContentListener; 26 | private SlidingMenu mMenu; 27 | 28 | // example default selections. 29 | public ATableViewStyle mTableViewStyle = ATableViewStyle.Grouped; 30 | public ATableViewCellSeparatorStyle mSeparatorStyle = ATableViewCellSeparatorStyle.SingleLineEtched; 31 | public boolean mAllowsSelection = true; 32 | public boolean mAllowsMultipleSelection = false; 33 | 34 | private void setupSlidingMenu() { 35 | mMenu = new SlidingMenu(this); 36 | 37 | mMenu.setMode(SlidingMenu.LEFT); 38 | mMenu.setTouchModeAbove(SlidingMenu.TOUCHMODE_FULLSCREEN); 39 | mMenu.setShadowWidthRes(R.dimen.menu_shadow_width); 40 | mMenu.setShadowDrawable(R.drawable.shadow_menu); 41 | mMenu.setBehindOffsetRes(R.dimen.menu_behind_offset); 42 | mMenu.setFadeDegree(0.35f); 43 | mMenu.attachToActivity(this, SlidingMenu.SLIDING_CONTENT); 44 | 45 | mMenu.setMenu(R.layout.menu_frame); 46 | 47 | getSupportFragmentManager().beginTransaction().replace(R.id.menu_frame, 48 | new MenuFragment()).commit(); 49 | } 50 | 51 | public SlidingMenu getSlidingMenu() { 52 | return mMenu; 53 | } 54 | 55 | @Override 56 | public void onCreate(Bundle savedInstanceState) { 57 | super.onCreate(savedInstanceState); 58 | setContentView(R.layout.content_frame); 59 | 60 | getSupportActionBar().setDisplayHomeAsUpEnabled(true); 61 | setupSlidingMenu(); 62 | 63 | onTableViewDemoSelected(MultipleStylesListFragment.class); 64 | } 65 | 66 | @Override 67 | public boolean onCreateOptionsMenu(Menu menu) { 68 | getSupportMenuInflater().inflate(R.menu.main_menu, menu); 69 | return true; 70 | } 71 | 72 | @Override 73 | public boolean onOptionsItemSelected(MenuItem item) { 74 | switch (item.getItemId()) { 75 | case android.R.id.home: 76 | mMenu.toggle(); return true; 77 | case R.id.goto_github: 78 | String url = getResources().getString(R.string.github_url); 79 | startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url))); 80 | return true; 81 | } 82 | 83 | return super.onOptionsItemSelected(item); 84 | } 85 | 86 | @Override 87 | public boolean onKeyDown(int keycode, KeyEvent event ) { 88 | if (keycode == KeyEvent.KEYCODE_MENU) { 89 | mMenu.toggle(); return true; 90 | } 91 | 92 | return super.onKeyDown(keycode,event); 93 | } 94 | 95 | @Override 96 | public void onTableViewConfigurationChanged() { 97 | mContentListener.onTableViewConfigurationChanged(); 98 | } 99 | 100 | @Override 101 | public void onTableViewDemoSelected(Class fragmentClass) { 102 | T fragment = null; 103 | try { 104 | fragment = fragmentClass.newInstance(); 105 | } catch (InstantiationException e) { 106 | Log.e(this.getClass().toString(), e.getMessage()); 107 | } catch (IllegalAccessException e) { 108 | Log.e(this.getClass().toString(), e.getMessage()); 109 | } 110 | fragment.setHasOptionsMenu(true); 111 | 112 | getSupportFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).commit(); 113 | mContentListener = (TableViewConfigurationInterface) fragment; 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/cells/MyCustomCell.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.cells; 2 | 3 | import android.content.Context; 4 | 5 | import com.nakardo.atableview.demo.R; 6 | import com.nakardo.atableview.view.ATableViewCell; 7 | 8 | public class MyCustomCell extends ATableViewCell { 9 | 10 | protected int getLayout(ATableViewCellStyle style) { 11 | return R.layout.my_custom_cell; 12 | } 13 | 14 | public MyCustomCell(ATableViewCellStyle style, String reuseIdentifier, Context context) { 15 | super(style, reuseIdentifier, context); 16 | } 17 | 18 | public MyCustomCell(Context context) { 19 | super(context); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/fragments/BaseListFragment.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.fragments; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.view.LayoutInflater; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.FrameLayout; 9 | 10 | import com.actionbarsherlock.app.SherlockFragment; 11 | import com.nakardo.atableview.demo.activities.MainActivity; 12 | import com.nakardo.atableview.demo.interfaces.TableViewConfigurationInterface; 13 | import com.nakardo.atableview.protocol.ATableViewDataSource; 14 | import com.nakardo.atableview.protocol.ATableViewDelegate; 15 | import com.nakardo.atableview.view.ATableView; 16 | import com.slidingmenu.lib.SlidingMenu; 17 | 18 | public abstract class BaseListFragment extends SherlockFragment implements TableViewConfigurationInterface { 19 | protected MainActivity mFragmentContainer; 20 | protected ATableView mTableView; 21 | 22 | protected void createTableView() { 23 | mTableView = new ATableView(mFragmentContainer.mTableViewStyle, getActivity()); 24 | mTableView.setSeparatorStyle(mFragmentContainer.mSeparatorStyle); 25 | mTableView.setAllowsSelection(mFragmentContainer.mAllowsSelection); 26 | mTableView.setAllowsMultipleSelection(mFragmentContainer.mAllowsMultipleSelection); 27 | mTableView.setDataSource(getDataSource()); 28 | mTableView.setDelegate(getDelegate()); 29 | 30 | ViewGroup container = (ViewGroup) getView(); 31 | container.addView(mTableView); 32 | } 33 | 34 | public abstract ATableViewDataSource getDataSource(); 35 | 36 | public ATableViewDelegate getDelegate() { 37 | return new ATableViewDelegate(); 38 | } 39 | 40 | @Override 41 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 42 | FrameLayout view = new FrameLayout(getActivity()); 43 | return view; 44 | } 45 | 46 | @Override 47 | public void onActivityCreated(Bundle savedInstanceState) { 48 | super.onActivityCreated(savedInstanceState); 49 | createTableView(); 50 | 51 | // dismiss menu if it's currently showing, it reduces animation glitch while creating fragment. 52 | SlidingMenu menu = mFragmentContainer.getSlidingMenu(); 53 | if (menu.isMenuShowing()) { 54 | mFragmentContainer.getSlidingMenu().toggle(); 55 | } 56 | } 57 | 58 | @Override 59 | public void onAttach(Activity activity) { 60 | if (activity instanceof MainActivity) mFragmentContainer = (MainActivity) activity; 61 | else throw new RuntimeException("Fragment must be attached to an instance of MainActivity"); 62 | 63 | super.onAttach(activity); 64 | } 65 | 66 | @Override 67 | public void onTableViewConfigurationChanged() { 68 | ((ViewGroup) getView()).removeView(mTableView); 69 | createTableView(); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/fragments/MenuFragment.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.fragments; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import android.os.Bundle; 8 | import android.support.v4.app.Fragment; 9 | import android.view.ViewGroup; 10 | 11 | import com.nakardo.atableview.foundation.NSIndexPath; 12 | import com.nakardo.atableview.internal.ATableViewCellAccessoryView.ATableViewCellAccessoryType; 13 | import com.nakardo.atableview.protocol.ATableViewDataSource; 14 | import com.nakardo.atableview.protocol.ATableViewDelegate; 15 | import com.nakardo.atableview.view.ATableView; 16 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 17 | import com.nakardo.atableview.view.ATableViewCell; 18 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSeparatorStyle; 19 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellStyle; 20 | 21 | public class MenuFragment extends BaseListFragment { 22 | 23 | // section. 24 | private static final String[] mSectionsTitle = { "Demos", "Style", "Selection Style" }; 25 | private static enum MenuFragmentSection { DEMOS, STYLES, SELECTION }; 26 | 27 | // selections. 28 | private static enum ATableViewDemo { SIMPLE, COMPLEX }; 29 | private static enum ATableViewStyleValue { GROUPED_ETCHED, GROUPED, PLAIN }; 30 | private static enum ATableViewSelectionValue { NONE, SINGLE, MULTIPLE }; 31 | 32 | private List> mRowsText; 33 | 34 | public interface TableViewDemoInterface { 35 | public void onTableViewDemoSelected(Class fragmentClass); 36 | } 37 | 38 | private static List> createRowsTextList() { 39 | List> rows = new ArrayList>(); 40 | 41 | rows.add(Arrays.asList(new String[] { "Simple", "Complex" })); 42 | rows.add(Arrays.asList(new String[] { "Grouped (Etched)", "Grouped", "Plain" })); 43 | rows.add(Arrays.asList(new String[] { "None", "Single", "Multiple" })); 44 | 45 | return rows; 46 | } 47 | 48 | @Override 49 | protected void createTableView() { 50 | mTableView = new ATableView(ATableViewStyle.Plain, getActivity()); 51 | mTableView.setDataSource(new MenuTableViewDataSource()); 52 | mTableView.setDelegate(new MenuTableViewDelegate()); 53 | 54 | ViewGroup container = (ViewGroup) getView(); 55 | container.addView(mTableView); 56 | } 57 | 58 | @Override 59 | public ATableViewDataSource getDataSource() { 60 | return new MenuTableViewDataSource(); 61 | } 62 | 63 | @Override 64 | public ATableViewDelegate getDelegate() { 65 | return new MenuTableViewDelegate(); 66 | } 67 | 68 | @Override 69 | public void onActivityCreated(Bundle savedInstanceState) { 70 | mRowsText = createRowsTextList(); 71 | super.onActivityCreated(savedInstanceState); 72 | } 73 | 74 | private class MenuTableViewDataSource extends ATableViewDataSource { 75 | 76 | private boolean isSelected(NSIndexPath indexPath) { 77 | boolean isSelected = false; 78 | 79 | int row = indexPath.getRow(); 80 | MenuFragmentSection section = MenuFragmentSection.values()[indexPath.getSection()]; 81 | switch (section) { 82 | case STYLES: 83 | ATableViewStyle tableViewStyle = mFragmentContainer.mTableViewStyle; 84 | ATableViewCellSeparatorStyle separatorStyle = mFragmentContainer.mSeparatorStyle; 85 | 86 | ATableViewStyleValue style = ATableViewStyleValue.values()[row]; 87 | switch (style) { 88 | case GROUPED_ETCHED: 89 | isSelected = (tableViewStyle == ATableViewStyle.Grouped && 90 | separatorStyle == ATableViewCellSeparatorStyle.SingleLineEtched); break; 91 | case GROUPED: 92 | isSelected = (tableViewStyle == ATableViewStyle.Grouped && 93 | separatorStyle == ATableViewCellSeparatorStyle.SingleLine); break; 94 | default: 95 | isSelected = (tableViewStyle == ATableViewStyle.Plain); break; 96 | } break; 97 | case SELECTION: 98 | boolean allowsSelection = mFragmentContainer.mAllowsSelection; 99 | boolean allowsMultipleSelection = mFragmentContainer.mAllowsMultipleSelection; 100 | 101 | ATableViewSelectionValue selection = ATableViewSelectionValue.values()[row]; 102 | switch (selection) { 103 | case NONE: isSelected = (!allowsSelection); break; 104 | case SINGLE: isSelected = (allowsSelection && !allowsMultipleSelection); break; 105 | default: isSelected = (allowsSelection && allowsMultipleSelection); break; 106 | } break; 107 | default: break; 108 | } 109 | 110 | return isSelected; 111 | } 112 | 113 | @Override 114 | public ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 115 | ATableViewCell cell = null; 116 | String cellIdentifier = null; 117 | 118 | MenuFragmentSection section = MenuFragmentSection.values()[indexPath.getSection()]; 119 | if (section == MenuFragmentSection.DEMOS) { 120 | cellIdentifier = "SELECTION_CELL"; 121 | 122 | cell = dequeueReusableCellWithIdentifier(cellIdentifier); 123 | if (cell == null) { 124 | cell = new ATableViewCell(ATableViewCellStyle.Default, cellIdentifier, getActivity()); 125 | cell.setAccessoryType(ATableViewCellAccessoryType.DisclosureIndicator); 126 | } 127 | } else { 128 | cellIdentifier = "CHECKED_CELL"; 129 | 130 | cell = dequeueReusableCellWithIdentifier(cellIdentifier); 131 | if (cell == null) { 132 | cell = new ATableViewCell(ATableViewCellStyle.Default, cellIdentifier, getActivity()); 133 | } 134 | 135 | // toogle selection. 136 | ATableViewCellAccessoryType accessoryType = ATableViewCellAccessoryType.None; 137 | if (isSelected(indexPath)) { 138 | accessoryType = ATableViewCellAccessoryType.Checkmark; 139 | } 140 | cell.setAccessoryType(accessoryType); 141 | } 142 | 143 | // set text. 144 | String text = mRowsText.get(indexPath.getSection()).get(indexPath.getRow()); 145 | cell.getTextLabel().setText(text); 146 | 147 | return cell; 148 | } 149 | 150 | @Override 151 | public String titleForHeaderInSection(ATableView tableView, int section) { 152 | return mSectionsTitle[section]; 153 | } 154 | 155 | @Override 156 | public int numberOfSectionsInTableView(ATableView tableView) { 157 | return mSectionsTitle.length; 158 | } 159 | 160 | @Override 161 | public int numberOfRowsInSection(ATableView tableView, int section) { 162 | return mRowsText.get(section).size(); 163 | } 164 | } 165 | 166 | private class MenuTableViewDelegate extends ATableViewDelegate { 167 | 168 | @Override 169 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 170 | int row = indexPath.getRow(); 171 | 172 | MenuFragmentSection section = MenuFragmentSection.values()[indexPath.getSection()]; 173 | switch (section) { 174 | case DEMOS: 175 | Class fragmentClass = null; 176 | 177 | ATableViewDemo demo = ATableViewDemo.values()[row]; 178 | switch (demo) { 179 | case SIMPLE: fragmentClass = SimpleListFragment.class; break; 180 | default: fragmentClass = MultipleStylesListFragment.class; break; 181 | } 182 | 183 | mFragmentContainer.onTableViewDemoSelected(fragmentClass); 184 | break; 185 | case STYLES: 186 | ATableViewStyle tableViewStyle = ATableViewStyle.Grouped; 187 | ATableViewCellSeparatorStyle separatorStyle = ATableViewCellSeparatorStyle.SingleLine; 188 | 189 | ATableViewStyleValue style = ATableViewStyleValue.values()[row]; 190 | switch (style) { 191 | case GROUPED_ETCHED: separatorStyle = ATableViewCellSeparatorStyle.SingleLineEtched; break; 192 | case GROUPED: break; 193 | default: tableViewStyle = ATableViewStyle.Plain; break; 194 | } 195 | 196 | mFragmentContainer.mTableViewStyle = tableViewStyle; 197 | mFragmentContainer.mSeparatorStyle = separatorStyle; 198 | 199 | mTableView.reloadData(); mFragmentContainer.onTableViewConfigurationChanged(); 200 | break; 201 | case SELECTION: 202 | boolean allowsSelection = true, allowsMultipleSelection = false; 203 | 204 | ATableViewSelectionValue selection = ATableViewSelectionValue.values()[row]; 205 | switch (selection) { 206 | case NONE: allowsSelection = false; break; 207 | case MULTIPLE: allowsMultipleSelection = true; break; 208 | default: break; 209 | } 210 | 211 | mFragmentContainer.mAllowsSelection = allowsSelection; 212 | mFragmentContainer.mAllowsMultipleSelection = allowsMultipleSelection; 213 | 214 | mTableView.reloadData(); mFragmentContainer.onTableViewConfigurationChanged(); 215 | break; 216 | default: break; 217 | } 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/fragments/MultipleStylesListFragment.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.fragments; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import android.graphics.drawable.Drawable; 8 | import android.os.Bundle; 9 | import android.text.TextUtils.TruncateAt; 10 | import android.widget.ImageView; 11 | import android.widget.LinearLayout; 12 | import android.widget.ListView; 13 | import android.widget.TextView; 14 | import android.widget.Toast; 15 | 16 | import com.nakardo.atableview.demo.R; 17 | import com.nakardo.atableview.demo.cells.MyCustomCell; 18 | import com.nakardo.atableview.foundation.NSIndexPath; 19 | import com.nakardo.atableview.internal.ATableViewCellAccessoryView.ATableViewCellAccessoryType; 20 | import com.nakardo.atableview.protocol.ATableViewDataSource; 21 | import com.nakardo.atableview.protocol.ATableViewDataSourceExt; 22 | import com.nakardo.atableview.protocol.ATableViewDelegate; 23 | import com.nakardo.atableview.view.ATableView; 24 | import com.nakardo.atableview.view.ATableViewCell; 25 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSelectionStyle; 26 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellStyle; 27 | 28 | public class MultipleStylesListFragment extends BaseListFragment { 29 | private List> mCapitals; 30 | private List> mProvinces; 31 | private String[] mRegions = { 32 | "Northwest", "Gran Chaco", "Mesopotamia", "Pampas", "Cuyo", "Patagonia", "Capital City", "About" 33 | }; 34 | private String[] mNotes = { 35 | null, "Southwestern Santiago del Estero is sometimes considered part of the Sierras area.", 36 | null, "Southern part of La Pampa is sometimes called Dry Pampa and included in Patagonia.", 37 | "La Rioja is sometimes considered part of Cuyo region instead of the Northwest.", null, 38 | null, null 39 | }; 40 | 41 | private static List> createProvincesList() { 42 | List> provinces = new ArrayList>(); 43 | 44 | provinces.add(Arrays.asList(new String[] { "Jujuy", "Salta", "Tucuman", "Catamarca" })); 45 | provinces.add(Arrays.asList(new String[] { "Formosa", "Chaco", "Santiago del Estero" })); 46 | provinces.add(Arrays.asList(new String[] { "Misiones", "Entre Rios", "Corrientes" })); 47 | provinces.add(Arrays.asList(new String[] { "Cordoba", "Santa Fe", "La Pampa", "Buenos Aires" })); 48 | provinces.add(Arrays.asList(new String[] { "San Juan", "La Rioja", "Mendoza", "San Luis" })); 49 | provinces.add(Arrays.asList(new String[] { "Neuquen", "Chubut", "Santa Cruz", "Tierra del Fuego" })); 50 | provinces.add(Arrays.asList(new String[] { "Autonomous City of Buenos Aires" })); 51 | provinces.add(Arrays.asList(new String[] { "ATableView intends to imitate same object model proposed on UIKit for building tables, " + 52 | "so it's not only limited on theming Android ListView.\n\nCopyright 2012 Diego Acosta\n\n" + 53 | "Contact me at diegonake@gmail.com / @nakardo"})); 54 | 55 | return provinces; 56 | } 57 | 58 | private static List> createCapitalsList() { 59 | List> capitals = new ArrayList>(); 60 | 61 | capitals.add(Arrays.asList(new String[] { "San Salvador de Jujuy", "Salta", "San Miguel de Tucuman", "S.F.V. de Catamarca" })); 62 | capitals.add(Arrays.asList(new String[] { "Formosa", "Resistencia", "Santiago del Estero" })); 63 | capitals.add(Arrays.asList(new String[] { "Posadas", "Parana", "Corrientes" })); 64 | capitals.add(Arrays.asList(new String[] { "Cordoba", "Santa Fe", "Santa Rosa", "Capital Federal" })); 65 | capitals.add(Arrays.asList(new String[] { "San Juan", "La Rioja", "Mendoza", "San Luis" })); 66 | capitals.add(Arrays.asList(new String[] { "Viedma", "Neuquen", "Rawson", "Rio Gallegos", "Ushuaia" })); 67 | 68 | return capitals; 69 | } 70 | 71 | @Override 72 | public ATableViewDataSource getDataSource() { 73 | return new MultipleStylesListDataSource(); 74 | } 75 | 76 | @Override 77 | public ATableViewDelegate getDelegate() { 78 | return new MultipleStylesListDelegate(); 79 | } 80 | 81 | @Override 82 | public void onActivityCreated(Bundle savedInstanceState) { 83 | mCapitals = createCapitalsList(); 84 | mProvinces = createProvincesList(); 85 | 86 | super.onActivityCreated(savedInstanceState); 87 | } 88 | 89 | private class MultipleStylesListDataSource extends ATableViewDataSourceExt { 90 | 91 | private Drawable getDrawableForRowAtIndexPath(NSIndexPath indexPath) { 92 | Drawable drawable = null; 93 | switch (indexPath.getRow()) { 94 | case 0: drawable = getResources().getDrawable(R.drawable.san_juan); break; 95 | case 1: drawable = getResources().getDrawable(R.drawable.la_rioja); break; 96 | case 2: drawable = getResources().getDrawable(R.drawable.mendoza); break; 97 | default:drawable = getResources().getDrawable(R.drawable.san_luis); 98 | } 99 | 100 | return drawable; 101 | } 102 | 103 | private void setupImageView(ATableViewCell cell, NSIndexPath indexPath) { 104 | ImageView imageView = cell.getImageView(); 105 | if (indexPath.getSection() == 4) { 106 | int paddingLeft = (int) Math.ceil(8 * getResources().getDisplayMetrics().density); 107 | imageView.setPadding(paddingLeft, 0, 0, 0); 108 | imageView.setImageDrawable(getDrawableForRowAtIndexPath(indexPath)); 109 | } else { 110 | imageView.setPadding(0, 0, 0, 0); 111 | imageView.setImageDrawable(null); 112 | } 113 | } 114 | 115 | private void setupLayout(ATableViewCell cell, NSIndexPath indexPath) { 116 | TextView textLabel = (TextView) cell.findViewById(R.id.textLabel); 117 | 118 | int maxLines = 1; 119 | TruncateAt truncateAt = TruncateAt.END; 120 | LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) textLabel.getLayoutParams(); 121 | params.topMargin = params.bottomMargin = 0; 122 | 123 | // add multiline to textView apart from WRAP_CONTENT to make height dynamic. 124 | if (indexPath.getSection() == 7) { 125 | maxLines = Integer.MAX_VALUE; 126 | params.topMargin = (int) getResources().getDimension(R.dimen.atv_cell_content_margin); 127 | params.bottomMargin = (int) getResources().getDimension(R.dimen.atv_cell_content_margin); 128 | truncateAt = null; 129 | } 130 | 131 | textLabel.setLayoutParams(params); 132 | textLabel.setMaxLines(maxLines); 133 | textLabel.setEllipsize(truncateAt); 134 | } 135 | 136 | @Override 137 | public ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 138 | String cellIdentifier = "CellIdentifier0"; 139 | ATableViewCellStyle cellStyle = ATableViewCellStyle.Default; 140 | ATableViewCellAccessoryType accessoryType = ATableViewCellAccessoryType.None; 141 | ATableViewCellSelectionStyle selectionStyle = ATableViewCellSelectionStyle.Blue; 142 | 143 | // set proper style and identifier for cells on each section. 144 | int section = indexPath.getSection(); 145 | if (section == 0) { 146 | cellIdentifier = "CellIdentifier1"; 147 | cellStyle = ATableViewCellStyle.Subtitle; 148 | accessoryType = ATableViewCellAccessoryType.DisclosureIndicator; 149 | } else if (section == 1) { 150 | cellIdentifier = "CellIdentifier2"; 151 | cellStyle = ATableViewCellStyle.Value1; 152 | accessoryType = ATableViewCellAccessoryType.DisclosureButton; 153 | } else if (section == 2) { 154 | cellIdentifier = "CellIdentifier3"; 155 | cellStyle = ATableViewCellStyle.Value2; 156 | accessoryType = ATableViewCellAccessoryType.Checkmark; 157 | } else if (section == 5) { 158 | cellIdentifier = "CustomCellIdentifier"; 159 | selectionStyle = ATableViewCellSelectionStyle.Gray; 160 | } else if (section == 7) { 161 | selectionStyle = ATableViewCellSelectionStyle.None; 162 | } 163 | 164 | // get row data. 165 | int row = indexPath.getRow(); 166 | String province = mProvinces.get(section).get(row); 167 | 168 | ATableViewCell cell = null; 169 | if (section != 5) { 170 | cell = dequeueReusableCellWithIdentifier(cellIdentifier); 171 | if (cell == null) { 172 | cell = new ATableViewCell(cellStyle, cellIdentifier, getActivity()); 173 | } 174 | 175 | cell.setSelectionStyle(selectionStyle); 176 | cell.setAccessoryType(accessoryType); 177 | 178 | // imageView 179 | setupImageView(cell, indexPath); 180 | 181 | // textLabel 182 | cell.getTextLabel().setText(province); 183 | 184 | // detailTextLabel 185 | TextView detailTextLabel = cell.getDetailTextLabel(); 186 | if (detailTextLabel != null) { 187 | String capital = mCapitals.get(section).get(row); 188 | detailTextLabel.setText(capital); 189 | } 190 | 191 | setupLayout(cell, indexPath); 192 | } else { 193 | MyCustomCell customCell = (MyCustomCell)dequeueReusableCellWithIdentifier(cellIdentifier); 194 | if (cell == null) { 195 | customCell = new MyCustomCell(ATableViewCellStyle.Default, cellIdentifier, getActivity()); 196 | customCell.setSelectionStyle(selectionStyle); 197 | customCell.setAccessoryType(accessoryType); 198 | } 199 | 200 | // customLabel 201 | customCell.getTextLabel().setText(province); 202 | 203 | cell = customCell; 204 | } 205 | 206 | return cell; 207 | } 208 | 209 | @Override 210 | public int numberOfRowsInSection(ATableView tableView, int section) { 211 | return mProvinces.get(section).size(); 212 | } 213 | 214 | @Override 215 | public int numberOfSectionsInTableView(ATableView tableView) { 216 | return mRegions.length; 217 | } 218 | 219 | @Override 220 | public String titleForHeaderInSection(ATableView tableView, int section) { 221 | return mRegions[section]; 222 | } 223 | 224 | @Override 225 | public String titleForFooterInSection(ATableView tableView, int section) { 226 | return mNotes[section]; 227 | } 228 | 229 | @Override 230 | public int numberOfRowStyles() { 231 | return 5; 232 | } 233 | 234 | @Override 235 | public int styleForRowAtIndexPath(NSIndexPath indexPath) { 236 | int style = indexPath.getRow(); 237 | 238 | switch (indexPath.getSection()) { 239 | case 3: case 4: case 6: case 7: style = 3; break; // default 240 | case 5: style = 4; break; // custom 241 | default: break; 242 | } 243 | 244 | return style; 245 | } 246 | } 247 | 248 | private class MultipleStylesListDelegate extends ATableViewDelegate { 249 | 250 | @Override 251 | public int heightForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 252 | if (indexPath.getSection() == 7) { 253 | return ListView.LayoutParams.WRAP_CONTENT; 254 | } 255 | 256 | return super.heightForRowAtIndexPath(tableView, indexPath); 257 | } 258 | 259 | @Override 260 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 261 | String text ="Selected IndexPath [" + indexPath.getSection() + "," + indexPath.getRow() + "]"; 262 | Toast toast = Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT); 263 | toast.show(); 264 | } 265 | 266 | @Override 267 | public void accessoryButtonTappedForRowWithIndexPath(ATableView tableView, NSIndexPath indexPath) { 268 | String text = "Tapped DisclosureButton at indexPath [" + indexPath.getSection() + "," + indexPath.getRow() + "]"; 269 | Toast toast = Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT); 270 | toast.show(); 271 | mTableView.clearChoices(); mTableView.requestLayout(); 272 | } 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/fragments/SimpleListFragment.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.fragments; 2 | 3 | import android.view.Gravity; 4 | import android.widget.Toast; 5 | 6 | import com.nakardo.atableview.foundation.NSIndexPath; 7 | import com.nakardo.atableview.protocol.ATableViewDataSource; 8 | import com.nakardo.atableview.protocol.ATableViewDelegate; 9 | import com.nakardo.atableview.view.ATableView; 10 | import com.nakardo.atableview.view.ATableViewCell; 11 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellStyle; 12 | 13 | public class SimpleListFragment extends BaseListFragment { 14 | private static final int ADD_MORE_ROWS_INCREMENT = 100; 15 | private enum SimpleListSection { ROWS, SHOW_SELECTED_ROWS, ADD_MORE }; 16 | 17 | private int mRowCount = ADD_MORE_ROWS_INCREMENT; 18 | 19 | private SimpleListSection getListSection(int section) { 20 | return SimpleListSection.values()[section]; 21 | } 22 | 23 | @Override 24 | public ATableViewDataSource getDataSource() { 25 | return new SimpleListDataSource(); 26 | } 27 | 28 | @Override 29 | public ATableViewDelegate getDelegate() { 30 | return new SimpleListDelegate(); 31 | } 32 | 33 | private class SimpleListDataSource extends ATableViewDataSource { 34 | 35 | @Override 36 | public ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 37 | final String cellIdentifier = "SIMPLE_CELL"; 38 | 39 | ATableViewCell cell = dequeueReusableCellWithIdentifier(cellIdentifier); 40 | if (cell == null) { 41 | cell = new ATableViewCell(ATableViewCellStyle.Default, cellIdentifier, getActivity()); 42 | } 43 | 44 | String text = "Add 100 More Rows"; 45 | 46 | SimpleListSection theSection = getListSection(indexPath.getSection()); 47 | if (theSection == SimpleListSection.ROWS) { 48 | text = "Row " + String.valueOf(indexPath.getRow()); 49 | } else if (theSection == SimpleListSection.SHOW_SELECTED_ROWS) { 50 | text = "Show Selected Rows"; 51 | } 52 | cell.getTextLabel().setText(text); 53 | 54 | return cell; 55 | } 56 | 57 | @Override 58 | public int numberOfSectionsInTableView(ATableView tableView) { 59 | return SimpleListSection.values().length; 60 | } 61 | 62 | @Override 63 | public int numberOfRowsInSection(ATableView tableView, int section) { 64 | int count = mRowCount; 65 | 66 | SimpleListSection theSection = getListSection(section); 67 | if (theSection == SimpleListSection.SHOW_SELECTED_ROWS || 68 | theSection == SimpleListSection.ADD_MORE) { 69 | count = 1; 70 | } 71 | 72 | return count; 73 | } 74 | } 75 | 76 | private class SimpleListDelegate extends ATableViewDelegate { 77 | 78 | public String getIndexPathsText(NSIndexPath[] indexPaths) { 79 | String text = ""; 80 | for (NSIndexPath indexPath : indexPaths) { 81 | text += indexPath.toString() + ", "; 82 | } 83 | 84 | return text.substring(0, text.length() - 2); 85 | } 86 | 87 | @Override 88 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 89 | 90 | SimpleListSection theSection = getListSection(indexPath.getSection()); 91 | if (theSection == SimpleListSection.SHOW_SELECTED_ROWS) { 92 | String text = "Selected indexPaths " + getIndexPathsText(mTableView.getIndexPathsForSelectedRows()); 93 | Toast.makeText(getActivity(), text, Toast.LENGTH_SHORT).show(); 94 | } else if (theSection == SimpleListSection.ADD_MORE) { 95 | mRowCount += ADD_MORE_ROWS_INCREMENT; mTableView.reloadData(); 96 | } 97 | } 98 | 99 | @Override 100 | public void willDisplayCellForRowAtIndexPath(ATableView tableView, ATableViewCell cell, NSIndexPath indexPath) { 101 | int gravity = Gravity.LEFT; 102 | 103 | SimpleListSection theSection = getListSection(indexPath.getSection()); 104 | if (theSection == SimpleListSection.SHOW_SELECTED_ROWS || 105 | theSection == SimpleListSection.ADD_MORE) { 106 | gravity = Gravity.CENTER_HORIZONTAL; 107 | } 108 | 109 | cell.getTextLabel().setGravity(gravity); 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /demo/src/com/nakardo/atableview/demo/interfaces/TableViewConfigurationInterface.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.demo.interfaces; 2 | 3 | 4 | public interface TableViewConfigurationInterface { 5 | public void onTableViewConfigurationChanged(); 6 | } 7 | -------------------------------------------------------------------------------- /library/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 9 | -------------------------------------------------------------------------------- /library/libs/android-support-v4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/libs/android-support-v4.jar -------------------------------------------------------------------------------- /library/project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system edit 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | # 10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home): 11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt 12 | 13 | # Project target. 14 | target=android-8 15 | android.library=true 16 | -------------------------------------------------------------------------------- /library/res/color/atv_default_cell_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_subtitle_cell_detail_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_subtitle_cell_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_value1_cell_detail_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_value1_cell_title_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_value2_cell_detail_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/color/atv_value2_cell_title_text_selector.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/drawable-hdpi/checkmark_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/checkmark_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/checkmark_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/checkmark_normal.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/disclosure_button_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/disclosure_button_normal.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/disclosure_button_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/disclosure_button_pressed.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/disclosure_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/disclosure_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/disclosure_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/disclosure_normal.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/group_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/group_background.png -------------------------------------------------------------------------------- /library/res/drawable-hdpi/plain_header_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-hdpi/plain_header_background.9.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/checkmark_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/checkmark_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/checkmark_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/checkmark_normal.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/disclosure_button_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/disclosure_button_normal.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/disclosure_button_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/disclosure_button_pressed.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/disclosure_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/disclosure_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/disclosure_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/disclosure_normal.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/group_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/group_background.png -------------------------------------------------------------------------------- /library/res/drawable-mdpi/plain_header_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-mdpi/plain_header_background.9.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/checkmark_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/checkmark_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/checkmark_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/checkmark_normal.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/disclosure_button_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/disclosure_button_normal.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/disclosure_button_pressed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/disclosure_button_pressed.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/disclosure_highlighted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/disclosure_highlighted.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/disclosure_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/disclosure_normal.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/group_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/group_background.png -------------------------------------------------------------------------------- /library/res/drawable-xhdpi/plain_header_background.9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nakardo/ATableView/c745d6b057b5958f115d1485968e034ddf2270c4/library/res/drawable-xhdpi/plain_header_background.9.png -------------------------------------------------------------------------------- /library/res/drawable/checkmark.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/drawable/disclosure.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /library/res/drawable/disclosure_button.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /library/res/layout/atv_cell_default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /library/res/layout/atv_cell_subtitle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 32 | 33 | 40 | 41 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /library/res/layout/atv_cell_value1.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 33 | 34 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /library/res/layout/atv_cell_value2.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 13 | 14 | 19 | 20 | 25 | 26 | 32 | 33 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /library/res/layout/atv_grouped_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /library/res/layout/atv_grouped_header.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 13 | 14 | -------------------------------------------------------------------------------- /library/res/layout/atv_plain_header_footer.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 12 | 13 | -------------------------------------------------------------------------------- /library/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | #D9D9D9 5 | #FFFFFF 6 | #9B9B9B 7 | 8 | 9 | #555555 10 | 11 | 12 | #4C566C 13 | 14 | 15 | #F5F5F5 16 | #D9D9D9 17 | #FFFFFF 18 | 19 | 20 | #058CF5 21 | #015EE6 22 | 23 | 24 | #CECECE 25 | #ABABAB 26 | 27 | 28 | #000000 29 | 30 | 31 | #000000 32 | #808080 33 | 34 | 35 | #000000 36 | #385487 37 | 38 | 39 | #526691 40 | #000000 41 | 42 | #FFFFFF 43 | -------------------------------------------------------------------------------- /library/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 1dp 6 | 7dp 7 | 8 | 9 | 18sp 10 | 12dp 11 | 18dp 12 | 24px 13 | 14 | 15 | 8dp 16 | 20dp 17 | 10dp 18 | 19 | 20 | 20sp 21 | 16dp 22 | 6dp 23 | 24 | 25 | 18sp 26 | 10dp 27 | 6dp 28 | 29 | 30 | 10dp 31 | 32 | 33 | 44px 34 | 35 | 36 | 10dp 37 | 38 | 39 | 8dp 40 | 41 | 42 | 20sp 43 | 44 | 45 | 18sp 46 | 14sp 47 | 48 | 49 | 17sp 50 | 17sp 51 | 52 | 53 | 67dp 54 | 12sp 55 | 15sp 56 | -------------------------------------------------------------------------------- /library/res/values/ids.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /library/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 10 | 11 | 17 | 18 | 22 | 23 | 28 | 29 | 34 | 35 | 40 | 41 | 44 | 45 | 49 | 50 | 56 | 57 | 58 | 59 | 63 | 64 | 68 | 69 | 74 | 75 | 79 | 80 | 85 | 86 | 91 | 92 | 96 | 97 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/foundation/NSIndexPath.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.foundation; 2 | 3 | public class NSIndexPath { 4 | private int mSection; 5 | private int mRow; 6 | 7 | private NSIndexPath(int row, int section) { 8 | mRow = row; 9 | mSection = section; 10 | } 11 | 12 | public static NSIndexPath indexPathForRowInSection(int row, int section) { 13 | return new NSIndexPath(row, section); 14 | } 15 | 16 | public int getSection() { 17 | return mSection; 18 | } 19 | 20 | public int getRow() { 21 | return mRow; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "[" + mRow + ", " + mSection + "]"; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewAdapter.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import android.content.res.Resources; 7 | import android.graphics.Rect; 8 | import android.graphics.drawable.ShapeDrawable; 9 | import android.graphics.drawable.StateListDrawable; 10 | import android.view.View; 11 | import android.view.View.MeasureSpec; 12 | import android.view.ViewGroup; 13 | import android.widget.AbsListView; 14 | import android.widget.BaseAdapter; 15 | import android.widget.ListView; 16 | import android.widget.TextView; 17 | 18 | import com.nakardo.atableview.R; 19 | import com.nakardo.atableview.foundation.NSIndexPath; 20 | import com.nakardo.atableview.internal.ATableViewCellAccessoryView.ATableViewCellAccessoryType; 21 | import com.nakardo.atableview.internal.ATableViewCellDrawable.ATableViewCellBackgroundStyle; 22 | import com.nakardo.atableview.internal.ATableViewHeaderFooterCell.ATableViewHeaderFooterCellType; 23 | import com.nakardo.atableview.protocol.ATableViewDataSource; 24 | import com.nakardo.atableview.protocol.ATableViewDataSourceExt; 25 | import com.nakardo.atableview.protocol.ATableViewDelegate; 26 | import com.nakardo.atableview.utils.DrawableUtils; 27 | import com.nakardo.atableview.view.ATableView; 28 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 29 | import com.nakardo.atableview.view.ATableViewCell; 30 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSelectionStyle; 31 | 32 | public class ATableViewAdapter extends BaseAdapter { 33 | private List mHasHeader; 34 | private List mHasFooter; 35 | private List mHeadersHeight; 36 | private List mFootersHeight; 37 | private List mRows; 38 | private List> mRowsHeight; 39 | 40 | private ATableView mTableView; 41 | 42 | private void initialize() { 43 | mHasHeader = new ArrayList(); 44 | mHasFooter = new ArrayList(); 45 | mHeadersHeight = new ArrayList(); 46 | mFootersHeight = new ArrayList(); 47 | mRows = new ArrayList(); 48 | mRowsHeight = new ArrayList>(); 49 | 50 | int sections = 0; 51 | 52 | ATableViewDataSource dataSource = mTableView.getDataSource(); 53 | ATableViewDelegate delegate = mTableView.getDelegate(); 54 | 55 | // datasource & delegate setup. 56 | if (dataSource != null) { 57 | sections = dataSource.numberOfSectionsInTableView(mTableView); 58 | for (int s = 0; s < sections; s++) { 59 | Boolean hasHeader = false, hasFooter = false; 60 | 61 | // mark header if overridden in delegate, otherwise try to pull title instead. 62 | int headerHeight = delegate.heightForHeaderInSection(mTableView, s); 63 | if (headerHeight != ATableViewCell.LayoutParams.UNDEFINED || 64 | dataSource.titleForHeaderInSection(mTableView, s) != null) { 65 | hasHeader = true; 66 | } 67 | mHeadersHeight.add(headerHeight); 68 | mHasHeader.add(hasHeader); 69 | 70 | // mark footer if overridden in delegate, otherwise try to pull title instead. 71 | int footerHeight = delegate.heightForFooterInSection(mTableView, s); 72 | if (footerHeight != ATableViewCell.LayoutParams.UNDEFINED || 73 | dataSource.titleForFooterInSection(mTableView, s) != null) { 74 | hasFooter = true; 75 | } 76 | mFootersHeight.add(footerHeight); 77 | mHasFooter.add(hasFooter); 78 | 79 | // pull row count from datasource. 80 | mRows.add(dataSource.numberOfRowsInSection(mTableView, s)); 81 | 82 | List sectionRowHeights = new ArrayList(); 83 | 84 | // pull row heights. 85 | // closes #23, make sure to pull at least the default height for empty rows sections 86 | int r = mRows.get(s) - 1; 87 | do { 88 | NSIndexPath indexPath = NSIndexPath.indexPathForRowInSection(r, s); 89 | sectionRowHeights.add(delegate.heightForRowAtIndexPath(mTableView, indexPath)); 90 | r--; 91 | } while (r >= 0); 92 | mRowsHeight.add(sectionRowHeights); 93 | } 94 | } 95 | } 96 | 97 | public ATableViewAdapter(ATableView tableView) { 98 | mTableView = tableView; 99 | initialize(); 100 | } 101 | 102 | @Override 103 | public void notifyDataSetChanged() { 104 | initialize(); 105 | super.notifyDataSetChanged(); 106 | } 107 | 108 | public int getContentHeight() { 109 | float height = 0; 110 | 111 | // TODO we're supporting content height only for plain tables, it's more complicated for grouped style 112 | // since we would have to measure all headers & footers values. 113 | if (mTableView.getStyle() == ATableViewStyle.Plain) { 114 | float density = mTableView.getResources().getDisplayMetrics().density; 115 | 116 | // rows. 117 | for (List sectionHeights : mRowsHeight) { 118 | for (int rowHeight : sectionHeights) { 119 | height += rowHeight * density; 120 | } 121 | } 122 | 123 | // headers. 124 | for (int section = 0; section < mHeadersHeight.size(); section++) { 125 | height += hasHeader(section) ? getHeaderFooterRowHeight(section, false) : 0; 126 | } 127 | 128 | // footers. 129 | for (int section = 0; section < mFootersHeight.size(); section++) { 130 | height += hasFooter(section) ? getHeaderFooterRowHeight(section, true) : 0; 131 | } 132 | 133 | // MAGIC MAGIC MAGIC. for some reason we've to add the row count to the height. 134 | // might it be related with the ListView separators? 135 | height += getCount(); 136 | } 137 | 138 | return (int) Math.floor(height); 139 | } 140 | 141 | public int getLastRowHeight() { 142 | List sectionHeights = mRowsHeight.get(mRowsHeight.size() - 1); 143 | return sectionHeights.get(sectionHeights.size() - 1); 144 | } 145 | 146 | public NSIndexPath getIndexPath(int position) { 147 | // closes #18, set offset in one by default only if we've a header in the very first 148 | // section of the table. 149 | int offset = hasHeader(0) ? 1 : 0, count = 0, limit = 0; 150 | 151 | int sections = mRows.size(); 152 | for (int s = 0; s < sections; s++) { 153 | int rows = mRows.get(s); 154 | 155 | limit += rows + getHeaderFooterCountOffset(s); 156 | if (position < limit) { 157 | // offset is given by current pos, accumulated headers, footers and rows. 158 | int positionWithOffset = position - offset - count; 159 | return NSIndexPath.indexPathForRowInSection(positionWithOffset, s); 160 | } 161 | offset += getHeaderFooterCountOffset(s); 162 | count += rows; 163 | } 164 | 165 | return null; 166 | } 167 | 168 | public boolean hasHeader(int section) { 169 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 170 | return true; 171 | } 172 | 173 | return section < mHasHeader.size() && mHasHeader.get(section); 174 | } 175 | 176 | public boolean hasFooter(int section) { 177 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 178 | return true; 179 | } 180 | 181 | return section < mHasHeader.size() && mHasFooter.get(section); 182 | } 183 | 184 | public boolean isHeaderRow(int position) { 185 | int sections = mRows.size(); 186 | for (int s = 0; s < sections; s++) { 187 | if (hasHeader(s) && position == 0) { 188 | return true; 189 | } 190 | position -= mRows.get(s) + getHeaderFooterCountOffset(s); 191 | } 192 | 193 | return false; 194 | } 195 | 196 | public boolean isFooterRow(int position) { 197 | int positionWithOffset = 0; 198 | 199 | int sections = mRows.size(); 200 | for (int s = 0; s < sections; s++) { 201 | positionWithOffset += mRows.get(s) + getHeaderFooterCountOffset(s); 202 | if (hasFooter(s) && position - positionWithOffset == -1) { 203 | return true; 204 | } 205 | } 206 | 207 | return false; 208 | } 209 | 210 | private boolean isSingleRow(NSIndexPath indexPath) { 211 | return indexPath.getRow() == 0 && mRows.get(indexPath.getSection()) == 1; 212 | } 213 | 214 | private boolean isTopRow(NSIndexPath indexPath) { 215 | return indexPath.getRow() == 0 && mRows.get(indexPath.getSection()) > 1; 216 | } 217 | 218 | private boolean isBottomRow(NSIndexPath indexPath) { 219 | return indexPath.getRow() == mRows.get(indexPath.getSection()) - 1; 220 | } 221 | 222 | private int getMeasuredRowHeight(ATableViewCell cell, NSIndexPath indexPath, boolean cache) { 223 | 224 | // closes #12, use table width instead cell since sometimes returns zero for WRAP_CONTENT height cells. 225 | int widthMeasureSpec = MeasureSpec.makeMeasureSpec(mTableView.getWidth(), MeasureSpec.EXACTLY); 226 | int heightMeasureSpec = MeasureSpec.makeMeasureSpec(AbsListView.LayoutParams.WRAP_CONTENT, MeasureSpec.EXACTLY); 227 | cell.measure(widthMeasureSpec, heightMeasureSpec); 228 | 229 | // add measured height to cache, so we don't have to recalculate every time. 230 | int height = (int) (cell.getMeasuredHeight() / cell.getResources().getDisplayMetrics().density); 231 | if (cache) { 232 | mRowsHeight.get(indexPath.getSection()).set(indexPath.getRow(), height); 233 | } 234 | 235 | return height; 236 | } 237 | 238 | private int getRowHeight(ATableViewCell cell, NSIndexPath indexPath, ATableViewCellBackgroundStyle backgroundStyle) { 239 | Resources res = mTableView.getContext().getResources(); 240 | 241 | // transform height constants into values if we've set so. 242 | // closes #7. it seems Android ~2.2 requires known row height to draw cell background drawable. 243 | int rowHeight = mRowsHeight.get(indexPath.getSection()).get(indexPath.getRow()); 244 | if (rowHeight < 0) { 245 | // cached for performance, it might have some impact if user changes the text after layout. 246 | rowHeight = getMeasuredRowHeight(cell, indexPath, true); 247 | } 248 | rowHeight = (int) Math.ceil(rowHeight * res.getDisplayMetrics().density); 249 | 250 | // add extra height to rows depending on it's style. 251 | Rect padding = ATableViewCellDrawable.getContentPadding(mTableView, backgroundStyle); 252 | rowHeight += padding.top + padding.bottom; 253 | 254 | return rowHeight; 255 | } 256 | 257 | private int getHeaderFooterRowHeight(int section, boolean isFooterRow) { 258 | Resources res = mTableView.getResources(); 259 | 260 | // pull height, it will default on delegate to UNDEFINED if not overridden. 261 | int rowHeight = ATableViewCell.LayoutParams.UNDEFINED; 262 | if (isFooterRow) { 263 | rowHeight = mFootersHeight.get(section); 264 | } else { 265 | rowHeight = mHeadersHeight.get(section); 266 | } 267 | 268 | // if undefined, set a valid height depending on table style, otherwise use overridden value. 269 | if (rowHeight == ATableViewCell.LayoutParams.UNDEFINED) { 270 | if (mTableView.getStyle() == ATableViewStyle.Plain) { 271 | rowHeight = (int) res.getDimension(R.dimen.atv_plain_section_header_height); 272 | } else { 273 | rowHeight = ListView.LayoutParams.WRAP_CONTENT; 274 | } 275 | } 276 | 277 | // convert row height value when an scalar was used. 278 | if (rowHeight > -1) { 279 | rowHeight = (int) Math.ceil(rowHeight * res.getDisplayMetrics().density); 280 | } 281 | 282 | return rowHeight; 283 | } 284 | 285 | private ATableViewCellBackgroundStyle getRowBackgroundStyle(NSIndexPath indexPath) { 286 | ATableViewCellBackgroundStyle backgroundStyle = ATableViewCellBackgroundStyle.Middle; 287 | 288 | if (isSingleRow(indexPath)) { 289 | backgroundStyle = ATableViewCellBackgroundStyle.Single; 290 | } else if (isTopRow(indexPath)) { 291 | backgroundStyle = ATableViewCellBackgroundStyle.Top; 292 | } else if (isBottomRow(indexPath)) { 293 | int section = indexPath.getSection(); 294 | boolean nextSectionHasHeader = section < mRows.size() - 1 && !hasHeader(section + 1); 295 | 296 | // closes #19, plain tables should show separator if next section doesn't have a header. 297 | backgroundStyle = ATableViewCellBackgroundStyle.Bottom; 298 | if (mTableView.getStyle() == ATableViewStyle.Plain && nextSectionHasHeader) { 299 | backgroundStyle = ATableViewCellBackgroundStyle.PlainBottomDoubleLine; 300 | } 301 | } 302 | 303 | return backgroundStyle; 304 | } 305 | 306 | private ATableViewHeaderFooterCell getReusableHeaderFooterCell(View convertView, boolean isFooterRow) { 307 | ATableViewHeaderFooterCell cell = (ATableViewHeaderFooterCell) convertView; 308 | if (cell == null) { 309 | ATableViewHeaderFooterCellType type = ATableViewHeaderFooterCellType.Header; 310 | if (isFooterRow) { 311 | type = ATableViewHeaderFooterCellType.Footer; 312 | } 313 | cell = new ATableViewHeaderFooterCell(type, mTableView); 314 | } 315 | 316 | return cell; 317 | } 318 | 319 | private void setupHeaderFooterRowLayout(ATableViewHeaderFooterCell cell, NSIndexPath indexPath, boolean isFooterRow) { 320 | ATableViewDataSource dataSource = mTableView.getDataSource(); 321 | int section = indexPath.getSection(); 322 | Resources res = mTableView.getResources(); 323 | TextView textLabel = cell.getTextLabel(); 324 | 325 | // get text. 326 | String headerText = null; 327 | if (isFooterRow) { 328 | headerText = dataSource.titleForFooterInSection(mTableView, section); 329 | } else { 330 | headerText = dataSource.titleForHeaderInSection(mTableView, section); 331 | } 332 | textLabel.setText(headerText); 333 | 334 | // setup layout and background depending on table style. 335 | Rect padding = new Rect(); 336 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 337 | boolean hasText = headerText != null && headerText.length() > 0; 338 | 339 | padding.left = padding.right = (int) res.getDimension(R.dimen.atv_grouped_section_header_footer_padding_left_right); 340 | 341 | // if we're on the very first header of the table and it has text, we've to add an extra padding 342 | // on top of the cell. 343 | padding.top = (int) res.getDimension(R.dimen.atv_grouped_section_header_padding_top); 344 | if (!isFooterRow && section == 0 && hasText) { 345 | padding.top = (int) res.getDimension(R.dimen.atv_grouped_section_header_first_row_padding_top); 346 | } 347 | 348 | // if we're on the last footer of the table, extra padding applies here as well. 349 | padding.bottom = (int) res.getDimension(R.dimen.atv_grouped_section_footer_padding_bottom); 350 | if (isFooterRow && section == mRows.size() - 1) { 351 | padding.bottom = (int) res.getDimension(R.dimen.atv_grouped_section_footer_last_row_padding_bottom); 352 | } 353 | 354 | // hide header or footer text if it's null. 355 | int visibility = headerText != null && headerText.length() > 0 ? View.VISIBLE : View.GONE; 356 | textLabel.setVisibility(visibility); 357 | } else { 358 | padding.left = (int) res.getDimension(R.dimen.atv_plain_section_header_padding_left); 359 | padding.right = (int) res.getDimension(R.dimen.atv_plain_section_header_padding_right); 360 | 361 | // set background for plain style. 362 | cell.setBackgroundResource(R.drawable.plain_header_background); 363 | } 364 | cell.setPadding(padding.left, padding.top, padding.right, padding.bottom); 365 | 366 | // setup layout height 367 | // closes #16, we've to set minHeight for grouped headers & footers as well to make it take effect. 368 | int rowHeight = getHeaderFooterRowHeight(indexPath.getSection(), isFooterRow); 369 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 370 | int minHeight = (int) res.getDimension(R.dimen.atv_grouped_section_header_footer_min_height); 371 | cell.setMinimumHeight(rowHeight < minHeight ? rowHeight : minHeight); 372 | } 373 | 374 | ListView.LayoutParams params = new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, rowHeight); 375 | cell.setLayoutParams(params); 376 | } 377 | 378 | private void setupRowLayout(ATableViewCell cell, NSIndexPath indexPath, int rowHeight) { 379 | 380 | // add extra padding for grouped style. 381 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 382 | int margin = (int) cell.getResources().getDimension(R.dimen.atv_cell_grouped_margins); 383 | cell.setPadding(margin, 0, margin, 0); 384 | } 385 | 386 | ListView.LayoutParams params = new ListView.LayoutParams(ListView.LayoutParams.MATCH_PARENT, rowHeight); 387 | cell.setLayoutParams(params); 388 | } 389 | 390 | private void setupRowBackgroundDrawable(ATableViewCell cell, NSIndexPath indexPath, 391 | ATableViewCellBackgroundStyle backgroundStyle, int rowHeight) { 392 | 393 | // setup background drawables. 394 | StateListDrawable drawable = new StateListDrawable(); 395 | 396 | ATableViewCellSelectionStyle selectionStyle = cell.getSelectionStyle(); 397 | if (selectionStyle != ATableViewCellSelectionStyle.None) { 398 | Resources res = mTableView.getContext().getResources(); 399 | 400 | int startColor = res.getColor(R.color.atv_cell_selection_style_blue_start); 401 | int endColor = res.getColor(R.color.atv_cell_selection_style_blue_end); 402 | 403 | if (selectionStyle == ATableViewCellSelectionStyle.Gray) { 404 | startColor = res.getColor(R.color.atv_cell_selection_style_gray_start); 405 | endColor = res.getColor(R.color.atv_cell_selection_style_gray_end); 406 | } 407 | 408 | ShapeDrawable pressed = new ATableViewCellDrawable(mTableView, backgroundStyle, rowHeight, startColor, endColor); 409 | drawable.addState(new int[] { android.R.attr.state_selected }, pressed); 410 | drawable.addState(new int[] { android.R.attr.state_pressed }, pressed); 411 | drawable.addState(new int[] { android.R.attr.state_focused }, pressed); 412 | } 413 | 414 | int color = DrawableUtils.getRowBackgroundColor(mTableView, cell); 415 | ShapeDrawable normal = new ATableViewCellDrawable(mTableView, backgroundStyle, rowHeight, color); 416 | drawable.addState(new int[] {}, normal); 417 | 418 | // when extending 419 | ViewGroup backgroundView = (ViewGroup) cell.getBackgroundView(); 420 | if (backgroundView == null) { 421 | throw new RuntimeException("Cannot find R.id.backgroundView on your cell custom layout, " + 422 | "please add it to remove this error."); 423 | } 424 | backgroundView.setBackgroundDrawable(drawable); 425 | } 426 | 427 | private void setupRowContentView(ATableViewCell cell, NSIndexPath indexPath) { 428 | ATableViewCellBackgroundStyle backgroundStyle = getRowBackgroundStyle(indexPath); 429 | 430 | // set margins accordingly to content view depending on stroke lines thickness. 431 | View contentView = cell.getContentView(); 432 | Rect padding = ATableViewCellDrawable.getContentPadding(mTableView, backgroundStyle); 433 | contentView.setPadding(padding.left, padding.top, padding.right, padding.bottom); 434 | } 435 | 436 | private void setupRowAccessoryButtonDelegateCallback(ATableViewCell cell, final NSIndexPath indexPath) { 437 | ATableViewCellAccessoryType accessoryType = cell.getAccessoryType(); 438 | if (accessoryType == ATableViewCellAccessoryType.DisclosureButton) { 439 | View accessoryView = cell.findViewById(R.id.accessoryView); 440 | accessoryView.setOnClickListener(new View.OnClickListener() { 441 | public void onClick(View v) { 442 | ATableViewDelegate delegate = mTableView.getDelegate(); 443 | delegate.accessoryButtonTappedForRowWithIndexPath(mTableView, indexPath); 444 | } 445 | }); 446 | } 447 | } 448 | 449 | private int getHeaderFooterStyleCount() { 450 | int count = 1; 451 | 452 | // closes #10. getViewTypeCount() is only called once by the adapter even when notifyDataSetChanged is invoked, 453 | // so we've to return header & footer styles even we don't have rows to display. 454 | if (mTableView.getStyle() == ATableViewStyle.Grouped) { 455 | count = 2; 456 | } 457 | 458 | return count; 459 | } 460 | 461 | private int getHeaderFooterCountOffset(int section) { 462 | return (hasHeader(section) ? 1 : 0) + (hasFooter(section) ? 1 : 0); 463 | } 464 | 465 | @Override 466 | public int getCount() { 467 | int count = 0; 468 | 469 | // count is given by number of rows in section plus its header & footer. 470 | for (int s = 0; s < mRows.size(); s++) { 471 | count += mRows.get(s) + getHeaderFooterCountOffset(s); 472 | } 473 | 474 | return count; 475 | } 476 | 477 | @Override 478 | public int getViewTypeCount() { 479 | int count = getHeaderFooterStyleCount(); 480 | 481 | // count must be 1 always, either we don't have any rows, plus the additional count for header & footers. 482 | ATableViewDataSource dataSource = mTableView.getDataSource(); 483 | if (dataSource instanceof ATableViewDataSourceExt) { 484 | // TODO should add custom headers & footers to view count here when supported. 485 | // getViewTypeCount() is called only once, so no effect if this value is changed on runtime by the user. 486 | count += ((ATableViewDataSourceExt) dataSource).numberOfRowStyles(); 487 | } else { 488 | count += 1; 489 | } 490 | 491 | return count; 492 | } 493 | 494 | @Override 495 | public int getItemViewType(int position) { 496 | int viewType = 0; 497 | 498 | int viewTypeCount = getViewTypeCount(); 499 | if (viewTypeCount > 1) { 500 | if (isHeaderRow(position) && mTableView.getStyle() == ATableViewStyle.Grouped) { 501 | viewType = viewTypeCount - 2; // additional style for groped headers. 502 | } else if (isHeaderRow(position) || isFooterRow(position)) { 503 | viewType = viewTypeCount - 1; // for plain tables, headers and footers share same style. 504 | } else { 505 | ATableViewDataSource dataSource = mTableView.getDataSource(); 506 | if (dataSource instanceof ATableViewDataSourceExt) { 507 | NSIndexPath indexPath = getIndexPath(position); 508 | viewType = ((ATableViewDataSourceExt) dataSource).styleForRowAtIndexPath(indexPath); 509 | } 510 | } 511 | } 512 | 513 | return viewType; 514 | } 515 | 516 | @Override 517 | public Object getItem(int position) { 518 | return null; 519 | } 520 | 521 | @Override 522 | public long getItemId(int position) { 523 | return position; 524 | } 525 | 526 | @Override 527 | public View getView(int position, View convertView, ViewGroup parent) { 528 | boolean isHeaderRow = isHeaderRow(position); 529 | boolean isFooterRow = isFooterRow(position); 530 | 531 | NSIndexPath indexPath = getIndexPath(position); 532 | if (isHeaderRow || isFooterRow) { 533 | ATableViewHeaderFooterCell cell = getReusableHeaderFooterCell(convertView, isFooterRow); 534 | 535 | // setup. 536 | setupHeaderFooterRowLayout(cell, indexPath, isFooterRow); 537 | 538 | convertView = cell; 539 | } else { 540 | ATableViewCell cell = (ATableViewCell)convertView; 541 | 542 | ATableViewDataSource dataSource = mTableView.getDataSource(); 543 | dataSource.setReusableCell(cell); 544 | 545 | cell = dataSource.cellForRowAtIndexPath(mTableView, indexPath); 546 | 547 | ATableViewCellBackgroundStyle backgroundStyle = getRowBackgroundStyle(indexPath); 548 | int rowHeight = getRowHeight(cell, indexPath, backgroundStyle); 549 | 550 | // setup. 551 | setupRowLayout(cell, indexPath, rowHeight); 552 | setupRowBackgroundDrawable(cell, indexPath, backgroundStyle, rowHeight); 553 | setupRowContentView(cell, indexPath); 554 | setupRowAccessoryButtonDelegateCallback(cell, indexPath); 555 | 556 | // notify delegate we're about drawing the cell, so it can make changes to layout before drawing. 557 | ATableViewDelegate delegate = mTableView.getDelegate(); 558 | delegate.willDisplayCellForRowAtIndexPath(mTableView, cell, indexPath); 559 | 560 | convertView = cell; 561 | } 562 | 563 | return convertView; 564 | } 565 | 566 | @Override 567 | public boolean isEnabled(int position) { 568 | // TODO disable sounds for header and footer rows, should be changed when supporting clicks on those views. 569 | if (isHeaderRow(position) || isFooterRow(position)) { 570 | return false; 571 | } 572 | 573 | return super.isEnabled(position); 574 | } 575 | } 576 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewCellAccessoryView.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import android.content.Context; 4 | import android.content.res.Resources; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.LinearLayout; 8 | import android.widget.LinearLayout.LayoutParams; 9 | 10 | import com.nakardo.atableview.R; 11 | import com.nakardo.atableview.view.ATableViewCell; 12 | 13 | // TODO this class should be generic, maybe we could change extension into a ViewGroup and place accessory within. 14 | public class ATableViewCellAccessoryView extends ImageView { 15 | public enum ATableViewCellAccessoryType { None, DisclosureIndicator, DisclosureButton, Checkmark }; 16 | 17 | public ATableViewCellAccessoryView(Context context) { 18 | super(context); 19 | } 20 | 21 | public static class Builder { 22 | private ATableViewCell mTableViewCell; 23 | private ATableViewCellAccessoryType mAccessoryType; 24 | 25 | private static ImageView getAccessoryView(ATableViewCell cell, ATableViewCellAccessoryType accessoryType) { 26 | LinearLayout containerView = (LinearLayout) cell.findViewById(R.id.containerView); 27 | 28 | // check if accessoryView already exists for current cell before creating a new instance. 29 | ImageView accessoryView = (ImageView) containerView.findViewById(R.id.accessoryView); 30 | if (accessoryView == null) { 31 | Resources res = cell.getResources(); 32 | 33 | // get marginRight for accessoryView, DisclosureButton has a different one. 34 | LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT); 35 | int marginRight = (int) res.getDimension(R.dimen.atv_cell_content_margin); 36 | if (accessoryType == ATableViewCellAccessoryType.DisclosureButton) { 37 | marginRight = (int) res.getDimension(R.dimen.atv_cell_disclosure_button_margin_right); 38 | } 39 | params.setMargins(0, 0, marginRight, 0); 40 | 41 | // setup. 42 | accessoryView = new ATableViewCellAccessoryView(cell.getContext()); 43 | accessoryView.setId(R.id.accessoryView); 44 | accessoryView.setLayoutParams(params); 45 | 46 | containerView.addView(accessoryView); 47 | } 48 | 49 | return accessoryView; 50 | } 51 | 52 | private static void createAccessoryView(ATableViewCell cell, ATableViewCellAccessoryType accessoryType) { 53 | boolean isClickeable = false; 54 | int visibility = View.VISIBLE; 55 | 56 | // setup accessoryType always. 57 | int resId = android.R.color.transparent; 58 | switch (accessoryType) { 59 | case DisclosureIndicator: 60 | resId = R.drawable.disclosure; 61 | break; 62 | case DisclosureButton: 63 | resId = R.drawable.disclosure_button; 64 | isClickeable = true; 65 | break; 66 | case Checkmark: 67 | resId = R.drawable.checkmark; 68 | break; 69 | default: 70 | visibility = View.GONE; 71 | break; 72 | } 73 | 74 | // get accessoryView for given accessoryType. 75 | ImageView accessoryView = getAccessoryView(cell, accessoryType); 76 | accessoryView.setImageResource(resId); 77 | accessoryView.setClickable(isClickeable); 78 | accessoryView.setVisibility(visibility); 79 | } 80 | 81 | public Builder(ATableViewCell cell) { 82 | mTableViewCell = cell; 83 | } 84 | 85 | public Builder setAccessoryType(ATableViewCellAccessoryType accessoryType) { 86 | mAccessoryType = accessoryType; 87 | return this; 88 | } 89 | 90 | public void create() { 91 | createAccessoryView(mTableViewCell, mAccessoryType); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewCellClickListener.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import android.view.View; 4 | import android.widget.AdapterView; 5 | import android.widget.AdapterView.OnItemClickListener; 6 | 7 | import com.nakardo.atableview.protocol.ATableViewDelegate; 8 | import com.nakardo.atableview.view.ATableView; 9 | import com.nakardo.atableview.view.ATableViewCell; 10 | 11 | public class ATableViewCellClickListener implements OnItemClickListener { 12 | private ATableView mTableView; 13 | 14 | public ATableViewCellClickListener(ATableView tableView) { 15 | mTableView = tableView; 16 | } 17 | 18 | @Override 19 | public void onItemClick(AdapterView adapter, View view, int pos, long id) { 20 | 21 | // make sure we're clicking a cell, do not send callbacks for header or footer rows. 22 | if (view instanceof ATableViewCell) { 23 | 24 | // don't throw up selection events if it's not allowed by the table configuration. 25 | ATableView tableView = (ATableView) view.getParent(); 26 | if (tableView.getAllowsSelection()) { 27 | ATableViewDelegate delegate = mTableView.getDelegate(); 28 | delegate.didSelectRowAtIndexPath(mTableView, mTableView.getInternalAdapter().getIndexPath(pos)); 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewCellContainerView.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import com.nakardo.atableview.view.ATableViewCell; 4 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSelectionStyle; 5 | 6 | import android.content.Context; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | import android.view.ViewParent; 10 | import android.widget.LinearLayout; 11 | 12 | public class ATableViewCellContainerView extends LinearLayout { 13 | 14 | private static ATableViewCell getContainerCell(View view) { 15 | ViewParent parent = view.getParent(); 16 | while (parent != null) { 17 | if (parent instanceof ATableViewCell) return (ATableViewCell) parent; 18 | parent = parent.getParent(); 19 | } 20 | 21 | return null; 22 | } 23 | 24 | public ATableViewCellContainerView(Context context) { 25 | super(context); 26 | } 27 | 28 | public ATableViewCellContainerView(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | } 31 | 32 | @Override 33 | public void setPressed(boolean pressed) { 34 | if (pressed) { 35 | ATableViewCell cell = getContainerCell(this); 36 | if (cell != null && cell.getSelectionStyle() == ATableViewCellSelectionStyle.None) { 37 | return; 38 | } 39 | } 40 | 41 | super.setPressed(pressed); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewCellDrawable.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Canvas; 5 | import android.graphics.LinearGradient; 6 | import android.graphics.Matrix; 7 | import android.graphics.Paint; 8 | import android.graphics.Rect; 9 | import android.graphics.RectF; 10 | import android.graphics.Shader; 11 | import android.graphics.drawable.ShapeDrawable; 12 | import android.graphics.drawable.shapes.RoundRectShape; 13 | import android.graphics.drawable.shapes.Shape; 14 | 15 | import com.nakardo.atableview.R; 16 | import com.nakardo.atableview.utils.DrawableUtils; 17 | import com.nakardo.atableview.view.ATableView; 18 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 19 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSeparatorStyle; 20 | 21 | public class ATableViewCellDrawable extends ShapeDrawable { 22 | 23 | // PlainBottomDoubleLine applies for bottom rows on Plain tables without a section next to it. 24 | public enum ATableViewCellBackgroundStyle { 25 | Single, Top, Middle, Bottom, PlainBottomDoubleLine 26 | }; 27 | 28 | private ATableView mTableView; 29 | private ATableViewCellBackgroundStyle mCellBackgroundStyle; 30 | private int mRowHeight; 31 | private int mStrokeWidth; 32 | 33 | private Paint mSeparatorPaint; 34 | private Paint mTopEtchedPaint; 35 | private Paint mBottomEtchedPaint; 36 | private Paint mBackgroundPaint; 37 | private Paint mSelectedPaint; 38 | 39 | private int mStartColor; 40 | private int mEndColor; 41 | 42 | private static RoundRectShape getShape(ATableView tableView, ATableViewCellBackgroundStyle backgroundStyle) { 43 | ATableViewStyle tableStyle = tableView.getStyle(); 44 | 45 | float[] radius = new float[] { 0, 0, 0, 0, 0, 0, 0, 0 }; 46 | if (tableStyle == ATableViewStyle.Grouped) { 47 | Resources res = tableView.getResources(); 48 | 49 | float radii = Math.round(res.getDimension(R.dimen.atv_grouped_stroke_radius)); 50 | if (backgroundStyle == ATableViewCellBackgroundStyle.Single) { 51 | radius = new float[] { radii, radii, radii, radii, radii, radii, radii, radii }; 52 | } else if (backgroundStyle == ATableViewCellBackgroundStyle.Top) { 53 | radius = new float[] { radii, radii, radii, radii, 0, 0, 0, 0 }; 54 | } else if (backgroundStyle == ATableViewCellBackgroundStyle.Bottom) { 55 | radius = new float[] { 0, 0, 0, 0, radii, radii, radii, radii }; 56 | } 57 | } 58 | 59 | return new RoundRectShape(radius, null, null); 60 | } 61 | 62 | private static boolean isGroupedDoubleLineEtchedRow(ATableView tableView, 63 | ATableViewCellBackgroundStyle backgroundStyle) { 64 | 65 | return tableView.getStyle() == ATableViewStyle.Grouped && 66 | tableView.getSeparatorStyle() == ATableViewCellSeparatorStyle.SingleLineEtched && 67 | (backgroundStyle == ATableViewCellBackgroundStyle.Bottom || 68 | backgroundStyle == ATableViewCellBackgroundStyle.Single); 69 | } 70 | 71 | public static Rect getContentPadding(ATableView tableView, ATableViewCellBackgroundStyle backgroundStyle) { 72 | int strokeWidth = DrawableUtils.getStrokeWidth(tableView.getResources()); 73 | int margins = 0, marginTop = 0, marginBottom = 0; 74 | 75 | // calculate margins to avoid content to overlap with cell stroke lines. 76 | if (tableView.getStyle() == ATableViewStyle.Grouped) { 77 | margins = marginTop = strokeWidth; 78 | 79 | // double lines for etched single / bottom rows, this is a pain in the ass. 80 | if (isGroupedDoubleLineEtchedRow(tableView, backgroundStyle)) { 81 | marginBottom = strokeWidth * 2; 82 | } else if (backgroundStyle == ATableViewCellBackgroundStyle.Single || 83 | backgroundStyle == ATableViewCellBackgroundStyle.Bottom) { 84 | marginBottom = strokeWidth; 85 | } 86 | } else if (backgroundStyle == ATableViewCellBackgroundStyle.Middle || 87 | backgroundStyle == ATableViewCellBackgroundStyle.Bottom) { 88 | marginTop = strokeWidth; 89 | } else if (backgroundStyle == ATableViewCellBackgroundStyle.PlainBottomDoubleLine) { 90 | marginTop = marginBottom = strokeWidth; 91 | } 92 | 93 | return new Rect(margins, marginTop, margins, marginBottom); 94 | } 95 | 96 | public ATableViewCellDrawable(ATableView tableView, ATableViewCellBackgroundStyle backgroundStyle, 97 | int rowHeight, int backgroundColor) { 98 | 99 | super(getShape(tableView, backgroundStyle)); 100 | Resources res = tableView.getResources(); 101 | 102 | mTableView = tableView; 103 | mCellBackgroundStyle = backgroundStyle; 104 | 105 | // Closes #11, even we should be able to pull height from canvas it doesn't work well on ~2.2. 106 | mRowHeight = rowHeight; 107 | 108 | // separator. 109 | mSeparatorPaint = new Paint(getPaint()); 110 | mSeparatorPaint.setColor(DrawableUtils.getSeparatorColor(mTableView)); 111 | 112 | // calculate stroke width. 113 | mStrokeWidth = DrawableUtils.getStrokeWidth(res); 114 | 115 | // etched lines, only for grouped tables, with SingleLineEtched style. 116 | if (mTableView.getStyle() == ATableViewStyle.Grouped && 117 | mTableView.getSeparatorStyle() == ATableViewCellSeparatorStyle.SingleLineEtched) { 118 | int etchedLineColor = res.getColor(R.color.atv_cell_grouped_etched_line); 119 | 120 | mBottomEtchedPaint = new Paint(getPaint()); 121 | mBottomEtchedPaint.setColor(etchedLineColor); 122 | 123 | if (backgroundStyle == ATableViewCellBackgroundStyle.Top || 124 | backgroundStyle == ATableViewCellBackgroundStyle.Single) { 125 | etchedLineColor = res.getColor(R.color.atv_cell_grouped_top_cell_etched_line); 126 | } 127 | mTopEtchedPaint = new Paint(getPaint()); 128 | mTopEtchedPaint.setColor(etchedLineColor); 129 | } 130 | 131 | // background. 132 | mBackgroundPaint = new Paint(getPaint()); 133 | mBackgroundPaint.setColor(backgroundColor); 134 | } 135 | 136 | public ATableViewCellDrawable(ATableView tableView, ATableViewCellBackgroundStyle backgroundStyle, 137 | int rowHeight, int startColor, int endColor) { 138 | 139 | this(tableView, backgroundStyle, rowHeight, android.R.color.transparent); 140 | 141 | // selected. 142 | mSelectedPaint = new Paint(getPaint()); 143 | mStartColor = startColor; 144 | mEndColor = endColor; 145 | } 146 | 147 | private Matrix getSeparatorPaintMatrix(Rect bounds) { 148 | Matrix matrix = new Matrix(); 149 | 150 | if (isGroupedDoubleLineEtchedRow(mTableView, mCellBackgroundStyle)) { 151 | RectF rect = new RectF(0, 0, bounds.right, bounds.bottom - mStrokeWidth); 152 | matrix.setRectToRect(new RectF(0, 0, bounds.right, bounds.bottom), rect, Matrix.ScaleToFit.FILL); 153 | } 154 | 155 | return matrix; 156 | } 157 | 158 | private Matrix getTopEtchedPaintMatrix(Rect bounds) { 159 | Matrix matrix = new Matrix(); 160 | 161 | RectF rect = new RectF(mStrokeWidth, mStrokeWidth, bounds.right - mStrokeWidth, bounds.bottom); 162 | if (isGroupedDoubleLineEtchedRow(mTableView, mCellBackgroundStyle)) { 163 | rect.bottom -= mStrokeWidth * 2; 164 | } 165 | matrix.setRectToRect(new RectF(0, 0, bounds.right, bounds.bottom), rect, Matrix.ScaleToFit.FILL); 166 | 167 | return matrix; 168 | } 169 | 170 | private Matrix getBackgroundPaintMatrix(Rect bounds) { 171 | Matrix matrix = new Matrix(); 172 | 173 | Rect padding = getContentPadding(mTableView, mCellBackgroundStyle); 174 | int paddingTop = padding.top; 175 | if (mTableView.getStyle() == ATableViewStyle.Grouped && 176 | mTableView.getSeparatorStyle() == ATableViewCellSeparatorStyle.SingleLineEtched) { 177 | paddingTop *= 2; 178 | } 179 | RectF rect = new RectF(padding.left, paddingTop, bounds.right - padding.right, bounds.bottom - padding.bottom); 180 | matrix.setRectToRect(new RectF(0, 0, bounds.right, bounds.bottom), rect, Matrix.ScaleToFit.FILL); 181 | 182 | return matrix; 183 | } 184 | 185 | private Matrix getSelectedPaintMatrix(Rect bounds) { 186 | Matrix matrix = new Matrix(); 187 | 188 | Rect padding = getContentPadding(mTableView, mCellBackgroundStyle); 189 | RectF rect = new RectF(padding.left, padding.top, bounds.right - padding.right, bounds.bottom - padding.bottom); 190 | if (isGroupedDoubleLineEtchedRow(mTableView, mCellBackgroundStyle)) { 191 | rect.bottom += mStrokeWidth; 192 | } 193 | matrix.setRectToRect(new RectF(0, 0, bounds.right, bounds.bottom), rect, Matrix.ScaleToFit.FILL); 194 | 195 | return matrix; 196 | } 197 | 198 | @Override 199 | protected void onDraw(Shape shape, Canvas canvas, Paint paint) { 200 | canvas.save(); 201 | Rect bounds = canvas.getClipBounds(); 202 | 203 | // bottom etched line. 204 | if (mBottomEtchedPaint != null) shape.draw(canvas, mBottomEtchedPaint); 205 | canvas.restore(); canvas.save(); 206 | 207 | // separator. 208 | canvas.concat(getSeparatorPaintMatrix(bounds)); 209 | shape.draw(canvas, mSeparatorPaint); 210 | canvas.restore(); canvas.save(); 211 | 212 | // top etched line. 213 | canvas.concat(getTopEtchedPaintMatrix(bounds)); 214 | if (mTopEtchedPaint != null) shape.draw(canvas, mTopEtchedPaint); 215 | canvas.restore(); canvas.save(); 216 | 217 | // background. 218 | canvas.concat(getBackgroundPaintMatrix(bounds)); 219 | shape.draw(canvas, mBackgroundPaint); 220 | canvas.restore(); canvas.save(); 221 | 222 | // selected. 223 | canvas.concat(getSelectedPaintMatrix(bounds)); 224 | if (mSelectedPaint != null) { 225 | 226 | // we'll set the selected color on onDraw event since we don't know drawable height up to here. 227 | Shader shader = new LinearGradient(0, 0, 0, mRowHeight, mStartColor, mEndColor, Shader.TileMode.MIRROR); 228 | mSelectedPaint.setShader(shader); 229 | 230 | shape.draw(canvas, mSelectedPaint); 231 | } 232 | } 233 | } 234 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewHeaderFooterCell.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.widget.FrameLayout; 6 | 7 | import com.nakardo.atableview.R; 8 | import com.nakardo.atableview.uikit.UILabel; 9 | import com.nakardo.atableview.view.ATableView; 10 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 11 | 12 | public class ATableViewHeaderFooterCell extends FrameLayout { 13 | public enum ATableViewHeaderFooterCellType { Header, Footer }; 14 | 15 | private UILabel mTextLabel; 16 | 17 | protected static int getLayout(ATableViewHeaderFooterCellType type, ATableView tableView) { 18 | ATableViewStyle style = tableView.getStyle(); 19 | if (ATableViewStyle.Grouped == style) { 20 | if (ATableViewHeaderFooterCellType.Header == type) { 21 | return R.layout.atv_grouped_header; 22 | } 23 | 24 | return R.layout.atv_grouped_footer; 25 | } 26 | 27 | return R.layout.atv_plain_header_footer; 28 | } 29 | 30 | public ATableViewHeaderFooterCell(ATableViewHeaderFooterCellType type, ATableView tableView) { 31 | super(tableView.getContext()); 32 | LayoutInflater.from(getContext()).inflate(getLayout(type, tableView), this, true); 33 | 34 | mTextLabel = (UILabel) findViewById(R.id.textLabel); 35 | } 36 | 37 | public ATableViewHeaderFooterCell(Context context) { 38 | super(context); 39 | } 40 | 41 | public UILabel getTextLabel() { 42 | return mTextLabel; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/internal/ATableViewPlainFooterDrawable.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.internal; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Canvas; 5 | import android.graphics.Paint; 6 | import android.graphics.drawable.ShapeDrawable; 7 | import android.graphics.drawable.shapes.RectShape; 8 | import android.graphics.drawable.shapes.Shape; 9 | 10 | import com.nakardo.atableview.utils.DrawableUtils; 11 | import com.nakardo.atableview.view.ATableView; 12 | 13 | public class ATableViewPlainFooterDrawable extends ShapeDrawable { 14 | private Paint mStrokePaint; 15 | 16 | private int mStrokeWidth; 17 | private float mStrokeOffset; 18 | 19 | public ATableViewPlainFooterDrawable(ATableView tableView, int rowHeight) { 20 | super(new RectShape()); 21 | 22 | Resources res = tableView.getResources(); 23 | 24 | mStrokeWidth = DrawableUtils.getStrokeWidth(res); 25 | mStrokeOffset = (float) Math.ceil(rowHeight * res.getDisplayMetrics().density) + mStrokeWidth; 26 | 27 | // stroke. 28 | mStrokePaint = new Paint(); 29 | mStrokePaint.setStyle(Paint.Style.STROKE); 30 | mStrokePaint.setStrokeWidth(mStrokeWidth); 31 | mStrokePaint.setColor(DrawableUtils.getSeparatorColor(tableView)); 32 | } 33 | 34 | @Override 35 | protected void onDraw(Shape shape, Canvas canvas, Paint paint) { 36 | float offset = mStrokeWidth / 2; 37 | while (offset < shape.getHeight()) { 38 | canvas.drawLine(0, offset, shape.getWidth(), offset, mStrokePaint); 39 | offset += mStrokeOffset; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/protocol/ATableViewDataSource.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.protocol; 2 | 3 | import com.nakardo.atableview.foundation.NSIndexPath; 4 | import com.nakardo.atableview.view.ATableView; 5 | import com.nakardo.atableview.view.ATableViewCell; 6 | 7 | public abstract class ATableViewDataSource { 8 | private ATableViewCell mReusableCell; 9 | 10 | public abstract ATableViewCell cellForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath); 11 | public abstract int numberOfRowsInSection(ATableView tableView, int section); 12 | 13 | public int numberOfSectionsInTableView(ATableView tableView) { 14 | return 1; 15 | } 16 | 17 | public String titleForHeaderInSection(ATableView tableView, int section) { 18 | return null; 19 | } 20 | 21 | public String titleForFooterInSection(ATableView tableView, int section) { 22 | return null; 23 | } 24 | 25 | public ATableViewCell dequeueReusableCellWithIdentifier(String cellIdentifier) { 26 | if (cellIdentifier != null && mReusableCell != null && 27 | cellIdentifier.equals(mReusableCell.getReuseIdentifier())) { 28 | return mReusableCell; 29 | } 30 | 31 | return null; 32 | } 33 | 34 | public void setReusableCell(ATableViewCell reusableCell) { 35 | mReusableCell = reusableCell; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/protocol/ATableViewDataSourceExt.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.protocol; 2 | 3 | import com.nakardo.atableview.foundation.NSIndexPath; 4 | 5 | public abstract class ATableViewDataSourceExt extends ATableViewDataSource { 6 | public abstract int numberOfRowStyles(); 7 | public abstract int styleForRowAtIndexPath(NSIndexPath indexPath); 8 | } 9 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/protocol/ATableViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.protocol; 2 | 3 | import com.nakardo.atableview.R; 4 | import com.nakardo.atableview.foundation.NSIndexPath; 5 | import com.nakardo.atableview.view.ATableView; 6 | import com.nakardo.atableview.view.ATableViewCell; 7 | 8 | public class ATableViewDelegate { 9 | public int heightForRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 10 | return (int) tableView.getResources().getDimension(R.dimen.atv_cell_default_row_height); 11 | } 12 | 13 | public void willDisplayCellForRowAtIndexPath(ATableView tableView, ATableViewCell cell, NSIndexPath indexPath) { 14 | return; 15 | } 16 | 17 | public int heightForHeaderInSection(ATableView tableView, int section) { 18 | return ATableViewCell.LayoutParams.UNDEFINED; 19 | } 20 | 21 | public int heightForFooterInSection(ATableView tableView, int section) { 22 | return ATableViewCell.LayoutParams.UNDEFINED; 23 | } 24 | 25 | public void didSelectRowAtIndexPath(ATableView tableView, NSIndexPath indexPath) { 26 | return; 27 | } 28 | 29 | public void accessoryButtonTappedForRowWithIndexPath(ATableView tableView, NSIndexPath indexPath) { 30 | return; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/uikit/UILabel.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.uikit; 2 | 3 | import java.io.InputStream; 4 | 5 | import android.content.Context; 6 | import android.content.res.AssetManager; 7 | import android.graphics.Typeface; 8 | import android.util.AttributeSet; 9 | import android.widget.TextView; 10 | 11 | public class UILabel extends TextView { 12 | private static final String BOLD_FONT_PATH = "fonts/Roboto-Bold.ttf"; 13 | private static final String REGULAR_FONT_PATH = "fonts/Roboto-Regular.ttf"; 14 | 15 | private static boolean assetExists(Context context, String path) { 16 | boolean exists = false; 17 | try { 18 | InputStream stream = context.getAssets().open(path); stream.close(); 19 | exists = true; 20 | } catch (Exception e) {} 21 | 22 | return exists; 23 | } 24 | 25 | public UILabel(Context context) { 26 | super(context); 27 | } 28 | 29 | public UILabel(Context context, AttributeSet attrs) { 30 | super(context, attrs); 31 | } 32 | 33 | @Override 34 | public void setTypeface (Typeface tf, int style) { 35 | if (!isInEditMode()) { 36 | String customTypefacePath = REGULAR_FONT_PATH; 37 | if (style == Typeface.BOLD) { 38 | customTypefacePath = BOLD_FONT_PATH; 39 | } 40 | 41 | // load custom font if available on app bundle. 42 | if (assetExists(getContext(), customTypefacePath)) { 43 | AssetManager assets = getContext().getAssets(); 44 | tf = Typeface.createFromAsset(assets, customTypefacePath); 45 | } 46 | 47 | super.setTypeface(tf, style); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/utils/DrawableUtils.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.utils; 2 | 3 | import android.content.res.Resources; 4 | import android.graphics.Bitmap; 5 | import android.graphics.BitmapFactory; 6 | import android.graphics.Shader.TileMode; 7 | import android.graphics.drawable.BitmapDrawable; 8 | import android.graphics.drawable.ColorDrawable; 9 | import android.graphics.drawable.Drawable; 10 | 11 | import com.nakardo.atableview.R; 12 | import com.nakardo.atableview.view.ATableView; 13 | import com.nakardo.atableview.view.ATableView.ATableViewStyle; 14 | import com.nakardo.atableview.view.ATableViewCell; 15 | 16 | public class DrawableUtils { 17 | 18 | public static Drawable getTableBackgroundDrawable(ATableView tableView) { 19 | Drawable drawable = null; 20 | 21 | Resources res = tableView.getResources(); 22 | 23 | // -1 implies no color defined. 24 | int color = tableView.getBackgroundColor(); 25 | if (color == -1) { 26 | if (tableView.getStyle() == ATableViewStyle.Grouped) { 27 | 28 | // closes #20, tiled backgrounds defined on xml doesn't seems to work well on Android ~2.1. 29 | // setup gray striped background for plain style tables. 30 | Bitmap bitmap = BitmapFactory.decodeResource(res, R.drawable.group_background); 31 | 32 | BitmapDrawable bitmapDrawable = new BitmapDrawable(bitmap); 33 | bitmapDrawable.setTileModeX(TileMode.REPEAT); 34 | bitmapDrawable.setTileModeY(TileMode.REPEAT); 35 | 36 | drawable = bitmapDrawable; 37 | } else { 38 | drawable = new ColorDrawable(res.getColor(R.color.atv_plain_background)); 39 | } 40 | } else { 41 | drawable = new ColorDrawable(color); 42 | } 43 | 44 | return drawable; 45 | } 46 | 47 | public static int getRowBackgroundColor(ATableView tableView, ATableViewCell cell) { 48 | Resources res = tableView.getResources(); 49 | 50 | // -1 implies no color defined. 51 | int color = cell.getBackgroundColor(); 52 | if (color == -1) { 53 | int tableBackgroundColor = tableView.getBackgroundColor(); 54 | if (tableBackgroundColor == - 1) { 55 | color = res.getColor(R.color.atv_plain_background); 56 | if (tableView.getStyle() == ATableViewStyle.Grouped) { 57 | color = res.getColor(R.color.atv_cell_grouped_background); 58 | } 59 | } else { 60 | color = tableBackgroundColor; 61 | } 62 | } 63 | 64 | return color; 65 | } 66 | 67 | public static int getStrokeWidth(Resources res) { 68 | return (int) Math.floor(res.getDimension(R.dimen.atv_stroke_width)); 69 | } 70 | 71 | public static int getSeparatorColor(ATableView tableView) { 72 | Resources res = tableView.getResources(); 73 | 74 | // pull color, -1 implies no custom color has being defined so we go with defaults. 75 | int color = tableView.getSeparatorColor(); 76 | if (color == -1) { 77 | color = res.getColor(R.color.atv_plain_separator); 78 | if (tableView.getStyle() == ATableViewStyle.Grouped) { 79 | color = res.getColor(R.color.atv_grouped_separator); 80 | } 81 | } 82 | 83 | return color; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/view/ATableView.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.view; 2 | 3 | import java.util.ArrayList; 4 | 5 | import android.content.Context; 6 | import android.util.AttributeSet; 7 | import android.util.SparseBooleanArray; 8 | import android.view.View; 9 | import android.view.ViewTreeObserver; 10 | import android.widget.AbsListView; 11 | import android.widget.FrameLayout; 12 | import android.widget.HeaderViewListAdapter; 13 | import android.widget.ListView; 14 | 15 | import com.nakardo.atableview.foundation.NSIndexPath; 16 | import com.nakardo.atableview.internal.ATableViewAdapter; 17 | import com.nakardo.atableview.internal.ATableViewCellClickListener; 18 | import com.nakardo.atableview.internal.ATableViewPlainFooterDrawable; 19 | import com.nakardo.atableview.protocol.ATableViewDataSource; 20 | import com.nakardo.atableview.protocol.ATableViewDelegate; 21 | import com.nakardo.atableview.utils.DrawableUtils; 22 | import com.nakardo.atableview.view.ATableViewCell.ATableViewCellSeparatorStyle; 23 | 24 | public class ATableView extends ListView { 25 | private static final ATableViewStyle DEFAULT_STYLE = ATableViewStyle.Plain; 26 | 27 | // UIView 28 | private int mBackgroundColor = -1; 29 | 30 | private ATableViewCellSeparatorStyle mSeparatorStyle = ATableViewCellSeparatorStyle.SingleLine; 31 | private int mSeparatorColor = -1; 32 | private ATableViewStyle mStyle = DEFAULT_STYLE; 33 | private boolean mAllowsSelection = true; 34 | private boolean mAllowsMultipleSelection = false; 35 | private ATableViewDataSource mDataSource; 36 | private ATableViewDelegate mDelegate = new ATableViewDelegate(); 37 | 38 | public enum ATableViewStyle { 39 | Plain, Grouped 40 | }; 41 | 42 | private void setupFooterView(int lastRowHeight) { 43 | 44 | // closes #12, add footer for plain style tables in order to make the effect of repeating 45 | // rows across table height. 46 | if (mStyle == ATableViewStyle.Plain) { 47 | final View footerView = new FrameLayout(getContext()); 48 | 49 | // add listener to resize after layout has been completed. 50 | getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 51 | public void onGlobalLayout() { 52 | getViewTreeObserver().removeGlobalOnLayoutListener(this); 53 | 54 | int footerHeight = getHeight() - getInternalAdapter().getContentHeight(); 55 | AbsListView.LayoutParams params = new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, 56 | footerHeight > 0 ? footerHeight : 0); 57 | footerView.setLayoutParams(params); 58 | } 59 | }); 60 | 61 | footerView.setBackgroundDrawable(new ATableViewPlainFooterDrawable(this, lastRowHeight)); 62 | addFooterView(footerView); 63 | } 64 | } 65 | 66 | private void setupBackgroundDrawable() { 67 | setBackgroundDrawable(DrawableUtils.getTableBackgroundDrawable(this)); 68 | } 69 | 70 | private int getSelectionMode() { 71 | 72 | // well, this is just a workaround since we've two variables in ios and only one in android 73 | // to define selection enabled and multiple selection. 74 | int choiceMode = CHOICE_MODE_SINGLE; 75 | if (mAllowsMultipleSelection) choiceMode = CHOICE_MODE_MULTIPLE; 76 | 77 | return choiceMode; 78 | } 79 | 80 | private void clearSelectedRows() { 81 | clearChoices(); requestLayout(); 82 | } 83 | 84 | public ATableView(ATableViewStyle style, Context context) { 85 | super(context); 86 | mStyle = style; 87 | 88 | setSelector(android.R.color.transparent); 89 | setChoiceMode(getSelectionMode()); 90 | setDivider(null); 91 | setDividerHeight(0); 92 | setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY); 93 | setScrollingCacheEnabled(false); 94 | 95 | setupBackgroundDrawable(); 96 | } 97 | 98 | public ATableView(Context context) { 99 | super(context); 100 | } 101 | 102 | public ATableView(Context context, AttributeSet attrs) { 103 | super(context, attrs); 104 | } 105 | 106 | public ATableView(Context context, AttributeSet attrs, int defStyle) { 107 | super(context, attrs, defStyle); 108 | } 109 | 110 | public int getBackgroundColor() { 111 | return mBackgroundColor; 112 | } 113 | public void setBackgroundColor(int resId) { 114 | mBackgroundColor = resId; setupBackgroundDrawable(); 115 | } 116 | 117 | public ATableViewCellSeparatorStyle getSeparatorStyle() { 118 | return mSeparatorStyle; 119 | } 120 | public void setSeparatorStyle(ATableViewCellSeparatorStyle separatorStyle) { 121 | mSeparatorStyle = separatorStyle; 122 | } 123 | 124 | public int getSeparatorColor() { 125 | return mSeparatorColor; 126 | } 127 | public void setSeparatorColor(int resId) { 128 | mSeparatorColor = resId; 129 | } 130 | 131 | public ATableViewStyle getStyle() { 132 | return mStyle; 133 | } 134 | 135 | public boolean getAllowsSelection() { 136 | return mAllowsSelection; 137 | } 138 | public void setAllowsSelection(boolean allowsSelection) { 139 | mAllowsSelection = allowsSelection; 140 | 141 | if (mAllowsSelection) setChoiceMode(getSelectionMode()); 142 | else setChoiceMode(CHOICE_MODE_NONE); 143 | 144 | clearSelectedRows(); 145 | } 146 | 147 | public boolean getAllowsMultipleSelection() { 148 | return mAllowsMultipleSelection; 149 | } 150 | public void setAllowsMultipleSelection(boolean allowsMultipleSelection) { 151 | mAllowsMultipleSelection = allowsMultipleSelection; 152 | 153 | if (mAllowsSelection) { 154 | setChoiceMode(getSelectionMode()); clearSelectedRows(); 155 | } 156 | } 157 | 158 | public NSIndexPath getIndexPathForSelectedRow() { 159 | NSIndexPath indexPath = null; 160 | 161 | int position = getCheckedItemPosition(); 162 | if (position != INVALID_POSITION) { 163 | indexPath = getInternalAdapter().getIndexPath(position); 164 | } 165 | 166 | return indexPath; 167 | } 168 | 169 | public NSIndexPath[] getIndexPathsForSelectedRows() { 170 | NSIndexPath[] indexPaths = null; 171 | 172 | SparseBooleanArray checkedList = getCheckedItemPositions(); 173 | if (checkedList != null) { 174 | ArrayList indexPathList = new ArrayList(); 175 | 176 | ATableViewAdapter adapter = getInternalAdapter(); 177 | for (int i = 0; i < adapter.getCount(); i++) { 178 | if (checkedList.get(i)) { 179 | indexPathList.add(adapter.getIndexPath(i)); 180 | } 181 | } 182 | 183 | indexPaths = indexPathList.toArray(new NSIndexPath[indexPathList.size()]); 184 | } 185 | 186 | return indexPaths; 187 | } 188 | 189 | public ATableViewDataSource getDataSource() { 190 | return mDataSource; 191 | } 192 | public void setDataSource(ATableViewDataSource dataSource) { 193 | mDataSource = dataSource; 194 | } 195 | 196 | public ATableViewDelegate getDelegate() { 197 | return mDelegate; 198 | } 199 | public void setDelegate(ATableViewDelegate delegate) { 200 | mDelegate = delegate; 201 | } 202 | 203 | public ATableViewAdapter getInternalAdapter() { 204 | 205 | // fixes bugs for tables which includes headers or footers. 206 | ATableViewAdapter adapter = null; 207 | if (getAdapter() instanceof HeaderViewListAdapter) { 208 | HeaderViewListAdapter headerAdapter = (HeaderViewListAdapter) getAdapter(); 209 | adapter = (ATableViewAdapter) headerAdapter.getWrappedAdapter(); 210 | } else { 211 | adapter = (ATableViewAdapter) getAdapter(); 212 | } 213 | 214 | return adapter; 215 | } 216 | 217 | public void reloadData() { 218 | getInternalAdapter().notifyDataSetChanged(); 219 | clearSelectedRows(); 220 | } 221 | 222 | @Override 223 | protected void onAttachedToWindow() { 224 | ATableViewAdapter adapter = new ATableViewAdapter(this); 225 | 226 | // TODO we should handle the case last row is ListView.LayoutParams.WRAP_CONTENT, to get its height. 227 | // setup footer for plain tables to complete its height with empty rows. 228 | setupFooterView(adapter.getLastRowHeight()); 229 | 230 | setAdapter(adapter); 231 | setOnItemClickListener(new ATableViewCellClickListener(this)); 232 | super.onAttachedToWindow(); 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /library/src/com/nakardo/atableview/view/ATableViewCell.java: -------------------------------------------------------------------------------- 1 | package com.nakardo.atableview.view; 2 | 3 | import android.content.Context; 4 | import android.view.LayoutInflater; 5 | import android.view.View; 6 | import android.widget.Checkable; 7 | import android.widget.FrameLayout; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | 11 | import com.nakardo.atableview.R; 12 | import com.nakardo.atableview.internal.ATableViewCellAccessoryView; 13 | import com.nakardo.atableview.internal.ATableViewCellAccessoryView.ATableViewCellAccessoryType; 14 | 15 | public class ATableViewCell extends FrameLayout implements Checkable { 16 | public enum ATableViewCellStyle { Default, Subtitle, Value1, Value2 }; 17 | public enum ATableViewCellSelectionStyle { None, Blue, Gray }; 18 | public enum ATableViewCellSeparatorStyle { None, SingleLine, SingleLineEtched }; 19 | 20 | // UIView 21 | private int mBackgroundColor = -1; 22 | 23 | // internal 24 | private View mContainerView; 25 | private boolean mIsChecked; 26 | 27 | private String mReuseIdentifier; 28 | private TextView mTextLabel; 29 | private TextView mDetailTextLabel; 30 | private ImageView mImageView; 31 | private View mContentView; 32 | private View mBackgroundView; 33 | private ATableViewCellAccessoryType mAccessoryType = ATableViewCellAccessoryType.None; 34 | private ATableViewCellSelectionStyle mSelectionStyle = ATableViewCellSelectionStyle.Blue; 35 | 36 | protected int getLayout(ATableViewCellStyle style) { 37 | switch (style) { 38 | case Subtitle: 39 | return R.layout.atv_cell_subtitle; 40 | case Value1: 41 | return R.layout.atv_cell_value1; 42 | case Value2: 43 | return R.layout.atv_cell_value2; 44 | default: 45 | return R.layout.atv_cell_default; 46 | } 47 | } 48 | 49 | public ATableViewCell(ATableViewCellStyle style, String reuseIdentifier, Context context) { 50 | super(context); 51 | LayoutInflater.from(context).inflate(getLayout(style), this, true); 52 | 53 | mReuseIdentifier = reuseIdentifier; 54 | mTextLabel = (TextView)findViewById(R.id.textLabel); 55 | mDetailTextLabel = (TextView)findViewById(R.id.detailTextLabel); 56 | mImageView = (ImageView)findViewById(R.id.imageView); 57 | mContentView = findViewById(R.id.contentView); 58 | mBackgroundView = findViewById(R.id.backgroundView); 59 | mContainerView = findViewById(R.id.containerView); 60 | } 61 | 62 | public ATableViewCell(Context context) { 63 | super(context); 64 | } 65 | 66 | public View getInternalContainerView() { 67 | return mContainerView; 68 | } 69 | 70 | public int getBackgroundColor() { 71 | return mBackgroundColor; 72 | } 73 | public void setBackgroundColor(int resId) { 74 | mBackgroundColor = resId; 75 | } 76 | 77 | public String getReuseIdentifier() { 78 | return mReuseIdentifier; 79 | } 80 | 81 | public TextView getTextLabel() { 82 | return mTextLabel; 83 | } 84 | 85 | public TextView getDetailTextLabel() { 86 | return mDetailTextLabel; 87 | } 88 | 89 | public ImageView getImageView() { 90 | return mImageView; 91 | } 92 | 93 | public View getContentView() { 94 | return mContentView; 95 | } 96 | 97 | public View getBackgroundView() { 98 | return mBackgroundView; 99 | } 100 | public void setBackgroundView(View backgroundView) { 101 | mBackgroundView = backgroundView; 102 | } 103 | 104 | public ATableViewCellAccessoryType getAccessoryType() { 105 | return mAccessoryType; 106 | } 107 | 108 | public void setAccessoryType(ATableViewCellAccessoryType accessoryType) { 109 | mAccessoryType = accessoryType; 110 | 111 | // TODO build accessory view, it should support building accessories from any view. 112 | ATableViewCellAccessoryView.Builder builder = new ATableViewCellAccessoryView.Builder(this); 113 | builder.setAccessoryType(accessoryType); 114 | builder.create(); 115 | } 116 | 117 | public ATableViewCellSelectionStyle getSelectionStyle() { 118 | return mSelectionStyle; 119 | } 120 | public void setSelectionStyle(ATableViewCellSelectionStyle selectionStyle) { 121 | mSelectionStyle = selectionStyle; 122 | } 123 | 124 | public class LayoutParams { 125 | public static final int UNDEFINED = -3; 126 | } 127 | 128 | @Override 129 | public void setPressed(boolean pressed) { 130 | 131 | // disable selection when it's not allowed by the table configuration. 132 | ATableView tableView = (ATableView) getParent(); 133 | super.setPressed(tableView.getAllowsSelection() ? pressed : false); 134 | } 135 | 136 | @Override 137 | public void setSelected(boolean selected) { 138 | 139 | // disable selection if selectionStyle is none. 140 | super.setSelected(mSelectionStyle != ATableViewCellSelectionStyle.None ? selected : false); 141 | } 142 | 143 | @Override 144 | public boolean isChecked() { 145 | return mIsChecked; 146 | } 147 | 148 | @Override 149 | public void setChecked(boolean checked) { 150 | mIsChecked = checked; setSelected(mIsChecked); 151 | } 152 | 153 | @Override 154 | public void toggle() { 155 | mIsChecked = !mIsChecked; setSelected(mIsChecked); 156 | } 157 | } 158 | --------------------------------------------------------------------------------