1. 程式人生 > >Android拖動實現(一個流暢的拖動排序DragSortGridView,自動滾屏)

Android拖動實現(一個流暢的拖動排序DragSortGridView,自動滾屏)

/** * Copyright (C), 2008-2015, Huawei Tech. Co., Ltd. * <p/> * Description : 拖動排序佈局 * * @version V100R001 * @since V100R001 */ @SuppressLint({ "NewApi", "Override" }) public class DragSortGridView extends FrameLayout { protected NoScrollGridView mGridView; private ScrollView mScrollView; private
int headDragPosition = 0; private int footDragPosition = 0; private FrameLayout mDragFrame; private View mCopyView, hideView; private GestureDetector detector; /** 動畫時間 */ private static final long ANIM_DURING = 250; protected int mNumColumns = 3, mColHeight = 0, mColWidth = 0, mChildCount = 0
, mMaxHeight = 0; private int currentDragPosition = -1; private DragAdapter adapter; /** 持有子view */ private List<View> mChilds = new ArrayList<View>(); private static final int TAG_KEY = R.id.first; // private static final int TAG_KEY = R.id.tag_key; private int mCurrentY = 0
; /** * 觸控區域,0不滾動區域,1可向上滾動的區域,-1可向下滾動的區域 */ private int mTouchArea = 0; /** * gridview能否滾動,是否內容太多 */ private boolean canScroll = true; /** * 是否可以拖動,點選拖動策略下直接開啟,長按拖動需要長按以後開啟 */ private boolean isDragable = true; /** * 自動滾屏的動畫 */ private ValueAnimator animator; /** * view是否載入完成,如果未載入完成,沒有寬高,無法接受事件 */ private boolean isViewInitDone = false; /** 是否有位置發生改變,否則不用重繪 */ private boolean hasPositionChange = false; /** 介面卡的觀察者,觀察介面卡的資料改變 */ private DataSetObserver observer = new DataSetObserver() { @Override public void onChanged() { mChildCount = adapter.getCount(); // 下列屬性狀態清除,才會在被呼叫notifyDataSetChange時,在gridview測量佈局完成後重新獲取 mChilds.clear(); mColHeight = mColWidth = mMaxHeight = 0; isViewInitDone = false; } @Override public void onInvalidated() { mChildCount = adapter.getCount(); } }; private float[] lastLocation = null; /** * 手勢監聽器,滾動和單擊 */ private SimpleOnGestureListener simpleOnGestureListener = new SimpleOnGestureListener() { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { if (hasSendDragMsg) { hasSendDragMsg = false; handler.removeMessages(0x123); } if (isDragable && mCopyView != null) {// 可以拖動,實現跟隨手指的拖動效果 // /// 2015/11/27補充修正跟隨手指移動方法,適用於當本控制元件在drag時同時滾動的情況 if (lastLocation == null) { lastLocation = new float[] { e1.getRawX(), e1.getRawY() }; } distanceX = lastLocation[0] - e2.getRawX(); distanceY = lastLocation[1] - e2.getRawY(); lastLocation[0] = e2.getRawX(); lastLocation[1] = e2.getRawY(); // //////// mCopyView.setX(mCopyView.getX() - distanceX); mCopyView.setY(mCopyView.getY() - distanceY); mCopyView.invalidate(); int to = eventToPosition(e2); if (to != currentDragPosition && to >= headDragPosition && to < mChildCount - footDragPosition) { onDragPositionChange(currentDragPosition, to); } } return true; } @Override public void onShowPress(MotionEvent e) { /** 響應長按拖拽 */ if (mDragMode == DRAG_BY_LONG_CLICK) { // 啟動拖拽模式 // isDragable = true; // 通知父控制元件不攔截我的事件 getParent().requestDisallowInterceptTouchEvent(true); // 根據點選的位置生成該位置上的view映象 int position = eventToPosition(e); if (position >= headDragPosition && position < mChildCount - footDragPosition) { // copyView(currentDragPosition = position); Message msg = handler.obtainMessage(0x123, position, 0); // showpress本身大概需要170毫秒 handler.sendMessageDelayed(msg, dragLongPressTime - 170); hasSendDragMsg = true; } } }; }; private boolean hasSendDragMsg = false; private Handler handler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { switch (msg.what) { case 0x123: // 啟動拖拽模式 isDragable = true; // 根據點選的位置生成該位置上的view映象 copyView(currentDragPosition = msg.arg1); hasSendDragMsg = false; break; default: break; } return false; } }); public DragSortGridView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public DragSortGridView(Context context) { super(context); init(); } private void init() { Context context = getContext(); mGridView = new NoScrollGridView(context); mGridView.setVerticalScrollBarEnabled(false); mGridView.setStretchMode(GridView.STRETCH_COLUMN_WIDTH); mGridView.setSelector(new ColorDrawable()); // View的寬高之類必須在測量,佈局,繪製一系列過程之後才能獲取到 mGridView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { @Override public void onGlobalLayout() { if (mChilds.isEmpty()) { for (int i = 0; i < mGridView.getChildCount(); i++) { View view = mGridView.getChildAt(i); view.setTag(TAG_KEY, new int[] { 0, 0 }); view.clearAnimation(); mChilds.add(view); } } if (!mChilds.isEmpty()) { mColHeight = mChilds.get(0).getHeight(); } mColWidth = mGridView.getColumnWidth(); if (mChildCount % mNumColumns == 0) { mMaxHeight = mColHeight * mChildCount / mNumColumns; } else { mMaxHeight = mColHeight * (mChildCount / mNumColumns + 1); } canScroll = mMaxHeight - getHeight() > 0; // 告知事件處理,完成View載入,許多屬性也已經初始化了 isViewInitDone = true; } }); mScrollView = new ListenScrollView(context); mDragFrame = new FrameLayout(context); addView(mScrollView, -1, -1); mScrollView.addView(mGridView, -1, -1); addView(mDragFrame, new LayoutParams(-1, -1)); detector = new GestureDetector(context, simpleOnGestureListener); detector.setIsLongpressEnabled(false); mGridView.setNumColumns(mNumColumns); } @Override public boolean onTouchEvent(MotionEvent ev) { if (l != null) { l.onTouch(this, ev); } if (!isViewInitDone) { return false; } if (isDragable) { handleScrollAndCreMirror(ev); } else { // 交給子控制元件自己處理 if (canScroll) mScrollView.dispatchTouchEvent(ev); else mGridView.dispatchTouchEvent(ev); } // 處理拖動 detector.onTouchEvent(ev); if (ev.getAction() == MotionEvent.ACTION_CANCEL || ev.getAction() == MotionEvent.ACTION_UP) { lastLocation = null; if (hasSendDragMsg) { hasSendDragMsg = false; handler.removeMessages(0x123); } } return true; } /** * Author :[pWX273343] 2015年7月22日 * <p> * Description :攔截所有事件 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return true; } /** * 處理自動滾屏,和單擊生成映象 */ private void handleScrollAndCreMirror(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // 通知父控制元件不攔截我的事件 getParent().requestDisallowInterceptTouchEvent(true); // 根據點選的位置生成該位置上的view映象 int position = eventToPosition(ev); if (position >= headDragPosition && position < mChildCount - footDragPosition) { copyView(currentDragPosition = position); } break; case MotionEvent.ACTION_MOVE: getParent().requestDisallowInterceptTouchEvent(true);// 通知父控制元件不攔截我的事件 // 內容太多時,移動到邊緣會自動滾動 if (canScroll) { int touchArea = decodeTouchArea(ev); if (touchArea != mTouchArea) { onTouchAreaChange(touchArea); mTouchArea = touchArea; } } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: if (hideView != null) { hideView.setVisibility(View.VISIBLE); if (onDragSelectListener != null) { onDragSelectListener.onPutDown(hideView); } } mDragFrame.removeAllViews(); // mDragFrame.scrollTo(0, 0); // isNotifyByDragSort = true; if (hasPositionChange) { hasPositionChange = false; adapter.notifyDataSetChanged(); } else if (mDragMode == DRAG_BY_LONG_CLICK && itemLongClickListener != null) { itemLongClickListener.onItemLongClick(mGridView, childAt(currentDragPosition), currentDragPosition, 0); } // 停止滾動 if (canScroll) { int scrollStates2 = decodeTouchArea(ev); if (scrollStates2 != 0) { onTouchAreaChange(0); mTouchArea = 0; } } // 放手時取消拖動排序模式 if (mDragMode == DRAG_BY_LONG_CLICK) { isDragable = false; } break; default: break; } } /** * @param ev * 事件 * @return 0中間區域, 1底部,-1頂部 * @描述: 檢查當前觸控事件位於哪個區域, 頂部1/5可能觸發下滾,底部1/5可能觸發上滾 * @作者 [pWX273343] 2015年6月30日 */ private int decodeTouchArea(MotionEvent ev) { if (ev.getY() > getHeight() * 4 / (double) 5) { return 1; } else if (ev.getY() < getHeight() / (double) 5) { return -1; } else { return 0; } } /** * @param ev * @return * @描述 得到事件觸發點,摸到的是哪一個item * @作者 [pWX273343] 2015年7月6日 */ public int eventToPosition(MotionEvent ev) { if (ev != null) { int m = (int) ev.getX() / mColWidth; int n = (int) (ev.getY() + mCurrentY) / mColHeight; int position = n * mNumColumns + m; if (position >= mChildCount) { return mChildCount - 1; } else { return position; } } return 0; } // 這裡把控制元件作為假的橫向ListView,所以返回position跟高度無關,暫時這樣 // public int eventToPosition(MotionEvent ev) { // // if (ev != null) { // int m = (int) ev.getX() / mColWidth; // if (m >= mChildCount) { // return mChildCount - 1; // } else { // return m; // } // } // return 0; // } /** * @param dragPosition * @描述:複製一個映象,並新增到透明層 * @作者 [pWX273343] 2015年7月6日 */ private void copyView(int dragPosition) { hideView = mChilds.get(dragPosition); int realPosition = mGridView.indexOfChild(hideView); if (!adapter.isUseCopyView()) { mCopyView = adapter.getView(realPosition, mCopyView, mDragFrame); } else { mCopyView = adapter.copyView(realPosition, mCopyView, mDragFrame); } hideView.setVisibility(View.INVISIBLE); mDragFrame.addView(mCopyView, mColWidth, mColHeight); int[] l1 = new int[2]; int[] l2 = new int[2]; hideView.getLocationOnScreen(l1); mDragFrame.getLocationOnScreen(l2); // mCopyView.setX(hideView.getLeft()); // mCopyView.setY(hideView.getTop() - mCurrentY); mCopyView.setX(l1[0] - l2[0]); mCopyView.setY(l1[1] - l2[1]); if (onDragSelectListener == null) { mCopyView.setScaleX(1.2f); mCopyView.setScaleY(1.2f); } else { onDragSelectListener.onDragSelect(mCopyView); } } /** * @param from * @param to * @描述:動畫效果移動View * @作者 [pWX273343] 2015年6月24日 */ private void translateView(int from, int to) { View view = mChilds.get(from); int fromXValue = ((int[]) view.getTag(TAG_KEY))[0]; int fromYValue = ((int[]) view.getTag(TAG_KEY))[1]; int toXValue = to % mNumColumns - from % mNumColumns + fromXValue; int toYValue = to / mNumColumns - from / mNumColumns + fromYValue; Animation animation = new TranslateAnimation(1, fromXValue, 1, toXValue, 1, fromYValue, 1, toYValue); animation.setDuration(ANIM_DURING); animation.setFillAfter(true); view.setTag(TAG_KEY, new int[] { toXValue, toYValue }); view.startAnimation(animation); } /** * @param from * @param to * @描述:拖動View使位置發生改變時 * @作者 [pWX273343] 2015年7月6日 */ private void onDragPositionChange(int from, int to) { if (from > to) { for (int i = to; i < from; i++) { translateView(i, i + 1); } } else { for (int i = to; i > from; i--) { translateView(i, i - 1); } } if (!hasPositionChange) { hasPositionChange = true; } adapter.onDataModelMove(from, to); View view = mChilds.remove(from); mChilds.add(to, view); currentDragPosition = to; } /** * Function :setAdapter * <p/> * Author :[pWX273343] 2015年6月24日 * <p/> * Description :設定介面卡.該介面卡必須實現一個方法,當view的位置發生變動時,對實際資料的改動 * * @param adapter * @see GridView#setAdapter(android.widget.ListAdapter) */ public void setAdapter(DragAdapter adapter) { if (this.adapter != null && observer != null) { this.adapter.unregisterDataSetObserver(observer); } this.adapter = adapter; mGridView.setAdapter(adapter); adapter.registerDataSetObserver(observer); mChildCount = adapter.getCount(); } public int getNumColumns() { return mNumColumns; } /** * 每行幾個 */ public void setNumColumns(int numColumns) { this.mNumColumns = numColumns; mGridView.setNumColumns(numColumns); } /** * 設定前幾個item不可以改變位置 */ public void setNoPositionChangeItemCount(int count) { headDragPosition = count; } /** * 設定後幾個item不可以改變位置 */ public void setFootNoPositionChangeItemCount(int count) { footDragPosition = count; } /** * 控制自動滾屏的動畫監聽器. */ private AnimatorUpdateListener animUpdateListener = new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int targetY = Math.round((Float) animation.getAnimatedValue()); if (targetY < 0) { targetY = 0; } else if (targetY > mMaxHeight - getHeight()) { targetY = mMaxHeight - getHeight(); } // mGridView.scrollTo(0, targetY); mScrollView.smoothScrollTo(0, targetY); // mCurrentY = targetY; } }; /** * @param scrollStates * @描述:觸控區域改變,做相應處理,開始滾動或停止滾動 * @作者 [pWX273343] 2015年6月29日 */ protected void onTouchAreaChange(int scrollStates) { if (!canScroll) { return; } if (animator != null) { animator.removeUpdateListener(animUpdateListener); } if (scrollStates == 1) {// 從普通區域進入觸發向上滾動的區域 int instance = mMaxHeight - getHeight() - mCurrentY; animator = ValueAnimator.ofFloat(mCurrentY, mMaxHeight - getHeight()); animator.setDuration((long) (instance / 0.5f)); animator.setTarget(mGridView); animator.addUpdateListener(animUpdateListener); animator.start(); } else if (scrollStates == -1) {// 進入觸發向下滾動的區域 animator = ValueAnimator.ofFloat(mCurrentY, 0); animator.setDuration((long) (mCurrentY / 0.5f)); animator.setTarget(mGridView); animator.addUpdateListener(animUpdateListener); animator.start(); } } private OnDragSelectListener onDragSelectListener; /** * @描述:一個item view剛被拖拽和放下時起來生成映象時呼叫. * @作者 [pWX273343] 2015年6月30日 */ public void setOnDragSelectListener(OnDragSelectListener onDragSelectListener) { this.onDragSelectListener = onDragSelectListener; } public interface OnDragSelectListener { /** * @param mirror * 所拖拽起來的view生成的映象 ,並不是實際的view.可對這個映象實施變換效果,但是並不改變放下後的效果 * @描述:拖拽起一個view時呼叫 * @作者 [pWX273343] 2015年6月30日 */ void onDragSelect(View mirror); /** * @param itemView * @描述:拖拽的View放下時呼叫 * @作者 [pWX273343] 2015年7月3日 */ void onPutDown(View itemView); } class NoScrollGridView extends GridView { public NoScrollGridView(Context context) { super(context); } /** * @return * @描述:相容老版本的getColumWidth * @作者 [pWX273343] 2015年7月1日 */ public int getColumnWidth() { return getWidth() / getNumColumns(); } public NoScrollGridView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int mExpandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST); super.onMeasure(widthMeasureSpec, mExpandSpec); } } /** * * Copyright (C), 2008-2015, Huawei Tech. Co., Ltd. * <p> * Description : 監聽滾動的scrollview,我們需要實時知道他已滾動的距離 * * @author [pWX273343] 2015年7月22日 * @version V100R001 * @since V100R001 * */ class ListenScrollView extends ScrollView { public ListenScrollView(Context context) { super(context); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); mCurrentY = getScrollY(); } } public View getChildViewAtIndex(int index) { if (index < mChilds.size()) { return mChilds.get(index); } return null; } // 轉交給gridview一些常用監聽器 private OnItemLongClickListener itemLongClickListener; /** * * @描述:item 轉交給gridview一些常用監聽器 * * @param itemClickListener * @作者 [pWX273343] 2015年7月27日 */ public void setOnItemClickListener(OnItemClickListener itemClickListener) { mGridView.setOnItemClickListener(itemClickListener); } /** * 長按監聽器自己觸發,點選拖動模式不存在長按 * * @param */ public void setOnItemLongClickListener(OnItemLongClickListener itemLongClickListener) { this.itemLongClickListener = itemLongClickListener; } /** 點選拖動 */ public static final int DRAG_WHEN_TOUCH = 0; /** 長按拖動 */ public static final int DRAG_BY_LONG_CLICK = 1; private int mDragMode = DRAG_WHEN_TOUCH; /** * @param mode * int型別 * @描述:設定拖動的策略是點選還是長按 * @作者 [pWX273343] 2015年7月20日 參考 DRAG_WHEN_TOUCH,DRAG_BY_LONG_CLICK */ public void setDragModel(int mode) { this.mDragMode = mode; isDragable = mode == DRAG_WHEN_TOUCH; } public View childAt(int index) { return mGridView.getChildAt(index); } public int childCount() { return mGridView.getChildCount(); } public void setAnimFrame(FrameLayout mDragFrame) { this.mDragFrame = mDragFrame; } private OnTouchListener l; @Override public void setOnTouchListener(OnTouchListener l) { this.l = l; } private long dragLongPressTime = 600; /** * 設定長按需要用時 * * @param time */ public void setDragLongPressTime(long time) { dragLongPressTime = time; } }

相關推薦

Android實現一個流暢排序DragSortGridView,自動

/** * Copyright (C), 2008-2015, Huawei Tech. Co., Ltd. * <p/> * Description : 拖動排序佈局 * * @version V100R001 * @since V100R001 */ @SuppressLint(

實現智慧讀報逐字朗讀+自動

序言 最近在研究讀報的功能,想實現自動閱讀,即能朗讀,還能提示讀到什麼地方,反正是越方便越好。通過多次試驗終於成功了。實現了逐字朗讀變色,自動滾屏,螢幕常亮等功能。接下來你們將我再一次見識我的聰明才智。 效果 逐字朗讀,和自動滾屏 實現

一個div和讓一個panel加拉大拉小

let sha cli class 事件綁定 borde 設置 scrip script 一、讓一個div拖動 <!doctype html> <html xmlns="http://www.w3.org/1999/xhtml"> <head

實現一個圖片拽到一個div的程式

<!DOCTYPE HTML> <html> <head> <script type="text/javascript"> function allowDrop(ev) { // 除去預設的方式,預設是不可拖拖拽的

NodeMedia / NodeMediaClient-Android一個簡單,快速,免費的直播SDK

NodeMedia RTMP/RTMFP/RTSP/HTTP Play/Publish Client SDK for Android 用Gradle匯入 allprojects { repositories { google() jcenter()

類成員的可訪問性不管怎麼設計,實現一個類在記憶體中只能呼叫一次單態設計模式

為了控制建立物件的個數,需要收回建立物件的權利,下面想辦法設定Teacher為記憶體中唯一物件,在Text中建立並使用Teacher; Teacher package cn.net.sdkd.cise; public class Teacher { pri

Android 使用RecyclerView實現仿微信的聯絡人A-Z字母排序和過濾搜尋功能

之前做專案的時候遇到一個需求是實現品牌的字母排序功能,網上的資料很多,但是有一部分有bug,這篇文章是我學習和解決部分bug之後的總結。今天帶來的是RecyclerView的A-Z字母排序和過濾搜尋功能。 首先上效果圖: 重點:1、實現資料排序分類 2、

Android-計算器的實現介面佈局,計算邏輯處理

    原始碼下載    閒來無事,用android做一個計算器玩玩,想著做一個私密空間,表面是計算器,按下原先設定的算式後可以跳轉到私密介面,當想想有些費事,以後若還有閒散時間,再來實現。    介面是這樣的,採用了GridLayout佈局,很容易實現。程式碼如下<?

VR Android播放器實現

最近正在研究一款VR視訊播放器,需要通過rtsp直連到相機端,相機採用的雙鏡頭,直接出來的兩個畫面拼接的一路視訊流,播放器要把左右畫面分別在螢幕上左右部分分別顯示,還要實現陀螺儀的轉動以及後期新增魚眼

android圖片快取實現自定義ImageLoader

import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import android.content.Context; import android.graphics.Bitmap; import

Android購物車的實現升級版 仿淘寶

前面有篇文章實現了Android 簡單的購物車 這篇實現了購物車中商品按照店鋪分類顯示的 也就是淘寶購物車的顯示方式。 主要程式碼 package com.jock.shopcart; import java.util.ArrayList; impo

一臉懵逼學習Storm---一個開源的分布式實時計算系統

在線 協調 深入 tor grouping 分配 有一點 cbo con 1:什麽是Storm?  Storm是一個開源的分布式實時計算系統,可以簡單、可靠的處理大量的數據流。被稱作“實時的hadoop”。Storm有很多使用場景:如實時分析,在線機

...續上文一個小萌新的C語言之旅

double 調用函數 小數 一位 技術 類型 說過 fff 兩個 我們繼續上次沒介紹完的繼續講:     下面我們說一下二進制,二進制是計算技術中廣泛采用的一種 數制。 二進制數據是用0和1兩個 數碼來表示的數。它的基數為2,進位規則是“逢二進一”。那麽二進制怎麽轉化為十

陰陽師魂十掛機實現後臺控制代碼截圖+滑鼠點選

        學習繁忙,但是作為癢癢鼠的忠實粉,抽空寫了個小指令碼,後臺掛機魂十,業原火,御靈,覺醒,還是美滋滋的。 指令碼實現的關鍵主要有兩部分:一是通過控制代碼後臺獲得截圖,二是通過控制代碼後臺對視窗傳送滑鼠點選

Android ListView批量選擇全選、反選、全不選

轉載:https://blog.csdn.net/zuiwuyuan/article/details/50042841?utm_source=blogxgwz0  APP的開發中,會常遇到這樣的需求:批量取消(刪除)List中的資料。這就要求ListVIew支援批量選擇、全選、單選等等

連結串列排序演算法java實現連結串列的快速排序、插入排序、歸併排序

難易程度:★★ 重要性:★★★      連結串列的排序相對陣列的排序更為複雜些,也是考察求職者是否真正理解了排序演算法(而不是“死記硬背”) 連結串列的插入排序 public class LinkedInsertSort { static cla

FPGA邊沿檢測Verilog實現包含上升沿,下降沿,雙邊沿

寫在最前面:2019屆秋招進行中。。。希望能拿到自己滿意的offer。。。楊超越附體(手動狗頭)。。。 網上搜了一下,結合自己總結的。首先介紹一下基本的原理。 脈衝邊沿的特性:兩側電平發生了變化 思路:設計兩個或多個一位的暫存器,用來接收被檢測的訊號,系統時鐘來

排序演算法1——圖解氣泡排序及其實現三種方法,基於模板及函式指標

排序演算法1——圖解氣泡排序及其實現(三種方法,基於模板及函式指標) 排序演算法2——圖解簡單選擇排序及其實現 排序演算法3——圖解直接插入排序以及折半(二分)插入排序及其實現 排序演算法4——圖解希爾排序及其實現 排序演算法5——圖解堆排序及其實現 排序演算法6——圖解歸併排序及其遞迴與非

android app版本升級DownloadManager、適配6.0、7.0

說明: 1.本文使用系統DownloadManager在通知欄更新下載進度  2.動態許可權使用第三方庫EasyPermissions(https://github.com/googlesamples/easypermissions)  3.下載完成的App安裝適配7.0 

Android第六次——高階控制元件下拉框與搜尋框

1. 高階控制元件與低階控制元件區別    是否使用介面卡 2. 介面卡種類和作用   2.1 種類       陣列介面卡 ArrayAdapter         new ArrayAdapter<String>(this,R.layout.actv_sty