1. 程式人生 > >Android 打造可下拉的EditText--DropEditText

Android 打造可下拉的EditText--DropEditText

android的預設Spinner只能下拉選擇內容,而不能選擇,有時候我們想提供給使用者更加人性化的UI,既可以通過下拉選擇,也可以通過EditText輸入,是要定義兩個元件嗎? 這樣並不適合我們的設計要求。

那麼, 我們就自己寫一個這樣的元件吧——DropEditText。

一、思路

1、DropEditText並不是一個Spinner,也不是一個EditText。

2、這裡的解決方式是,組合以個EditText和一個ImageView,點選ImageView彈出一個PopupWindow達到下拉的效果。

二、問題

1、組合EditText和ImageView,而又不能讓使用者看出這是一個組合。

2、PopupWindow彈出的位置怎麼控制。

3、如何做到當點選PopupWindow上的選項,向EditText填充對應的內容。

三、效果

再開始程式碼之前,先看看預想的效果吧,有了目標才好code


通過效果圖可以看出,DropEditText還算比較靈活的,可以設定下拉的模式:跟隨上面和包裹內容。

四、解決問題

再回頭看看我們的問題。

第一個問題很好解決,相信很多人都可以輕鬆的解決。做法是用一個LinearLayout包裹EditText和ImageView,同時設定LinearLayout的背景為我們定義的shape,同時取消掉EditText預設的背景。

  1. <
    LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  2.     android:layout_width="match_parent"
  3.     android:layout_height="wrap_content"
  4.     android:orientation="horizontal"
  5.     android:background="@drawable/edit_bg_shape">
  6.     <EditText
  7.         android:id="@+id/dropview_edit"
  8.         android:layout_width
    ="0dip"
  9.         android:layout_weight="1"
  10.         android:layout_height="wrap_content"
  11.         style="?android:attr/textViewStyle"
  12.         android:background="@null"
  13.         android:height="40dip"/>
  14.     <ImageView
  15.         android:id="@+id/dropview_image"
  16.         android:layout_width="wrap_content"
  17.         android:layout_height="match_parent"
  18.         android:layout_gravity="center_vertical"
  19.         android:scaleType="fitXY"
  20.         android:layout_marginTop="2dip"
  21.         android:layout_marginBottom="2dip"
  22.         android:paddingRight="2dip"/>
  23. </LinearLayout>
第二個問題,控制PopupWindow的彈出的位置,很明顯我們需要它顯示在EditText上下面,sdk給我們提供了一個很好的方法:
  1. PopupWindow.showAsDropDown(anchor, xoff, yoff)  
引數1:以哪個view為目標彈出

引數2:x偏移量

引數3:y的偏移量

第二個問題就這麼輕鬆的解決了。

第三個問題,我想到了用ListView做,用ListView做可以很方便的取item,但是有一個問題:ListView預設是佔滿橫向的螢幕的,但這也不是問題,我們可以重寫ListView的onMeasure方法改變它的測量機制。

五、上程式碼

先來看看重寫的ListView吧,做的工作就是重寫onMeasure方法,使它的寬度可變,還提供了一個方法可以設定ListView的寬度:

  1. publicclass WrapListView extends ListView {  
  2.     privateint mWidth = 0;  
  3.     public WrapListView(Context context, AttributeSet attrs) {  
  4.         this(context, attrs, 0);  
  5.     }  
  6.     public WrapListView(Context context, AttributeSet attrs, int defStyle) {  
  7.         super(context, attrs, defStyle);  
  8.     }  
  9.     // 重寫onMeasure方法 解決預設橫向佔滿螢幕問題
  10.     @Override
  11.     protectedvoid onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  12.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  13.         int height = getMeasuredHeight();  
  14.         // measureChildren(widthMeasureSpec, heightMeasureSpec);
  15.         for(int i=0;i<getChildCount();i++) {  
  16.             int childWidth = getChildAt(i).getMeasuredWidth();  
  17.             mWidth = Math.max(mWidth, childWidth);  
  18.         }  
  19.         setMeasuredDimension(mWidth, height);  
  20.     }  
  21.     /** 
  22.      * 設定寬度,如果不設定,則預設包裹內容 
  23.      * @param width 寬度 
  24.      */
  25.     protectedvoid setListWidth(int width) {  
  26.         mWidth = width;  
  27.     }  
  28. }  
重點在14~25行,首先我們呼叫了一下父類的onMeasure方法,為的就是利用ListView預設的測量機制獲取總高度。在第17行我們獲取了測量後的高度,接下來就是一個for迴圈,取出每一個item,並獲取他的高度。mWidth的值就是子item中最寬的那個item的寬度(當然在下面我們提供的方法中可以手動修改mWidth的值)。

自定義的setListWidth方法可以手動設定ListView的寬度,按說,我們改變了width的值,應該requestLayout()一下讓ListView重走一下測量流程才對,但這裡沒有提供。答案就是:ListView預設是不顯示的,只有在點選了drop圖示後才會出現,也就是setListWidth()永遠會走在onMeasure前面,可能到這裡會有點暈,看完下面的程式碼後就會清楚了。

再來看看DropEditText吧,這個View是組合了EditTextImageView,內建了一個PopupWindow,讓元件用起來更見方便。

  1. publicclass DropEditText extends FrameLayout implements View.OnClickListener, OnItemClickListener {  
  2.     private EditText mEditText;  // 輸入框
  3.     private ImageView mDropImage; // 右邊的圖片按鈕
  4.     private PopupWindow mPopup; // 點選圖片彈出popupwindow
  5.     private WrapListView mPopView; // popupwindow的佈局
  6.     privateint mDrawableLeft;  
  7.     privateint mDropMode; // flower_parent or wrap_content
  8.     private String mHit;  
  9.     public DropEditText(Context context, AttributeSet attrs) {  
  10.         this(context, attrs, 0);  
  11.     }  
  12.     public DropEditText(Context context, AttributeSet attrs, int defStyle) {  
  13.         super(context, attrs, defStyle);  
  14.         LayoutInflater.from(context).inflate(R.layout.edit_layout, this);  
  15.         mPopView = (WrapListView) LayoutInflater.from(context).inflate(R.layout.pop_view, null);  
  16.         TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.DropEditText, defStyle, 0);  
  17.         mDrawableLeft = ta.getResourceId(R.styleable.DropEditText_drawableRight, R.drawable.ic_launcher);  
  18.         mDropMode = ta.getInt(R.styleable.DropEditText_dropMode, 0);  
  19.         mHit = ta.getString(R.styleable.DropEditText_hint);  
  20.         ta.recycle();  
  21.     }  
  22.     @Override
  23.     protectedvoid onFinishInflate() {  
  24.         super.onFinishInflate();  
  25.         mEditText = (EditText) findViewById(R.id.dropview_edit);  
  26.         mDropImage = (ImageView) findViewById(R.id.dropview_image);  
  27.         mEditText.setSelectAllOnFocus(true);  
  28.         mDropImage.setImageResource(mDrawableLeft);  
  29.         if(!TextUtils.isEmpty(mHit)) {  
  30.             mEditText.setHint(mHit);  
  31.         }  
  32.         mDropImage.setOnClickListener(this);  
  33.         mPopView.setOnItemClickListener(this);  
  34.     }  
  35.     @Override
  36.     protectedvoid onLayout(boolean changed, int left, int top, int right,  
  37.             int bottom) {  
  38.         super.onLayout(changed, left, top, right, bottom);  
  39.         // 如果佈局發生改
  40.         // 並且dropMode是flower_parent
  41.         // 則設定ListView的寬度
  42.         if(changed && 0 == mDropMode) {  
  43.             mPopView.setListWidth(getMeasuredWidth());  
  44.         }  
  45.     }  
  46.     /** 
  47.      * 設定Adapter 
  48.      * @param adapter ListView的Adapter 
  49.      */
  50.     publicvoid setAdapter(BaseAdapter adapter) {  
  51.         mPopView.setAdapter(adapter);  
  52.         mPopup = new PopupWindow(mPopView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);  
  53.         mPopup.setBackgroundDrawable(new ColorDrawable(color.transparent));  
  54.         mPopup.setFocusable(true); // 讓popwin獲取焦點
  55.     }  
  56.     /** 
  57.      * 獲取輸入框內的內容 
  58.      * @return String content 
  59.      */
  60.     public String getText() {  
  61.         return mEditText.getText().toString();  
  62.     }  
  63.     @Override
  64.     publicvoid onClick(View v) {  
  65.         if(v.getId() == R.id.dropview_image) {  
  66.             if(mPopup.isShowing()) {  
  67.                 mPopup.dismiss();  
  68.                 return;  
  69.             }  
  70.             mPopup.showAsDropDown(

    相關推薦

    Android 打造EditText--DropEditText

    android的預設Spinner只能下拉選擇內容,而不能選擇,有時候我們想提供給使用者更加人性化的UI,既可以通過下拉選擇,也可以通過EditText輸入,是要定義兩個元件嗎? 這樣並不適合我們的設計要求。 那麼, 我們就自己寫一個這樣的元件吧——DropEditTe

    Android 仿美團網,大眾點評購買框懸浮效果,仿美團詳情頁,放大圖片,向上滾動圖片,鬆手有動畫

    先看效果圖 直接上程式碼註釋都寫到程式碼裡面了: 自定義的ScrollView package mm.shandong.com.testmtxqcomplex.myui; import android.content.Context; import andro

    Android中的列表

    creat get targe eight down things trie XML eat 在Web開發中,HTML提供了下拉列表的實現,就是使用<select>元素實現一個下拉列表,在其中每個下拉列表項使用<option>表示即可。這是在Web開

    【QT】 QComboBox實現編輯

    1.設定可編輯模式 comboBox->setEditable(true); 2.設定可編輯模式後,可以獲取comboBox裡QLineEdit 指向comboBox對應的QLineEdit,注意非可編輯模式,該物件為NULL comboBox->lineEdit()

    Android圖片與

    . ImageView(圖片框) 注意事項:res下面的資源名不能使用大寫字母,特別是圖片資源中的圖片的檔名,會造成R.java檔案丟失,改正確後即可 在div裡面放圖片 scaleType的屬性值有:matrix   fitXY  fitStart &nb

    的PinnedHeaderExpandableListView的實現

    分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

    Android中ListView重新整理上載入更多效果實現

      在Android開發中,下拉重新整理和上拉載入更多在很多app中都會有用到,下面就是具體的實現的方法。 首先,我們自定義一個RefreshListView來繼承與ListView,下面是程式碼: package com.example.downrefresh; import

    android實現帶列表的文字框

    android實現帶下拉列表的文字框 keywords:android studio、EditText、ImageView、PopupMenu。 佈局 <TextView android:layout_width="wrap_c

    Android簡單的重新整理,上載入

    先匯入第三方的東西 下載地址 匯入後,就和你的專案聯絡起來 佈局程式碼(activity_pull_to_refresh_action.xml) <?xml version="1.0" encoding="utf-8"?> <Lin

    Android LRecyclerView實現重新整理,滑動到底部自動載入更多

                         隨著功能的不斷優化,框架中的類或者介面名字會有變動,為了獲取準確的使用方法,請參考最新的說明文件:點此檢視。簡介LRecyclerView是支援addHeaderView、 addFooterView、下拉重新整理、分頁載入資料的RecyclerView。它對 Rec

    Android SwipeRefreshLayout 官方重新整理控制元件介紹

                    轉載請標明出處:http://blog.csdn.net/lmj623565791/article/details/24521483下面App基本都有下拉重新整理的功能,以前基本都使用XListView或者自己寫一個下拉重新整理,近期Google提供了一個官方的下拉重新整理控制

    Android中ListView重新整理的實現

    ListView中的下拉重新整理是非常常見的,也是經常使用的,看到有很多同學想要,那我就整理一下,供大家參考。那我就不解釋,直接上程式碼了。 這裡需要自己重寫一下ListView,重寫程式碼如下: package net.loonggg.listview; impor

    android自定義重新整理和上載入控制元件

    import android.content.Context; import android.graphics.Point; import android.support.v4.view.MotionEventCompat; import android.support.v4.view.NestedScro

    Android ListView 實現重新整理上載入

    1.簡介        無疑,在Android開發中,ListView是使用非常頻繁的控制元件之一,ListView提供一個列表的容易,允許我們以列表的形式將資料展示到介面上,但是Google給我們提供的原生ListView的控制元件,雖然在功能上很強大,但是在使用

    Android--Google官方重新整理SwipeRefreshLayout(附加增加上載入)

    Demo_SwipeRefreshLayout 下拉重新整理是用系統的控制元件,但是這控制元件本身不帶有上拉載入,上拉載入需要在ListView的Adapter中設定 需要V4包的支援 compile 'com.android.support:support-v4

    Android中Spinner列表(使用ArrayAdapter和自定義Adapter實現)

         今天學習了Spinner元件,使用Spinner相當於從下拉列表中選擇專案,下面演示一下Spinner的使用(分別使用ArrayAdapter和自定義Adapter實現) (一):使用Arr

    Android SwipeRefreshLayout官方重新整理控制元件介紹(與知乎Android客戶端重新整理一樣!!)

    轉載出處:http://blog.csdn.net/lmj623565791/article/details/24521483 //沒少看鴻洋老師的視訊,一如既往,鴻洋老師講解的淺顯易懂! 下面App基本都有下拉重新整理的功能,以前基本都使用XListView或者自己

    android 控制元件 重新整理 phoenix 帶原始碼分析

    向納什致敬,鳳凰城永遠的英雄!phoenix Yalantis 致力於提供世界一流的 Android 和 iOS 應用開發服務,因一些 動畫很棒的開源庫為大家所熟知 Phoenix-Android 旨在提供一個簡單的可定製的下拉重新整理功能。 <com

    Android 自定義重新整理和上載入

    完整程式碼在最下面。。 頭佈局xml: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_pare

    新增Header重新整理的RecyclerView

    RefreshRecyclerView 下拉重新整理的RecyclerView,兼有上拉載入更多、新增頭部、定製腳部功能,下拉重新整理使用SwipeRefreshLayout。 程式碼在這 效果圖 用法 新增Header和Footer F