[置顶] xamarin android自定义spinner

以前弄的一个下拉框时自带的spinner,感觉好丑,实际效果实在满足不了基本的UI界面要求,还是自己动手丰衣足食,看了网上关于android中自定义spinner的文章,感觉实现原理还是比较简单,所以这里用xamarin android来实现自定义spinner样式。参考文章:http://blog.csdn.net/jdsjlzx/article/details/41316417

实现原理
1.TextView中显示选择的内容,右边显示上下的箭头,点击事件中设置不同的箭头
2.TextView下显示的是一个PoputWindow,PoputWindow中显示的自定义ListView,在TextView单击事件中显示ListView就是下拉的选择项。
先来看看最终的效果图
这里写图片描述

代码实现的过程主要分为以下几个部分:

  1. MainActivity布局实现(这个就是一个TextView)
  2. PoputWindow布局和ListView布局实现
  3. 自定类SpinerPopWindow继承PoputWIndow的实现,ListView适配器类的实现(实现的关键)
  4. MainActivity.cs中TextView事件监听、ListView的Item单击事件的监听实现

1. MainActivity布局实现

MainActivity中只有一个TextView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingRight="20dp"
     android:background="@color/color_ffffff"
    android:paddingLeft="20dp">
    <TextView
        android:id="@+id/tv_value"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/color_dedede"
        android:drawableRight="@drawable/icon_down"
        android:padding="10dp"
        android:textColor="@color/content_color"
        android:textSize="20sp" />
</LinearLayout>

2.PoputWindow布局和ListView布局实现

1.PoputWindow里面放的是一个ListView控件。spinner_window_layout.xml的background需要添加边框、设置背景颜色

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentRight="true"
    android:orientation="vertical">
    <ListView
        android:id="@+id/listview"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:cacheColorHint="#00000000"
        android:background="@drawable/shape_popupwindow_list_bg"
        android:scrollbars="none" >
    </ListView>
</LinearLayout>

2.ListView布局文件spinner_item_layout里面只有一个TextView

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:text="fdsfdsfdsf"
        android:textSize="20sp"/>
</LinearLayout>

3.自定类SpinerPopWindow继承PoputWIndow的实现,ListView适配器类的实现(实现的关键)

spinnerPopWindow.cs需要继承PoputWindow,初始化ListView。ListView的Adapter类LVAdapter就不多说了。

using System.Collections.Generic;
using System.Linq;
using Android.Content;
using Android.Views;
using Android.Widget;
using Android.Graphics.Drawables;
using static Android.Views.ViewGroup;
namespace customSpinnerDemo
{
    public  class SpinerPopWindow<T>:PopupWindow
    {
        private ListView listView;
        private List<T> list;
        private LVAdapter<T> adapter;
        private Context context;
        private LayoutInflater inflater;
        public SpinerPopWindow(Context _context ,List<T> _list, AdapterView.IOnItemClickListener itemClickListener)
        {
            context = _context;
            list = _list;
            inflater = LayoutInflater.From(_context);
            InitListView(itemClickListener);
        }
        private void InitListView(AdapterView.IOnItemClickListener itemClickListener)
        {
            View view = inflater.Inflate(Resource.Layout.spiner_window_layout, null);
            this.ContentView = view;
            //LayoutParams
            var parentView = (ViewGroup)view;
            var child  = parentView.GetChildAt(0);
            this.Width = LayoutParams.WrapContent;
            this.Height = LayoutParams.WrapContent;
            this.Focusable = true;
            ColorDrawable cdw = new ColorDrawable(Android.Graphics.Color.Transparent);
            SetBackgroundDrawable(cdw);
            //View childView = ContentView

            listView = view.FindViewById<ListView>(Resource.Id.listview);
            adapter = new customSpinnerDemo.LVAdapter<T>(context,list);
            listView.Adapter = adapter;
            listView.OnItemClickListener = itemClickListener;
        }
    }
    public class LVAdapter<T> : BaseAdapter
    {
        private List<T> list;
        private Context context;
        public LVAdapter(Context _context,List<T> _list)
        {
            context = _context;
            list = _list;
        }
        public override int Count
        {
            get{
                return list.Count();
            }
        }
        public override Java.Lang.Object GetItem(int position)
        {
            return null;
        }
        public override long GetItemId(int position)
        {
            return position;
        }
        public override View GetView(int position, View convertView, ViewGroup parent)
        {
            ViewHolder holder = null;
            if (convertView == null)
            {
                holder = new ViewHolder();
                convertView = LayoutInflater.From(context).Inflate(Resource.Layout.spiner_item_layout,parent,false);
                holder.tvName = convertView.FindViewById<TextView>(Resource.Id.tv_name);
                convertView.Tag = holder;
            }
            else
            {
                holder = (ViewHolder)convertView.Tag;
            }
            holder.tvName.Text = list[position].ToString();
            return convertView; 
        }
        private class ViewHolder:Java.Lang.Object {
            internal TextView tvName;
        }
    }
}

4.MainActivity.cs中TextView事件监听、ListView的Item单击事件的监听实现
实现的原理就是一下代码了

using Android.App;
using Android.Widget;
using Android.OS;
using System.Collections.Generic;
using static Android.Widget.AdapterView;
using Android.Views;
using Android.Graphics.Drawables;
using Android.Support.V7.App;
namespace customSpinnerDemo
{
    [Activity(Label = "customSpinnerDemo", MainLauncher = true, Icon = "@drawable/icon",Theme = "@style/AppTheme")]
    public class MainActivity : AppCompatActivity, IOnItemClickListener, PopupWindow.IOnDismissListener
    {
        private List<string> list;
        private TextView tv_value;
        private SpinerPopWindow<string> SpinnerPopwindow;
        protected override void OnCreate(Bundle bundle)
        {
            base.OnCreate(bundle);
            SetContentView (Resource.Layout.Main);
            tv_value = FindViewById<TextView>(Resource.Id.tv_value);
            tv_value.Click += (s,e) =>
            {
                SpinnerPopwindow.Width = tv_value.Width;
                SpinnerPopwindow.ShowAsDropDown(tv_value);
                SetTextImage(Resource.Drawable.icon_up);
            };
            list = new List<string>() { "科比","詹姆斯","韦德","波什"};
            SpinnerPopwindow = new SpinerPopWindow<string>(this,list,this);
            SpinnerPopwindow.SetOnDismissListener(this);
        }
        /// <summary>
        /// 给TextView右边设置图片
        /// </summary>
        private void SetTextImage(int resId)
        {
            //var drawable =GetDrawable(resId);
            Drawable drawable = Resources.GetDrawable(resId);
            drawable.SetBounds(0,0,drawable.MinimumWidth,drawable.MinimumHeight);
            tv_value.SetCompoundDrawables(null,null,drawable,null);
        }
        /// <summary>
        /// popupWindow 显示的ListView的item点击事件
        /// </summary>
        public void OnItemClick(AdapterView parent, View view, int position, long id)
        {
            SpinnerPopwindow.Dismiss();
            tv_value.Text=list[position].ToString();
            Toast.MakeText(this,"点击了:"+list[position],ToastLength.Long).Show();
        }
        /// <summary>
        /// popupWindow取消
        /// </summary>
        public void OnDismiss()
        {
            SetTextImage(Resource.Drawable.icon_down);
        }
    }
}

小结

虽然实现原理比较简单,但是要把一个下拉框做的能够调用简单,代码多处复用,代码量小而简单,还是需要琢磨的。

posted @ 2017-07-14 21:38  张林-布莱恩特  阅读(376)  评论(0编辑  收藏  举报
博客统计by flagcounter: