功能列表:
- 橫向顯示
- 子視圖的寬度設置有效
- match_parent : 與HorizontalListView的寬度相同
- wrap_content : 寬度為自己所需寬度
- 固定數值 : 寬度為固定值
- 支持setSelection(int) setSelectionFromLeft(int, int)
- 支持scrollTo(int)
- 支持RequestFreeze
- 通常用於刷新數據,固定當前子視圖的位置。
- 支持OnScrollListener
請從github上下載源碼。本文后面貼的代碼不同步更新了。
HorzitontalListView Source code
嘮叨一下,想直接看源碼的可以跳過
水平的ListView控件。很常用。但目前android widget並沒有該控件。
之前用過HorizontalScrollView 寫過。改動起來很麻煩。自己寫Adapter 自己寫Recycle 以及常用方法如setSelection() 等等。
打算照着ListView的思路寫一個Horizontal的。上網搜搜發現github上有一個兄弟寫了。網址附上:https://github.com/dinocore1/DevsmartLib-Android/tree/master/demo/src/com/devsmart/demo
用的時候發現有bug,而且顯示效果並不是我想要的(與ListView相比較,僅僅是方向變了)。而且並不支持setSelection(int) 故動手改了改,
尊重原著,注釋緊將版本號改為1.5.1(原為1.5)
變量名與取值盡量與ListView一致,方便閱讀。
並未實現所有接口,使用的時候注意哦。
code:

1 /*
2 * HorizontalListView.java v1.5.1 3 * 4 * Copyright (c) 2011 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 * THE SOFTWARE. 23 * 24 */
25
26 import java.util.LinkedList; 27 import java.util.Queue; 28
29 import android.content.Context; 30 import android.database.DataSetObserver; 31 import android.graphics.Rect; 32 import android.util.AttributeSet; 33 import android.view.GestureDetector; 34 import android.view.GestureDetector.OnGestureListener; 35 import android.view.MotionEvent; 36 import android.view.View; 37 import android.view.ViewGroup; 38 import android.widget.AbsListView; 39 import android.widget.AdapterView; 40 import android.widget.ListAdapter; 41 import android.widget.Scroller; 42
43 public class HorizontalListView extends AdapterView<ListAdapter> { 44
45 /**
46 * Regular layout - usually an unsolicited layout from the view system 47 */
48 static final int LAYOUT_NORMAL = 0; 49
50 /**
51 * Make a mSelectedItem appear in a specific location and build the rest of 52 * the views from there. The top is specified by mSpecificTop. 53 */
54 static final int LAYOUT_SPECIFIC = 4; 55
56 /**
57 * Layout to sync as a result of a data change. Restore mSyncPosition to have its top 58 * at mSpecificTop 59 */
60 static final int LAYOUT_SYNC = 5; 61
62 /**
63 * Controls how the next layout will happen 64 */
65 int mLayoutMode = LAYOUT_NORMAL; 66
67
68 public boolean mAlwaysOverrideTouch = true; 69
70 protected ListAdapter mAdapter; 71 protected Scroller mScroller; 72 private GestureDetector mGesture; 73
74 private int mLeftViewIndex = -1; 75 private int mRightViewIndex = 0; 76
77 private int mMaxX = Integer.MAX_VALUE; 78 private int mMinX = Integer.MIN_VALUE; 79 protected int mCurrentX; 80 protected int mNextX; 81 private int mDisplayOffset = 0; 82
83 private Queue<View> mRemovedViewQueue = new LinkedList<View>(); 84
85 private OnItemSelectedListener mOnItemSelected; 86 private OnItemClickListener mOnItemClicked; 87 private OnItemLongClickListener mOnItemLongClicked; 88
89 private boolean mDataChanged = false; 90
91 private int mFirstPosition = 0; 92
93 public HorizontalListView(Context context, AttributeSet attrs) { 94 super(context, attrs); 95 initView(); 96 } 97
98 private synchronized void initView() { 99 mLeftViewIndex = -1; 100 mRightViewIndex = 0; 101 mDisplayOffset = 0; 102 mCurrentX = 0; 103 mNextX = 0; 104 mFirstPosition = 0; 105 mSpecificPosition = 0; 106 mSpecificLeft = 0; 107 mMaxX = Integer.MAX_VALUE; 108 mMinX = Integer.MIN_VALUE; 109 mScroller = new Scroller(getContext()); 110 mGesture = new GestureDetector(getContext(), mOnGesture); 111 } 112
113 private synchronized void initViewForSpecific() { 114 mLeftViewIndex = mSpecificPosition - 1; 115 mRightViewIndex = mSpecificPosition + 1; 116 mFirstPosition = mSpecificPosition; 117 mDisplayOffset = 0; 118 mCurrentX = 0; 119 mNextX = 0; 120 mMaxX = Integer.MAX_VALUE; 121 mScroller = new Scroller(getContext()); 122 mGesture = new GestureDetector(getContext(), mOnGesture); 123 } 124
125 @Override 126 public void setOnItemSelectedListener( 127 AdapterView.OnItemSelectedListener listener) { 128 mOnItemSelected = listener; 129 } 130
131 @Override 132 public void setOnItemClickListener(AdapterView.OnItemClickListener listener) { 133 mOnItemClicked = listener; 134 } 135
136 @Override 137 public void setOnItemLongClickListener( 138 AdapterView.OnItemLongClickListener listener) { 139 mOnItemLongClicked = listener; 140 } 141
142 private DataSetObserver mDataObserver = new DataSetObserver() { 143
144 @Override 145 public void onChanged() { 146 synchronized (HorizontalListView.this) { 147 mDataChanged = true; 148 } 149 invalidate(); 150 requestLayout(); 151 } 152
153 @Override 154 public void onInvalidated() { 155 reset(); 156 invalidate(); 157 requestLayout(); 158 } 159
160 }; 161
162
163
164 private int mSpecificLeft; 165
166 private int mSpecificPosition; 167
168 @Override 169 public ListAdapter getAdapter() { 170 return mAdapter; 171 } 172
173 @Override 174 public View getSelectedView() { 175 // TODO: implement
176 return null; 177 } 178
179 @Override 180 public void setAdapter(ListAdapter adapter) { 181 if (mAdapter != null) { 182 mAdapter.unregisterDataSetObserver(mDataObserver); 183 } 184 mAdapter = adapter; 185 mAdapter.registerDataSetObserver(mDataObserver); 186 reset(); 187 } 188
189 private synchronized void reset() { 190 initView(); 191 removeAllViewsInLayout(); 192 requestLayout(); 193 } 194
195 @Override 196 public int getFirstVisiblePosition() { 197 return mFirstPosition; 198 } 199
200 @Override 201 public void setSelection(int position) { 202 setSelectionFromLeft(position, 0); 203 } 204
205 /**
206 * Sets the selected item and positions the selection y pixels from the left edge 207 * of the ListView. (If in touch mode, the item will not be selected but it will 208 * still be positioned appropriately.) 209 * 210 * @param position Index (starting at 0) of the data item to be selected. 211 * @param x The distance from the left edge of the ListView (plus padding) that the 212 * item will be positioned. 213 */
214 public void setSelectionFromLeft(int position, int x) { 215 if (mAdapter == null) { 216 return; 217 } 218
219 if (!isInTouchMode()) { 220 position = lookForSelectablePosition(position, true); 221 } 222
223 if (position >= 0) { 224 mLayoutMode = LAYOUT_SPECIFIC; 225 mSpecificPosition = position; 226 mSpecificLeft = getPaddingLeft() + x; 227
228 requestLayout(); 229 } 230 } 231
232
233 /**
234 * Find a position that can be selected (i.e., is not a separator). 235 * 236 * @param position The starting position to look at. 237 * @param lookDown Whether to look down for other positions. 238 * @return The next selectable position starting at position and then searching either up or 239 * down. Returns {@link #INVALID_POSITION} if nothing can be found. 240 */
241 int lookForSelectablePosition(int position, boolean lookDown) { 242 final ListAdapter adapter = mAdapter; 243 if (adapter == null || isInTouchMode()) { 244 return INVALID_POSITION; 245 } 246
247 final int count = adapter.getCount(); 248 if (!adapter.areAllItemsEnabled()) { 249 if (lookDown) { 250 position = Math.max(0, position); 251 while (position < count && !adapter.isEnabled(position)) { 252 position++; 253 } 254 } else { 255 position = Math.min(position, count - 1); 256 while (position >= 0 && !adapter.isEnabled(position)) { 257 position--; 258 } 259 } 260
261 if (position < 0 || position >= count) { 262 return INVALID_POSITION; 263 } 264 return position; 265 } else { 266 if (position < 0 || position >= count) { 267 return INVALID_POSITION; 268 } 269 return position; 270 } 271 } 272
273 private void addAndMeasureChild(final View child, int viewPos) { 274 LayoutParams params = (LayoutParams) child.getLayoutParams(); 275 params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, 276 ViewGroup.LayoutParams.MATCH_PARENT); 277
278 addViewInLayout(child, viewPos, params, true); 279
280 int heightMeasureSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(), 281 MeasureSpec.EXACTLY); 282 int childHeightSpec = ViewGroup.getChildMeasureSpec(heightMeasureSpec, 283 getPaddingTop() + getPaddingBottom(), params.height); 284 int childWidthSpec = MeasureSpec.makeMeasureSpec( 285 params.width > 0 ? params.width : 0, MeasureSpec.UNSPECIFIED); 286 child.measure(childWidthSpec, childHeightSpec); 287
288 } 289
290
291 @Override 292 protected synchronized void onLayout(boolean changed, int left, int top, 293 int right, int bottom) { 294 super.onLayout(changed, left, top, right, bottom); 295
296 if (mAdapter == null) { 297 return; 298 } 299
300 if (mDataChanged) { 301 int oldCurrentX = mCurrentX; 302 initView(); 303 removeAllViewsInLayout(); 304 mNextX = oldCurrentX; 305 mDataChanged = false; 306 } 307
308 if (mScroller.computeScrollOffset()) { 309 int scrollx = mScroller.getCurrX(); 310 mNextX = scrollx; 311 } 312
313 if (mNextX <= mMinX) { 314 mNextX = mMinX; 315 mScroller.forceFinished(true); 316 } 317 if (mNextX >= mMaxX) { 318 mNextX = mMaxX; 319 mScroller.forceFinished(true); 320 } 321
322 int dx = 0; 323 switch (mLayoutMode) { 324 case LAYOUT_SPECIFIC: 325 dx = mSpecificLeft; 326 detachAllViewsFromParent(); 327 initViewForSpecific(); 328 fillSpecific(mSpecificPosition, dx); 329 positionItems(dx); 330
331 mNextX = mSpecificLeft; 332 mSpecificPosition = -1; 333 mSpecificLeft = 0; 334 break; 335 default: 336 dx = mCurrentX - mNextX; 337 removeNonVisibleItems(dx); 338 fillList(dx); 339 positionItems(dx); 340 } 341
342 mCurrentX = mNextX; 343 mLayoutMode = LAYOUT_NORMAL; 344
345 if (!mScroller.isFinished()) { 346 post(new Runnable() { 347
348 @Override 349 public void run() { 350 requestLayout(); 351 } 352 }); 353
354 } 355 } 356
357 private void fillList(final int dx) { 358 int edge = 0; 359 View child = getChildAt(getChildCount() - 1); 360 if (child != null) { 361 edge = child.getRight(); 362 } 363 fillListRight(edge, dx); 364
365 edge = 0; 366 child = getChildAt(0); 367 if (child != null) { 368 edge = child.getLeft(); 369 } 370 fillListLeft(edge, dx); 371
372 } 373
374 private void fillSpecific(int position, int top) { 375 View child = mAdapter.getView(position, null, null); 376 if (child == null) return; 377 addAndMeasureChild(child, -1); 378 int edge = 0; 379 if (child != null) { 380 edge = child.getRight(); 381 fillListRight(edge, top); 382 edge = child.getLeft(); 383 fillListLeft(edge, top); 384 } 385 } 386
387 private void fillListRight(int rightEdge, final int dx) { 388 while (rightEdge + dx < getWidth() 389 && mRightViewIndex < mAdapter.getCount()) { 390
391 View child = mAdapter.getView(mRightViewIndex, 392 mRemovedViewQueue.poll(), this); 393 addAndMeasureChild(child, -1); 394 rightEdge += child.getMeasuredWidth(); 395
396 if (mRightViewIndex == mAdapter.getCount() - 1) { 397 mMaxX = mCurrentX + rightEdge - getWidth(); 398 } 399
400 if (mMaxX < 0) { 401 mMaxX = 0; 402 } 403 mRightViewIndex++; 404 } 405
406 } 407
408 private void fillListLeft(int leftEdge, final int dx) { 409 while (leftEdge + dx > 0 && mLeftViewIndex >= 0) { 410 View child = mAdapter.getView(mLeftViewIndex, 411 mRemovedViewQueue.poll(), this); 412 addAndMeasureChild(child, 0); 413 leftEdge -= child.getMeasuredWidth(); 414 if (mLeftViewIndex == 0) { 415 mMinX = mCurrentX + leftEdge; 416 } 417 if (mMinX > 0) { 418 mMinX = 0; 419 } 420 mLeftViewIndex--; 421 mDisplayOffset -= child.getMeasuredWidth(); 422 } 423 mFirstPosition = mLeftViewIndex + 1; 424 } 425
426 private void removeNonVisibleItems(final int dx) { 427 View child = getChildAt(0); 428 while (child != null && child.getRight() + dx <= 0) { 429 mDisplayOffset += child.getMeasuredWidth(); 430 mRemovedViewQueue.offer(child); 431 removeViewInLayout(child); 432 mLeftViewIndex++; 433 child = getChildAt(0); 434
435 } 436
437 child = getChildAt(getChildCount() - 1); 438 while (child != null && child.getLeft() + dx >= getWidth()) { 439 mRemovedViewQueue.offer(child); 440 removeViewInLayout(child); 441 mRightViewIndex--; 442 child = getChildAt(getChildCount() - 1); 443 } 444 } 445
446 private void positionItems(final int dx) { 447 if (getChildCount() > 0) { 448 mDisplayOffset += dx; 449 int left = mDisplayOffset; 450 for (int i = 0; i < getChildCount(); i++) { 451 View child = getChildAt(i); 452 int childWidth = child.getMeasuredWidth(); 453 child.layout(left, 0, left + childWidth, 454 child.getMeasuredHeight()); 455 left += childWidth + child.getPaddingRight(); 456 } 457 } 458 } 459
460 public synchronized void scrollTo(int x) { 461 mScroller.startScroll(mNextX, 0, x - mNextX, 0); 462 requestLayout(); 463 } 464
465 @Override 466 public boolean dispatchTouchEvent(MotionEvent ev) { 467 boolean handled = super.dispatchTouchEvent(ev); 468 handled |= mGesture.onTouchEvent(ev); 469 return handled; 470 } 471
472 protected boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 473 float velocityY) { 474 synchronized (HorizontalListView.this) { 475 mScroller.fling(mNextX, 0, (int) -velocityX, 0, mMinX, mMaxX, 0, 0); 476 } 477 requestLayout(); 478
479 return true; 480 } 481
482 protected boolean onDown(MotionEvent e) { 483 mScroller.forceFinished(true); 484 return true; 485 } 486
487 private OnGestureListener mOnGesture = new GestureDetector.SimpleOnGestureListener() { 488
489 @Override 490 public boolean onDown(MotionEvent e) { 491 return HorizontalListView.this.onDown(e); 492 } 493
494 @Override 495 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, 496 float velocityY) { 497 return HorizontalListView.this
498 .onFling(e1, e2, velocityX, velocityY); 499 } 500
501 @Override 502 public boolean onScroll(MotionEvent e1, MotionEvent e2, 503 float distanceX, float distanceY) { 504
505 synchronized (HorizontalListView.this) { 506 mNextX += (int) distanceX; 507 } 508 requestLayout(); 509
510 return true; 511 } 512
513 @Override 514 public boolean onSingleTapConfirmed(MotionEvent e) { 515 for (int i = 0; i < getChildCount(); i++) { 516 View child = getChildAt(i); 517 if (isEventWithinView(e, child)) { 518 if (mOnItemClicked != null) { 519 mOnItemClicked.onItemClick(HorizontalListView.this, 520 child, mLeftViewIndex + 1 + i, 521 mAdapter.getItemId(mLeftViewIndex + 1 + i)); 522 } 523 if (mOnItemSelected != null) { 524 mOnItemSelected.onItemSelected(HorizontalListView.this, 525 child, mLeftViewIndex + 1 + i, 526 mAdapter.getItemId(mLeftViewIndex + 1 + i)); 527 } 528 break; 529 } 530
531 } 532 return true; 533 } 534
535 @Override 536 public void onLongPress(MotionEvent e) { 537 int childCount = getChildCount(); 538 for (int i = 0; i < childCount; i++) { 539 View child = getChildAt(i); 540 if (isEventWithinView(e, child)) { 541 if (mOnItemLongClicked != null) { 542 mOnItemLongClicked.onItemLongClick( 543 HorizontalListView.this, child, mLeftViewIndex 544 + 1 + i, 545 mAdapter.getItemId(mLeftViewIndex + 1 + i)); 546 } 547 break; 548 } 549
550 } 551 } 552
553 private boolean isEventWithinView(MotionEvent e, View child) { 554 Rect viewRect = new Rect(); 555 int[] childPosition = new int[2]; 556 child.getLocationOnScreen(childPosition); 557 int left = childPosition[0]; 558 int right = left + child.getWidth(); 559 int top = childPosition[1]; 560 int bottom = top + child.getHeight(); 561 viewRect.set(left, top, right, bottom); 562 return viewRect.contains((int) e.getRawX(), (int) e.getRawY()); 563 } 564 }; 565
566 }
Demo code:

1 package com.tangyu.component.test; 2
3 import com.tangyu.component.R; 4 import com.tangyu.component.Util; 5 import com.tangyu.component.view.HorizontalListView; 6
7 import android.app.Activity; 8 import android.os.Bundle; 9 import android.os.Handler; 10 import android.view.View; 11 import android.widget.AbsListView.LayoutParams; 12 import android.widget.AdapterView; 13 import android.widget.AdapterView.OnItemClickListener; 14 import android.widget.ArrayAdapter; 15
16 public class TestHorizontalListView extends Activity { 17
18 private HorizontalListView hListView; 19
20 Handler handler = new Handler() { 21 public void handleMessage(android.os.Message msg) { 22 final int position = hListView.getFirstVisiblePosition(); 23 hListView.setSelection(position + 1); 24 sendEmptyMessageDelayed(0, 1500); 25 }; 26 }; 27
28 @Override 29 protected void onCreate(Bundle savedInstanceState) { 30 super.onCreate(savedInstanceState); 31 hListView = getHListView(); 32 setContentView(hListView); 33
34 hListView.setAdapter(new ArrayAdapter<String>(this, R.layout.simple_list_item_1, mStringMores)); 35 hListView.setOnItemClickListener(new OnItemClickListener() { 36
37 @Override 38 public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, 39 long arg3) { 40 // TODO Auto-generated method stub
41 final int position = hListView.getFirstVisiblePosition(); 42 Util.toast(TestHorizontalListView.this, "first = " + (position + 1) + " cur = " + (arg2 + 1), true); 43 handler.removeMessages(0); 44 } 45 }); 46 } 47
48 public void onWindowFocusChanged(boolean hasFocus) { 49 super.onWindowFocusChanged(hasFocus); 50 if (hasFocus) { 51 hListView.setSelectionFromLeft(5, 0); 52 handler.sendEmptyMessageDelayed(0, 1500); 53 } 54 }; 55
56 HorizontalListView getHListView() { 57 HorizontalListView listView = new HorizontalListView(this, null); 58 listView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 59 LayoutParams.MATCH_PARENT)); 60 listView.setBackgroundColor(0x33FF0000); 61 return listView; 62 } 63
64 private String[] mStringMores = {"1 : Beyaz Peynir", 65 "2 : Harbourne Blue", 66 "3 : Doolin", 67 "4 : Cougar Gold", 68 "5 : Blue Castello", 69 "6 : Appenzell", 70 "7 : Rouleau De Beaulieu", 71 "8 : Ubriaco", 72 "9 : Evansdale Farmhouse Brie", 73 "10 : Mimolette", 74 "11 : Dreux a la Feuille", 75 "12 : Le Roule", 76 "13 : Seriously Strong Cheddar", 77 "14 : Bosworth", 78 "15 : Cream Havarti", 79 "16 : Ile d'Yeu", 80 "17 : Mont D'or Lyonnais", 81 "18 : Hubbardston Blue Cow", 82 "19 : Ardrahan", 83 "20 : Duroblando", 84 "21 : Provolone (Australian)", 85 "22 : Queso Fresco (Adobera)", 86 "23 : Mozzarella (Australian)", 87 "24 : Fiore Sardo", 88 "25 : Brick", 89 "26 : Maribo", 90 "27 : Danablu (Danish Blue)", 91 "28 : Provolone", 92 "29 : Crottin de Chavignol", 93 "30 : Pant ys Gawn", 94 "31 : Anejo Enchilado", 95 "32 : Schloss", 96 "33 : Bishop Kennedy", 97 "34 : Sirene", 98 "35 : Brebis du Lavort", 99 "36 : Llanboidy", 100 "37 : Exmoor Blue", 101 "38 : Yarg Cornish", 102 "39 : Canadian Cheddar", 103 "40 : Boulette d'Avesnes", 104 "41 : Cypress Grove Chevre", 105 "42 : Queso Majorero", 106 "43 : Gruyere", 107 "44 : Jindi Brie", 108 "45 : Ossau-Iraty", 109 "46 : Langres", 110 "47 : Fondant de Brebis", 111 "48 : Pasteurized Processed", 112 "49 : L'Ecir de l'Aubrac", 113 "50 : Monastery Cheeses", 114 "51 : Sainte Maure", 115 "52 : Rollot", 116 "53 : Swaledale", 117 "54 : Coeur de Camembert au Calvados", 118 "55 : Beauvoorde", 119 "56 : Leafield", 120 "57 : Bavarian Bergkase", 121 "58 : Caprice des Dieux", 122 "59 : Pecorino Romano", 123 "60 : Myzithra", 124 "61 : Feta (Australian)", 125 "62 : Caciotta", 126 "63 : Afuega'l Pitu", 127 "64 : Bleu de Laqueuille", 128 "65 : Maytag Blue", 129 "66 : Bleu de Septmoncel", 130 "67 : Lairobell", 131 "68 : Dauphin", 132 "69 : Coverdale", 133 "70 : Mozzarella di Bufala", 134 "71 : Herve", 135 "72 : Autun", 136 "73 : Bresse Bleu", 137 "74 : Bierkase", 138 "75 : Postel", 139 "76 : Buxton Blue", 140 "77 : Castelo Branco", 141 "78 : Tomme de Chevre", 142 "79 : Queso Jalapeno", 143 "80 : Matocq", 144 "81 : Regal de la Dombes", 145 "82 : Idaho Goatster", 146 "83 : Lanark Blue", 147 "84 : Acorn", 148 "85 : Trappe (Veritable)", 149 "86 : Romans Part Dieu", 150 "87 : Casciotta di Urbino", 151 "88 : Bryndza", 152 "89 : Perail de Brebis", 153 "90 : Galette du Paludier", 154 "91 : Gouda", 155 "92 : Mahoe Aged Gouda", 156 "93 : Chaource", 157 "94 : Bleu Des Causses", 158 "95 : Kadchgall", 159 "96 : Feta", 160 "97 : Orkney Extra Mature Cheddar", 161 "98 : Mozzarella Fresh, in water", 162 "99 : Liptauer", 163 "100 : Murol", 164 "101 : Aromes au Gene de Marc", 165 "102 : Petit Pardou", 166 "103 : Cooleney", 167 "104 : Saint-Paulin", 168 "105 : Gorgonzola", 169 "106 : Queso del Montsec", 170 "107 : Pate de Fromage", 171 "108 : Kaseri", 172 "109 : Fontina Val d'Aosta", 173 "110 : Spenwood", 174 "111 : Fromage Corse", 175 "112 : Fynbo", 176 "113 : Brebis du Puyfaucon", 177 "114 : Bonchester", 178 "115 : Weichkaese", 179 "116 : Fromage de Montagne de Savoie", 180 "117 : Rabacal", 181 "118 : Scamorza", 182 "119 : Dunbarra", 183 "120 : Friesekaas", 184 "121 : Abbaye du Mont des Cats", 185 "122 : Sourire Lozerien", 186 "123 : Shropshire Blue", 187 "124 : Klosterkaese", 188 "125 : Leerdammer", 189 "126 : Tetilla", 190 "127 : Grana Padano", 191 "128 : Castelleno", 192 "129 : Aubisque Pyrenees", 193 "130 : Bra", 194 "131 : Bleu de Gex", 195 "132 : Toscanello", 196 "133 : Leicester", 197 "134 : Graddost", 198 "135 : Gammelost", 199 "136 : Saaland Pfarr", 200 "137 : Broccio Demi-Affine", 201 "138 : Cornish Pepper", 202 "139 : Leyden", 203 "140 : Oszczypek", 204 "141 : Tillamook Cheddar", 205 "142 : Fourme de Montbrison", 206 "143 : Peekskill Pyramid", 207 "144 : Saint-Marcellin", 208 "145 : Sancerre", 209 "146 : Baguette Laonnaise", 210 "147 : Greve", 211 "148 : Niolo", 212 "149 : Ami du Chambertin", 213 "150 : Pyramide", 214 "151 : Cerney", 215 "152 : Neufchatel (Australian)", 216 "153 : King Island Cape Wickham Brie", 217 "154 : Maasdam", 218 "155 : Trois Cornes De Vendee", 219 "156 : Poivre d'Ane", 220 "157 : Caciocavallo", 221 "158 : Tupi", 222 "159 : Kashta", 223 "160 : Curworthy", 224 "161 : Bakers", 225 "162 : Toma", 226 "163 : Chevrotin des Aravis", 227 "164 : Friesla", 228 "165 : Sweet Style Swiss", 229 "166 : Bocconcini", 230 "167 : Alverca", 231 "168 : Gastanberra", 232 "169 : Trou du Cru", 233 "170 : Buchette d'Anjou", 234 "171 : Barry's Bay Cheddar", 235 "172 : Chabichou", 236 "173 : Galette Lyonnaise", 237 "174 : Tomme des Chouans", 238 "175 : Meyer Vintage Gouda", 239 "176 : Edelpilz", 240 "177 : Capricorn Goat", 241 "178 : Colby", 242 "179 : Macconais", 243 "180 : Port Nicholson", 244 "181 : Chaumes", 245 "182 : Castellano", 246 "183 : Reggianito", 247 "184 : Fromage a Raclette", 248 "185 : Blue", 249 "186 : Lou Palou", 250 "187 : Golden Cross", 251 "188 : Four Herb Gouda", 252 "189 : Celtic Promise", 253 "190 : Pave d'Affinois", 254 "191 : Tomme Brulee", 255 "192 : Port-Salut", 256 "193 : Quercy Petit", 257 "194 : Gospel Green", 258 "195 : Queso Iberico", 259 "196 : Cottage Cheese (Australian)", 260 "197 : Dessertnyj Belyj", 261 "198 : Mascarpone Torta", 262 "199 : Tilsit", 263 "200 : Fribourgeois", 264 "201 : Sveciaost", 265 "202 : Cuajada", 266 "203 : Waimata Farmhouse Blue", 267 "204 : Wensleydale", 268 "205 : Panela", 269 "206 : Berkswell", 270 "207 : Curd", 271 "208 : Lebbene", 272 "209 : Queso del Tietar", 273 "210 : Shelburne Cheddar", 274 "211 : Cendre d'Olivet", 275 "212 : Blue Rathgore", 276 "213 : Mahon", 277 "214 : Cheddar", 278 "215 : Rigotte", 279 "216 : Ossau Fermier", 280 "217 : Cold Pack", 281 "218 : Mycella", 282 "219 : Taleggio", 283 "220 : Selles sur Cher", 284 "221 : Podhalanski", 285 "222 : Coeur de Chevre", 286 "223 : Camembert de Normandie", 287 "224 : La Vache Qui Rit", 288 "225 : Quartirolo Lombardo", 289 "226 : Havarti", 290 "227 : Dolcelatte", 291 "228 : Manchego", 292 "229 : String", 293 "230 : Fourme de Haute Loire", 294 "231 : Paneer", 295 "232 : Crowley", 296 "233 : Gubbeen", 297 "234 : Evora De L'Alentejo", 298 "235 : Woodside Cabecou", 299 "236 : Lancashire", 300 "237 : Airedale", 301 "238 : Ackawi", 302 "239 : Brillat-Savarin", 303 "240 : Olivet Cendre", 304 "241 : Anneau du Vic-Bilh", 305 "242 : Fresh Ricotta", 306 "243 : Sbrinz", 307 "244 : Stinking Bishop", 308 "245 : Chabichou du Poitou", 309 "246 : Delice des Fiouves", 310 "247 : Briquette du Forez", 311 "248 : Yorkshire Blue", 312 "249 : Plateau de Herve", 313 "250 : Isle of Mull", 314 "251 : Tyn Grug", 315 "252 : Lavistown", 316 "253 : Requeson", 317 "254 : Cotherstone", 318 "255 : Somerset Brie", 319 "256 : Xynotyro", 320 "257 : Bel Paese", 321 "258 : Mozzarella Rolls", 322 "259 : Saint-Nectaire", 323 "260 : Sottocenare al Tartufo", 324 "261 : Basket Cheese", 325 "262 : Llanglofan Farmhouse", 326 "263 : Menonita", 327 "264 : Fresh Mozzarella", 328 "265 : Samso", 329 "266 : Castigliano", 330 "267 : Metton (Cancoillotte)", 331 "268 : Baladi", 332 "269 : Schabzieger", 333 "270 : Vasterbottenost", 334 "271 : Crema Agria", 335 "272 : Limburger", 336 "273 : Dorset Blue Vinney", 337 "274 : Doppelrhamstufel", 338 "275 : Gjetost", 339 "276 : Vendomois", 340 "277 : Allgauer Emmentaler", 341 "278 : Pont l'Eveque", 342 "279 : Geitost", 343 "280 : Knockalara", 344 "281 : Breakfast Cheese", 345 "282 : Northumberland", 346 "283 : Telemea", 347 "284 : Gornyaltajski", 348 "285 : Greuilh", 349 "286 : Ricotta (Australian)", 350 "287 : Le Brin", 351 "288 : Emental Grand Cru", 352 "289 : Mamirolle", 353 "290 : Brin d' Amour", 354 "291 : Petit Morin", 355 "292 : St. Agur Blue Cheese", 356 "293 : L'Aveyronnais", 357 "294 : Grana", 358 "295 : Devon Blue", 359 "296 : Grataron d' Areches", 360 "297 : Esbareich", 361 "298 : Parmesan (Parmigiano)", 362 "299 : Meira", 363 "300 : Frying Cheese", 364 "301 : Royalp Tilsit", 365 "302 : Laguiole", 366 "303 : Sardo Egyptian", 367 "304 : Olivet au Foin", 368 "305 : Pas de l'Escalette", 369 "306 : Tasmania Highland Chevre Log", 370 "307 : Haloumi-Style Cheese", 371 "308 : Loddiswell Avondale", 372 "309 : Nantais", 373 "310 : Herrgardsost", 374 "311 : Lajta", 375 "312 : Kenafa", 376 "313 : Cairnsmore", 377 "314 : Roule", 378 "315 : Emmental", 379 "316 : Brie de Melun", 380 "317 : Hereford Hop", 381 "318 : Jarlsberg", 382 "319 : Cure Nantais", 383 "320 : Herriot Farmhouse", 384 "321 : Tala", 385 "322 : Reblochon", 386 "323 : Mine-Gabhar", 387 "324 : Croghan", 388 "325 : Bouyssou", 389 "326 : Wellington", 390 "327 : Tete de Moine", 391 "328 : Valencay", 392 "329 : Passendale", 393 "330 : Blarney", 394 "331 : Grabetto", 395 "332 : Saga", 396 "333 : Cabecou", 397 "334 : Margotin", 398 "335 : Taupiniere", 399 "336 : Ricotta", 400 "337 : Bruder Basil", 401 "338 : Serra da Estrela", 402 "339 : Gris de Lille", 403 "340 : Fourme d' Ambert", 404 "341 : Cream Cheese", 405 "342 : Guerbigny", 406 "343 : Manouri", 407 "344 : Adelost", 408 "345 : Saanenkaese", 409 "346 : Castelmagno", 410 "347 : Stilton", 411 "348 : Graviera", 412 "349 : Mihalic Peynir", 413 "350 : Mozzarella", 414 "351 : Parmigiano Reggiano", 415 "352 : Brin d'Amour", 416 "353 : Kernhem", 417 "354 : Lincolnshire Poacher", 418 "355 : Queso Quesadilla", 419 "356 : Timboon Brie", 420 "357 : Kefalotyri", 421 "358 : Oxford Blue", 422 "359 : Zanetti Grana Padano", 423 "360 : Epoisses de Bourgogne", 424 "361 : Nokkelost", 425 "362 : Aragon", 426 "363 : Chontaleno", 427 "364 : Fougerus", 428 "365 : Cachaille", 429 "366 : Fin-de-Siecle", 430 "367 : Pecorino", 431 "368 : Hushallsost", 432 "369 : Tomme de Romans", 433 "370 : Cathelain", 434 "371 : Crowdie", 435 "372 : Queso Para Frier", 436 "373 : Olivet Bleu", 437 "374 : P'tit Berrichon", 438 "375 : Testouri", 439 "376 : Queso Fresco", 440 "377 : Gaperon a l'Ail", 441 "378 : Cotija", 442 "379 : Figue", 443 "380 : Lappi", 444 "381 : Richelieu", 445 "382 : Folded", 446 "383 : Fleur du Maquis", 447 "384 : Kikorangi", 448 "385 : Calenzana", 449 "386 : Durrus", 450 "387 : Maroilles", 451 "388 : Selva", 452 "389 : Creme Fraiche", 453 "390 : King River Gold", 454 "391 : Teifi", 455 "392 : Gowrie", 456 "393 : Ridder", 457 "394 : Babybel", 458 "395 : Filetta", 459 "396 : Fresh Truffles", 460 "397 : Caboc", 461 "398 : Gloucester", 462 "399 : Petit-Suisse", 463 "400 : Pressato", 464 "401 : Boule Du Roves", 465 "402 : Jermi Tortes", 466 "403 : Burgos", 467 "404 : Manur", 468 "405 : Brin", 469 "406 : Chabis de Gatine", 470 "407 : Fontal", 471 "408 : Abertam", 472 "409 : Cambazola", 473 "410 : Raclette", 474 "411 : Bath Cheese", 475 "412 : Vulscombe", 476 "413 : Washed Rind Cheese (Australian)", 477 "414 : Coulommiers", 478 "415 : Esrom", 479 "416 : Plymouth Cheese", 480 "417 : Torta del Casar", 481 "418 : Munster", 482 "419 : American Cheese", 483 "420 : Salers", 484 "421 : Orla", 485 "422 : Tamie", 486 "423 : Avaxtskyr", 487 "424 : Kugelkase", 488 "425 : Grafton Village Cheddar", 489 "426 : Civray", 490 "427 : Lingot Saint Bousquet d'Orb", 491 "428 : Butte", 492 "429 : Etorki", 493 "430 : Brie de Meaux", 494 "431 : Le Fium Orbo", 495 "432 : Penbryn", 496 "433 : Heidi Gruyere", 497 "434 : Braudostur", 498 "435 : Edam", 499 "436 : Ardi Gasna", 500 "437 : Menallack Farmhouse", 501 "438 : Laruns", 502 "439 : Wigmore", 503 "440 : Corleggy", 504 "441 : Tyning", 505 "442 : Boursault", 506 "443 : Galloway Goat's Milk Gems", 507 "444 : Fresh Jack", 508 "445 : Double Gloucester", 509 "446 : Rustinu", 510 "447 : Pecorino in Walnut Leaves", 511 "448 : Danbo", 512 "449 : Flower Marie", 513 "450 : Zamorano", 514 "451 : Roquefort", 515 "452 : Rocamadour", 516 "453 : Bocconcini (Australian)", 517 "454 : Prastost", 518 "455 : Brebis du Lochois", 519 "456 : Longhorn", 520 "457 : Mini Baby Bells", 521 "458 : Goutu", 522 "459 : Mothais a la Feuille", 523 "460 : Friesian", 524 "461 : Crayeux de Roncq", 525 "462 : Olde York", 526 "463 : Morbier Cru de Montagne", 527 "464 : Halloumi", 528 "465 : Prince-Jean", 529 "466 : Explorateur", 530 "467 : Beenleigh Blue", 531 "468 : Marble Cheddar", 532 "469 : Garrotxa", 533 "470 : Blue Vein (Australian)", 534 "471 : Asadero", 535 "472 : Sonoma Jack", 536 "473 : Soumaintrain", 537 "474 : Tronchon", 538 "475 : Canestrato", 539 "476 : Quark (Australian)", 540 "477 : Monterey Jack Dry", 541 "478 : Naboulsi", 542 "479 : Patefine Fort", 543 "480 : Bandal", 544 "481 : Fromage Frais", 545 "482 : Little Rydings", 546 "483 : Crottin du Chavignol", 547 "484 : Vignotte", 548 "485 : Serat", 549 "486 : Gabriel", 550 "487 : Processed Cheddar", 551 "488 : Rubens", 552 "489 : Polkolbin", 553 "490 : Finn", 554 "491 : Mascarpone", 555 "492 : Frinault", 556 "493 : Texas Goat Cheese", 557 "494 : Caerphilly", 558 "495 : Jubilee Blue", 559 "496 : Smoked Gouda", 560 "497 : Baylough", 561 "498 : Tourmalet", 562 "499 : Pave d'Auge", 563 "500 : Finlandia Swiss", 564 "501 : Dunsyre Blue", 565 "502 : Lou Pevre", 566 "503 : Remedou", 567 "504 : Pyengana Cheddar", 568 "505 : Abbaye de Belloc", 569 "506 : Cashel Blue", 570 "507 : Bergader", 571 "508 : Gratte-Paille", 572 "509 : Gippsland Blue", 573 "510 : Zanetti Parmigiano Reggiano", 574 "511 : Hipi Iti", 575 "512 : Raschera", 576 "513 : Venaco", 577 "514 : Mascarpone (Australian)", 578 "515 : Pouligny-Saint-Pierre", 579 "516 : Kervella Affine", 580 "517 : Lyonnais", 581 "518 : Dry Jack", 582 "519 : Pannerone", 583 "520 : Pelardon des Corbieres", 584 "521 : Mixte", 585 "522 : Loch Arthur Farmhouse", 586 "523 : Whitestone Farmhouse", 587 "524 : Iberico", 588 "525 : Meredith Blue", 589 "526 : Cabrales", 590 "527 : Vieux Corse", 591 "528 : Montasio", 592 "529 : Cheshire", 593 "530 : Baby Swiss", 594 "531 : Blue Vein Cheeses", 595 "532 : Red Leicester", 596 "533 : Neufchatel", 597 "534 : Coolea", 598 "535 : Swiss", 599 "536 : Waterloo", 600 "537 : Crescenza", 601 "538 : Buffalo", 602 "539 : Morbier", 603 "540 : Duddleswell", 604 "541 : Queso Blanco", 605 "542 : Xanadu", 606 "543 : Marbled Cheeses", 607 "544 : Halloumy (Australian)", 608 "545 : Ricotta Salata", 609 "546 : Tommes", 610 "547 : Balaton", 611 "548 : Mascares", 612 "549 : Piora", 613 "550 : Fruit Cream Cheese", 614 "551 : Queso Blanco con Frutas --Pina y Mango", 615 "552 : Maredsous", 616 "553 : Truffe", 617 "554 : Butterkase", 618 "555 : Pourly", 619 "556 : Anthoriro", 620 "557 : Juustoleipa", 621 "558 : Pithtviers au Foin", 622 "559 : San Simon", 623 "560 : Briquette de Brebis", 624 "561 : Ulloa", 625 "562 : Ragusano", 626 "563 : Mondseer", 627 "564 : Picos de Europa", 628 "565 : Formaggio di capra", 629 "566 : Brinza (Burduf Brinza)", 630 "567 : Boeren Leidenkaas", 631 "568 : Siraz", 632 "569 : Dutch Mimolette (Commissiekaas)", 633 "570 : La Taupiniere", 634 "571 : Sardo", 635 "572 : Yarra Valley Pyramid", 636 "573 : Malvern", 637 "574 : Monterey Jack", 638 "575 : Aisy Cendre", 639 "576 : Cantal", 640 "577 : Sussex Slipcote", 641 "578 : Capriole Banon", 642 "579 : Abondance", 643 "580 : Pave du Berry", 644 "581 : Brie", 645 "582 : Asiago", 646 "583 : Denhany Dorset Drum", 647 "584 : Banon", 648 "585 : Fontainebleau", 649 "586 : Chevres", 650 "587 : Quatre-Vents", 651 "588 : Syrian (Armenian String)", 652 "589 : Touree de L'Aubier", 653 "590 : Vacherin-Fribourgeois", 654 "591 : Basing", 655 "592 : Daralagjazsky", 656 "593 : Sage Derby", 657 "594 : Folded cheese with mint", 658 "595 : Flor de Guia", 659 "596 : Comte", 660 "597 : Milleens", 661 "598 : Double Worcester", 662 "599 : Pelardon des Cevennes", 663 "600 : Idiazabal", 664 "601 : Sharpam", 665 "602 : Mesost", 666 "603 : Sraffordshire Organic", 667 "604 : Grand Vatel", 668 "605 : Cheddar Clothbound", 669 "606 : Jibneh Arabieh", 670 "607 : Charolais", 671 "608 : Picodon de Chevre", 672 "609 : Brusselae Kaas (Fromage de Bruxelles)", 673 "610 : Devon Garland", 674 "611 : Emlett", 675 "612 : Dunlop", 676 "613 : Beer Cheese", 677 "614 : Cwmtawe Pecorino", 678 "615 : Tymsboro", 679 "616 : Romano", 680 "617 : Oaxaca", 681 "618 : Derby", 682 "619 : Tomme d'Abondance", 683 "620 : Livarot", 684 "621 : Queso de Murcia", 685 "622 : Molbo", 686 "623 : Broccio", 687 "624 : Il Boschetto al Tartufo", 688 "625 : Airag", 689 "626 : Bougon", 690 "627 : Roncal", 691 "628 : Penamellera", 692 "629 : Turunmaa", 693 "630 : Affidelice au Chablis", 694 "631 : Sap Sago", 695 "632 : Queso Media Luna", 696 "633 : Button (Innes)", 697 "634 : Brousse du Rove", 698 "635 : Pave de Chirac", 699 "636 : Ambert", 700 "637 : Coquetdale", 701 "638 : Armenian String", 702 "639 : Danish Fontina", 703 "640 : White Stilton", 704 "641 : Pencarreg", 705 "642 : Bleu d'Auvergne", 706 "643 : Crema Mexicana", 707 "644 : Le Lacandou", 708 "645 : Bergere Bleue", 709 "646 : Carre de l'Est", 710 "647 : Beaufort", 711 "648 : Cottage Cheese", 712 "649 : Quark", 713 "650 : Oschtjepka", 714 "651 : Boursin", 715 "652 : Tibet", 716 "653 : Tomme de Savoie", 717 "654 : Palet de Babligny", 718 }; 719 }
Demo layout code:
