精华内容
下载资源
问答
  • 自定义下拉列表

    2016-01-04 14:57:17
    自定义下拉列表,通过PopupWindow实现下拉列表,下拉列表的宽度和下拉框的宽度一样,使下拉列表看起来更整体。
  • 安卓自定义下拉列表样式View demo 查看演示Download Source 下载源Hi guys! I’m back with another article just for you, and CSS related of course! This time, we are going to talk (and ...
    安卓自定义下拉列表样式

    安卓自定义下拉列表样式

    Custom Drop-Down List Styling

    Hi guys! I’m back with another article just for you, and CSS related of course! This time, we are going to talk (and do stuff!) about something a bit more practical than button switches: drop-down lists. The point of this tutorial is to show how to create nice drop-downs without any image but with CSS only. We’ll add some line of jQuery to make them work.

    嗨,大家好! 我回来了另一本只为您介绍的文章,并且与CSS有关! 这次,我们将讨论(并做一些事情!)比按钮开关更实用的东西:下拉列表。 本教程的重点是显示如何创建美观的下拉菜单,而不显示任何图像,而仅使用CSS。 我们将添加一些jQuery行以使其工作。

    A few things before starting:

    开始之前的几件事:

    • You won’t see any vendor prefixes in the CSS snippets, but you will, of course, find them in the files.

      您不会在CSS片段中看到任何供应商前缀,但是您当然会在文件中找到它们。
    • I personally use the box-model where [width] = [element-width] + [padding] + [borders]. I activate it with the following snippet:

      我个人使用[[width] = [element-width] + [padding] + [borders]的盒子模型。 我使用以下代码段激活它:

      
      		*,
      		*:after,
      		*:before {
      		    box-sizing: border-box;
      		}
      		
      

    我们如何开始?(How do we start?)

    First question: what do we need to create a drop-down? In general, we’ll use a division with a span and an unordered list for the drop-down list (we might tweak this for some examples):

    第一个问题:创建下拉菜单需要什么? 通常,我们将使用一个带跨度的除法器和一个无序列表作为下拉列表(对于某些示例,我们可能会对其进行调整):

    
    <div class="wrapper-dropdown">
    	<span>I'm kinda the label!</span>
    	<ul class="dropdown">
    		<li>I'm hidden!</li>
    		<li>Me too!</li>
    		<li>So do I.</li>
    	</ul>
    </div>
    
    

    JavaScript(The JavaScript)

    For now and before everything else, we need some JavaScript to make this work. Since it’s basically the same JS snippet for all demos, let’s deal with it now:

    就目前而言,在一切之前,我们需要一些JavaScript才能完成这项工作。 由于对于所有演示来说,它基本上都是相同的JS代码段,所以让我们现在处理它:

    
    	//...
    
    	obj.dd.on('click', function(event){
    		$(this).toggleClass('active');
    		return false;
    	});
    
    	//...
    
    	$(function() {
    
    		var dd = new DropDown( $('#dd') );
    
    		$(document).click(function() {
    			// all dropdowns
    			$('.wrapper-dropdown-1').removeClass('active');
    		});
    
    	});
    
    

    So what does this script do exactly? First, it toggles a class called .active when you click on the wrapper. It means if the wrapper doesn’t have the .active class, it adds it, and if it does, it removes it.

    那么,该脚本到底能做什么? 首先,当您单击包装器时,它将切换一个名为.active的类。 这意味着如果包装器没有.active类,则将其添加,如果有,则将其删除。

    Second thing, it replicates the default behavior of a select drop-down by closing it if you click anywhere else on the screen. Basically, the script says if we click on a child from the <html> tag (so every single node on the DOM), the wrapper loses its .active class. But we prevent this behavior on the wrapper itself by stopping the propagation. Fairly simple, right?

    第二件事,如果您单击屏幕上的任何其他位置,它将通过关闭选择下拉列表来复制默认行为。 基本上,脚本说如果我们从<html>标记中单击一个子项(因此DOM上的每个节点),则包装器将丢失其.active类。 但是我们通过停止传播来防止包装器自身发生此行为。 很简单,对吧?

    Well, now we understand how it works, I guess it’s time to create some neat drop-downs!

    好了,现在我们了解了它的工作原理,我想是时候创建一些简洁的下拉列表了!

    例子1 (Example 1)

    Let’s start with something simple: a basic drop-down for gender. Let’s look at the markup first:

    让我们从简单的事情开始:性别的基本下拉列表。 让我们先看一下标记:

    标记 (The Markup)

    We need a few things: a wrapper, a (hidden) drop-down list and a “label” which we will wrap into a span. We use anchors because it seems semantically correct to me, but we could have also used another tag.

    我们需要一些东西:包装器,一个(隐藏的)下拉列表和一个“标签”,我们将它们包装成一个范围。 我们使用锚点是因为它对我而言在语义上是正确的,但我们也可以使用其他标记。

    
    <div id="dd" class="wrapper-dropdown-1" tabindex="1">
    	<span>Gender</span>
        <ul class="dropdown">
            <li><a href="#">Male</a></li>
            <li><a href="#">Female</a></li>
        </ul>
    </div>
    
    

    CSS(The CSS)

    Let’s dig into the CSS which is our focus in this tutorial. We will start with the wrapper:

    让我们深入研究CSS,这是本教程的重点。 我们将从包装器开始:

    
    .wrapper-dropdown {
        /* Size and position */
        position: relative; /* Enable absolute positioning for children and pseudo elements */
        width: 200px;
        padding: 10px;
        margin: 0 auto;
    
        /* Styles */
        background: #9bc7de;
        color: #fff;
        outline: none;
        cursor: pointer;
    
        /* Font settings */
        font-weight: bold;
    }
    
    

    We did a few things here. First we set a width to our dropdown and some paddings/margins. Next, we gave it some styles. And finally, we set some font settings, which will cascade to the dropdown itself.

    我们在这里做了一些事情。 首先,我们为下拉菜单和一些填充/边距设置宽度。 接下来,我们给它一些样式。 最后,我们设置一些字体设置,这些设置将级联到下拉菜单本身。

    Let’s finish with the “label” by adding the little arrow on the right with a pseudo-element (styling purpose = no extra markup).

    让我们以“标签”结束,在右边添加一个带有伪元素的小箭头(样式目的=没有额外的标记)。

    
    .wrapper-dropdown:after {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        right: 16px;
        top: 50%;
        margin-top: -6px;
        border-width: 6px 0 6px 6px;
        border-style: solid;
        border-color: transparent #fff;    
    }
    
    

    I think we all know how to create a little triangle with CSS thanks to some border tricks. It’s a hack yep, but it works pretty well so why not? Nothing much there then: a little white down arrow on the right of the wrapper.

    我想我们都知道由于一些边框技巧,如何使用CSS创建一个小三角形。 是的,是的,但是效果很好,为什么不呢? 那里没什么了:包装纸右边的白色向下箭头。

    We have a nice little button there, but without an actual drop-down it has no point really. So let’s deal with our list!

    我们在那里有一个漂亮的小按钮,但是没有实际的下拉菜单实际上没有任何意义。 因此,让我们处理一下清单!

    
    .wrapper-dropdown-1 .dropdown {
    	/* Size & position */
        position: absolute;
        top: 100%;
        left: 0; /* Size */
        right: 0; /* Size */
    
        /* Styles */
        background: #fff;
        font-weight: normal; /* Overwrites previous font-weight: bold; */
    
        /* Hiding */
        opacity: 0;
        pointer-events: none;
    }
    
    

    What did we just do? We give the drop-down absolute positioning and placed it just behind the button (top: 100%;). We gave it the same width as the button with the left and right values set to 0. And more importantly, we hide it by reducing its opacity to 0. What about pointer-events? Not seeing something doesn’t mean it’s not there. Setting pointer-events to none prevents clicking on the dropdown while it’s “hidden”.

    我们刚刚做了什么? 我们给出下拉菜单的绝对位置,并将其放置在按钮的后面( top: 100%; )。 我们将其宽度设置为与按钮的宽度相同,并且将左值和右值设置为0。更重要的是,我们通过将其不透明度降低为0来隐藏它。指针事件呢? 没有看到东西并不意味着它不存在。 将指针事件设置为none可以防止在“隐藏”状态下单击下拉列表。

    Let’s give some styles to the list elements inside the dropdown:

    让我们为下拉列表中的列表元素提供一些样式:

    
    .wrapper-dropdown-1 .dropdown li a {
        display: block;
        text-decoration: none;
        color: #9e9e9e;
        padding: 10px 20px;
    }
    
    /* Hover state */
    .wrapper-dropdown-1 .dropdown li:hover a {
        background: #f3f8f8;
    }
    
    

    Okay, so we have a nice button and a nice hidden drop-down menu. Now we have to deal with the “open” case when you click on the button to show the options. With JavaScript we toggle a class .active when we click on the button, so based on this class we can change our CSS to show the drop-down.

    好的,我们有一个不错的按钮和一个不错的隐藏下拉菜单。 现在,当您单击按钮以显示选项时,我们必须处理“打开”情况。 使用JavaScript,我们在单击按钮时会切换一个.active类,因此基于该类,我们可以更改CSS以显示下拉菜单。

    
    /* Active state */
    .wrapper-dropdown-1.active .dropdown {
        opacity: 1;
        pointer-events: auto;
    }
    
    .wrapper-dropdown-1.active:after {
        border-color: #9bc7de transparent;
        border-width: 6px 6px 0 6px ;
        margin-top: -3px;
    }
    
    .wrapper-dropdown-1.active {
      background: #9bc7de;
      background: linear-gradient(to right, #9bc7de 0%, #9bc7de 78%, #ffffff 78%, #ffffff 100%);
    }			
    
    

    Three things here:

    这里的三件事:

    • First, we make the drop-down appear by turning its opacity to 1. Don’t forget to set the pointer-event to auto to enable the interaction with it!

      首先,我们将下拉菜单的不透明度设置为1,以显示下拉菜单。不要忘记将指针事件设置为auto来启用与它的交互!
    • Next, we change the direction and the color of the little arrow.

      接下来,我们更改小箭头的方向和颜色。
    • Then, we change the background behind the arrow by using a clever gradient on the button. Isn’t that nice?

      然后,通过在按钮上使用智能渐变来更改箭头后面的背景。 那不是很好吗?

    JavaScript (The JavaScript)

    Last but not least, we also have to add another JavaScript snippet to make the button display the selected value.

    最后但并非最不重要的一点是,我们还必须添加另一个JavaScript代码段以使按钮显示所选值。

    
    function DropDown(el) {
        this.dd = el;
        this.placeholder = this.dd.children('span');
        this.opts = this.dd.find('ul.dropdown > li');
        this.val = '';
        this.index = -1;
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;
    
            obj.dd.on('click', function(event){
                $(this).toggleClass('active');
                return false;
            });
    
            obj.opts.on('click',function(){
                var opt = $(this);
                obj.val = opt.text();
                obj.index = opt.index();
                obj.placeholder.text('Gender: ' + obj.val);
            });
        },
        getValue : function() {
            return this.val;
        },
        getIndex : function() {
            return this.index;
        }
    }
    
    

    Very simple code here: when an element is clicked we get its value and display it in the “label”.

    此处的代码非常简单:单击某个元素后,我们将获得其值并将其显示在“标签”中。

    例子2 (Example 2)

    What a beautiful little drop-down to choose your way to sign in! I know, we use to have fancy buttons for that but let’s try something new, shall we?

    选择您的登录方式真是个美丽的小下拉菜单! 我知道,我们过去常常为此花哨的按钮,但让我们尝试一些新的东西,对吧?

    标记 (The Markup)

    
    <div id="dd" class="wrapper-dropdown-2">Sign in with
    	<ul class="dropdown">
    		<li><a href="#"><i class="icon-twitter icon-large"></i>Twitter</a></li>
    		<li><a href="#"><i class="icon-github icon-large"></i>Github</a></li>
    		<li><a href="#"><i class="icon-facebook icon-large"></i>Facebook</a></li>
    	</ul>
    </div>
    
    

    The <i> tags are used to display little icons from FontAwesome. I won’t explain all the FontAwesome stuff here because it has already been covered multiple times, I guess. Just make sure it works. 😛

    <i>标记用于显示FontAwesome中的小图标。 我想这里不会解释所有FontAwesome的东西,因为它已经被覆盖过多次了。 只要确保它能工作即可。 😛

    CSS (The CSS)

    Let’s start with the wrapper, shall we? Pretty much the same as the wrapper in the previous example. Note the 5px left border, it’s important for the following. 😉

    让我们从包装器开始吧? 与上一个示例中的包装程序几乎相同。 请注意5px的左边框,这对于以下操作很重要。 😉

    
    .wrapper-dropdown-2 {
        /* Size and position */
        position: relative; /* Enable absolute positioning for children and pseudo elements */
        width: 200px;
        margin: 0 auto;
        padding: 10px 15px;
    
        /* Styles */
        background: #fff;
        border-left: 5px solid grey;
        cursor: pointer;
        outline: none;
    }
    
    

    Now the little arrow. Exactly the same as before:

    现在是小箭头。 与之前完全相同:

    
    .wrapper-dropdown-2:after {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        right: 16px;
        top: 50%;
        margin-top: -3px;
        border-width: 6px 6px 0 6px;
        border-style: solid;
        border-color: grey transparent;
    }
    
    

    And here comes the drop-down list. Again, it’s pretty much the same thing like in the previous example:

    这是下拉列表。 同样,它与上一个示例几乎相同:

    
    .wrapper-dropdown-2 .dropdown {
      /* Size & position */
        position: absolute;
        top: 100%;
        left: -5px;
        right: 0px;
    
        /* Styles */
        background: white;
        transition: all 0.3s ease-out;
        list-style: none;
    
        /* Hiding */
        opacity: 0;
        pointer-events: none;
    }
    
    

    Please note the transition that we’ll use to make the drop-down progressively appear (animate) instead of simply pop up like in the first demo.

    请注意,我们将用于逐步显示下拉列表(动画)的过渡,而不是像第一个演示中那样简单地弹出。

    Some styles for the links and the icons:

    链接和图标的一些样式:

    
    .wrapper-dropdown-2 .dropdown li a {
        display: block;
        text-decoration: none;
        color: #333;
        border-left: 5px solid;
        padding: 10px;
        transition: all 0.3s ease-out;
    }
    
    .wrapper-dropdown-2 .dropdown li:nth-child(1) a { 
        border-left-color: #00ACED;
    }
    
    .wrapper-dropdown-2 .dropdown li:nth-child(2) a {
        border-left-color: #4183C4;
    }
    
    .wrapper-dropdown-2 .dropdown li:nth-child(3) a {
        border-left-color: #3B5998;
    }
    
    .wrapper-dropdown-2 .dropdown li i {
        margin-right: 5px;
        color: inherit;
        vertical-align: middle;
    }
    
    /* Hover state */
    
    .wrapper-dropdown-2 .dropdown li:hover a {
        color: grey;
    }
    
    

    We give the links a left border with a color based on the brand they stand for. The text is slightly indented to the right via a margin-right on the icons.

    根据链接所代表的品牌,我们为链接的左侧边框加上颜色。 文本通过图标上的右空白向右稍微缩进。

    And now, the expanded state. Pretty straight forward: the arrow changes direction, and the drop-down list becomes visible. Thanks to the transition property on the drop-down, it appears progressively (opacity animates from 0 to 1).

    而现在,扩展状态。 非常简单:箭头会更改方向,并且下拉列表将变为可见。 由于下拉菜单中的transition属性,它逐渐显示(不透明度从0到1动画)。

    
    .wrapper-dropdown-2.active:after {
        border-width: 0 6px 6px 6px;
    }
    
    .wrapper-dropdown-2.active .dropdown {
        opacity: 1;
        pointer-events: auto;
    }
    
    

    JavaScript(The JavaScript)

    
    function DropDown(el) {
        this.dd = el;
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;
    
            obj.dd.on('click', function(event){
                $(this).toggleClass('active');
                event.stopPropagation();
            }); 
        }
    }
    
    

    例子3(Example 3)

    This one is probably the one which comes the closest to a regular select element. Indeed, when you pick something, the label’s default value is replaced by the picked value. On a side note: it looks great doesn’t it?

    这可能是最接近常规选择元素的那个。 确实,当您选择某物时,标签的默认值将替换为所选择的值。 附带说明:看起来不错,不是吗?

    标记 (The Markup)

    
    <div id="dd" class="wrapper-dropdown-3" tabindex="1">
    	<span>Transport</span>
    	<ul class="dropdown">
    		<li><a href="#"><i class="icon-envelope icon-large"></i>Classic mail</a></li>
    		<li><a href="#"><i class="icon-truck icon-large"></i>UPS Delivery</a></li>
    		<li><a href="#"><i class="icon-plane icon-large"></i>Private jet</a></li>
    	</ul>
    </div>
    
    

    Not much more than before. Let’s go with the CSS!

    没有比以前更多。 让我们一起来看看CSS!

    CSS (The CSS)

    
    .wrapper-dropdown-3 {
        /* Size and position */
        position: relative;
        width: 200px;
        margin: 0 auto;
        padding: 10px;
    
        /* Styles */
        background: #fff;
        border-radius: 7px;
        border: 1px solid rgba(0,0,0,0.15);
        box-shadow: 0 1px 1px rgba(50,50,50,0.1);
        cursor: pointer;
        outline: none;
    
        /* Font settings */
        font-weight: bold;
        color: #8AA8BD;
    }
    
    

    Here we use some borders, a box-shadow and rounded corners. We need the little arrow:

    在这里,我们使用一些边框,一个盒子阴影和圆角。 我们需要小箭头:

    
    .wrapper-dropdown-3:after {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        right: 15px;
        top: 50%;
        margin-top: -3px;
        border-width: 6px 6px 0 6px;
        border-style: solid;
        border-color: #8aa8bd transparent;
    }
    
    

    This is the same as before, so let’s skip forward to the drop-down and its children.

    与之前相同,因此让我们跳至下拉列表及其子项。

    
    .wrapper-dropdown-3 .dropdown {
      /* Size & position */
        position: absolute;
        top: 140%;
        left: 0;
        right: 0;
    
        /* Styles */
        background: white;
        border-radius: inherit;
        border: 1px solid rgba(0,0,0,0.17);
        box-shadow: 0 0 5px rgba(0,0,0,0.1);
        font-weight: normal;
        transition: all 0.5s ease-in;
        list-style: none;
    
        /* Hiding */
        opacity: 0;
        pointer-events: none;
    }
    
    .wrapper-dropdown-3 .dropdown li a {
        display: block;
        padding: 10px;
        text-decoration: none;
        color: #8aa8bd;
        border-bottom: 1px solid #e6e8ea;
        box-shadow: inset 0 1px 0 rgba(255,255,255,1);
        transition: all 0.3s ease-out;
    }
    
    .wrapper-dropdown-3 .dropdown li i {
        float: right;
        color: inherit;
    }
    
    .wrapper-dropdown-3 .dropdown li:first-of-type a {
        border-radius: 7px 7px 0 0;
    }
    
    .wrapper-dropdown-3 .dropdown li:last-of-type a {
        border-radius: 0 0 7px 7px;
        border: none;
    }
    
    /* Hover state */
    
    .wrapper-dropdown-3 .dropdown li:hover a {
        background: #f3f8f8;
    }
    
    

    A few notes here:

    这里有一些注意事项:

    • We use a little box-shadow on the links in order to create a subtle light effect on their top.

      我们在链接上使用一个小盒子阴影,以在其顶部创建微妙的灯光效果。
    • To prevent this shadow to go out of the menu, we give the first link rounded corners.

      为了防止该阴影超出菜单,我们将第一个链接设置为圆角。
    • We remove the border of the last link to avoid a 1px weird border at the bottom of the dropdown.

      我们删除了最后一个链接的边框,以避免下拉菜单底部出现1px的怪异边框。
    • We don’t change the markup to place icons on the right: a simple float: right works like a charm.

      我们不会更改标记来在右侧放置图标:一个简单的float: right就像一个吊饰。

    Everything looks right except the little arrow on the top right of the drop-down. This arrow is important: without it, the dropdown looks like it’s floating with no connection to the button.

    除下拉菜单右上角的小箭头外,其他所有内容均显示正确。 此箭头很重要:没有箭头,下拉列表看起来就像是浮动的,与按钮没有任何连接。

    
    .wrapper-dropdown-3 .dropdown:after {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        bottom: 100%;
        right: 15px;
        border-width: 0 6px 6px 6px;
        border-style: solid;
        border-color: #fff transparent;    
    }
    
    .wrapper-dropdown-3 .dropdown:before {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        bottom: 100%;
        right: 13px;
        border-width: 0 8px 8px 8px;
        border-style: solid;
        border-color: rgba(0,0,0,0.1) transparent;    
    }
    
    

    Why are we using two pseudo-elements for this arrow? We want to create the border around it. Basically we create a white triangle sitting on top of a grey and slightly larger one. This way, it looks like there is only one little arrow with a border.

    为什么我们为此箭头使用两个伪元素? 我们要在其周围创建边框。 基本上,我们在灰色的稍大一点的顶部创建一个白色三角形。 这样,看起来只有一个带边框的小箭头。

    An now the expanded state. Always the same thing. However, note how we set the transition to the .dropdown a bit longer than usual (0.5s instead of 0.3s). That way, the opening of the menu is very smooth.

    现在是展开状态。 总是一样的东西。 但是,请注意我们如何将过渡到.dropdown的时间设置得比平时更长(0.5s而不是0.3s)。 这样,菜单的打开非常流畅。

    
    .wrapper-dropdown-3.active .dropdown {
        opacity: 1;
        pointer-events: auto;
    }
    
    

    JavaScript(The JavaScript)

    To finish this demo, we need to add a little bit of JavaScript to replace the default value of the button by the selected one. We saw how to do it in the first example, but since we don’t keep the “Transport” word here, the JS is very slightly different.

    要完成此演示,我们需要添加一些JavaScript以将按钮的默认值替换为所选按钮的默认值。 在第一个示例中,我们看到了如何执行此操作,但是由于这里没有保留“ Transport”一词,因此JS略有不同。

    
    function DropDown(el) {
        this.dd = el;
        this.placeholder = this.dd.children('span');
        this.opts = this.dd.find('ul.dropdown > li');
        this.val = '';
        this.index = -1;
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;
    
            obj.dd.on('click', function(event){
                $(this).toggleClass('active');
                return false;
            });
    
            obj.opts.on('click',function(){
                var opt = $(this);
                obj.val = opt.text();
                obj.index = opt.index();
                obj.placeholder.text(obj.val);
            });
        },
        getValue : function() {
            return this.val;
        },
        getIndex : function() {
            return this.index;
        }
    }
    
    

    例子4(Example 4)

    Looks different, doesn’t it? For this one, I thought it would be cool to create a little to-do-list instead of a select drop-down or a drop-down menu. Nothing spectacular, but different than previous demos for sure. 😉

    看起来不一样,不是吗? 对于这个,我认为创建一个小的待办事项列表而不是选择下拉菜单或下拉菜单会很酷。 没什么特别的,但是肯定与以前的演示不同。 😉

    标记 (The Markup)

    
    <div id="dd" class="wrapper-dropdown-4">To do
    	<ul class="dropdown">
    		<li><input type="checkbox" id="el-1" name="el-1" value="donut"><label for="el-1">Eat a donut</label></li>
    		<li><input type="checkbox" id="el-2" name="el-2" value="neighbour"><label for="el-2">Spy on my neighbours</label></li>
    		<li><input type="checkbox" id="el-3" name="el-3" value="T-rex"><label for="el-3">Feed my T-Rex</label></li>
    	</ul>
    </div>
    
    

    No more links. No more icons. For each element, we have two things: a checkbox linked to a label.

    没有更多链接。 没有更多的图标。 对于每个元素,我们有两件事:链接到标签的复选框。

    CSS (The CSS)

    
    .wrapper-dropdown-4 {
        /* Size and position */
        position: relative;
        width: 270px;
        margin: 0 auto;
        padding: 10px 10px 10px 30px;
    
        /* Styles */
        background: #fff;
        border: 1px solid silver;
        cursor: pointer;
        outline: none;
    }
    
    

    Nothing to say except that we use an important left padding to create enough space for the red lines. Now, the little arrow on the right:

    除了使用重要的左填充为红线创建足够的空间外,无话可说。 现在,右边的小箭头:

    
    .wrapper-dropdown-4:after {
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        right: 10px;
        top: 50%;
        margin-top: -3px;
        border-width: 6px 6px 0 6px;
        border-style: solid;
        border-color: #ffaa9f transparent;
    }
    
    

    The dropdown. I’m pretty sure you’re getting used to it. 🙂

    下拉菜单。 我敢肯定你已经习惯了。 🙂

    
    .wrapper-dropdown-4 .dropdown {
        /* Size & position */
        position: absolute;
        top: 100%;
        margin-top: 1px; /* border of wrapper */
        left: -1px;
        right: -1px;
    
        /* Styles */
        background: white;
        border: 1px solid silver;
        border-top: none;
        list-style: none;
        transition: all 0.3s ease-out;
      
        /* Hiding */
        opacity: 0;
        pointer-events: none;
    }
    
    

    We need to set the margin-top to 1px because we need to push it a bit down due to the border of the wrapper. The left is set to -1px to pull the drop-down into position and we’ll give it the same border like its parent, except that we take away the top one.

    我们需要将margin-top设置为1px,因为由于包装器的边框,我们需要将margin-top向下推一点。 左侧设置为-1px以将下拉列表拉到适当位置,我们将为其父边框赋予相同的边框,只是我们将顶部边框取走。

    
    .wrapper-dropdown-4 .dropdown li {
        position: relative; /* Enable absolute positioning for checkboxes */
    }
    
    .wrapper-dropdown-4 .dropdown li label {
        display: block;
        padding: 10px 10px 10px 30px; /* Same padding as the button */
        border-bottom: 1px dotted #1ccfcf;
        transition: all 0.3s ease-out;
    }
    
    .wrapper-dropdown-4 .dropdown li:last-of-type label {
        border: none;
    }
    
    .wrapper-dropdown-4 .dropdown li input /* Checkboxes */ {
        position: absolute;
        display: block;
        right: 10px;
        top: 50%;
        margin-top: -8px;
    }
    
    /* Hover state */
    
    .wrapper-dropdown-4 .dropdown li:hover label {
        background: #f0f0f0;
    }
    
    /* Checked state */
    
    .wrapper-dropdown-4 .dropdown li input:checked ~ label {
        color: grey;
        text-decoration: line-through;
    }
    
    

    Checkboxes are absolutely placed on the middle right of each line but since they are linked to labels, you can click wherever you want on the line to toggle them. When a checkbox is checked, the following respective label becomes grey and crossed-out. Simple but effective.

    复选框绝对位于每行的右中间,但是由于它们链接到标签,因此您可以在该行上的任意位置单击以切换它们。 选中复选框后,以下各个标签将变为灰色并划掉。 简单但有效。

    And now, we have to deal with the two thin red lines on the left of our little notebook. There are two ways to do this: one with pseudo-elements and one with gradients. Let’s look at both of them.

    现在,我们必须处理小笔记本左侧的两条细红线。 有两种方法可以做到这一点:一种是使用伪元素,另一种是使用渐变。 让我们看看它们两者。

    
    /* Red lines: the pseudo-elements way */
    .wrapper-dropdown-4 .dropdown:before,
    .wrapper-dropdown-4:before {
        content: "";
        width: 4px;
        height: 100%;
        position: absolute;
        top: 0;
        left: 15px;
        border: 1px solid #ffaa9f;
        border-top: none;
        border-bottom: none;
        z-index: 2;
    }
    
    /* OR: */
    /* Red lines: the gradients way */
    
    .wrapper-dropdown-4 .dropdown,
    .wrapper-dropdown-4 {
      background: linear-gradient(left, white 5%, #ffaa9f 5%, #ffaa9f 5.3%, white 5.3%, white 6.5%, #ffaa9f 6.5%, #ffaa9f 6.8%, white 6.8%);
    }
    
    .wrapper-dropdown-4 .dropdown li:hover label {
      background: linear-gradient(left, #f0F0F0 5%, #ffaa9f 5%, #ffaa9f 5.3%, #f0F0F0 5.3%, #f0F0F0 6.5%, #ffaa9f 6.5%, #ffaa9f 6.8%, #f0F0F0 6.8%);
    }
    
    
    

    The first method creates a pseudo-element (two actually: one for the button and one for the dropdown) with left and right borders sitting on top of everything else. The second method fakes the red lines with a gradient on both, the wrapper and the dropdown. So which one is better? Probably the first one, because if you want to change the hover effect on the list elements, you have to change the gradient which is pretty awful. Plus, pseudo-elements have a way better browser support (back to IE8) than gradients (not supported until IE10).

    第一种方法创建一个伪元素(实际上是两个:一个用于按钮,一个用于下拉菜单),其左右边界位于其他所有元素的顶部。 第二种方法在包装器和下拉菜单上都使用渐变来伪造红线。 那么哪个更好呢? 可能是第一个,因为如果要更改列表元素的悬停效果,则必须更改非常糟糕的渐变。 另外,伪元素比梯度(IE10之前不支持)具有更好的浏览器支持(回到IE8)。

    Let’s end it with the expanded state. Nothing new here.

    让我们以扩展状态结束。 这里没有新内容。

    
    /* Active state */
    
    .wrapper-dropdown-4.active:after {
        border-width: 0 6px 6px 6px;
    }
    
    .wrapper-dropdown-4.active .dropdown {
        opacity: 1;
        pointer-events: auto;
    }
    
    

    JavaScript(The JavaScript)

    
    function DropDown(el) {
        this.dd = el;
        this.opts = this.dd.find('ul.dropdown > li');
        this.val = [];
        this.index = [];
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;
    
            obj.dd.on('click', function(event){
                $(this).toggleClass('active');
                event.stopPropagation();
            });
    
            obj.opts.children('label').on('click',function(event){
                var opt = $(this).parent(),
                    chbox = opt.children('input'),
                    val = chbox.val(),
                    idx = opt.index();
    
                ($.inArray(val, obj.val) !== -1) ? obj.val.splice( $.inArray(val, obj.val), 1 ) : obj.val.push( val );
                ($.inArray(idx, obj.index) !== -1) ? obj.index.splice( $.inArray(idx, obj.index), 1 ) : obj.index.push( idx );
            });
        },
        getValue : function() {
            return this.val;
        },
        getIndex : function() {
            return this.index;
        }
    }
    
    

    例子5(Example 5)

    Our last example is a little drop-down menu for some admin panel. For this one, we will use a different animation when we toggle it. Instead of appearing/disappearing, it will slide up and down.

    我们的最后一个示例是一些管理面板的下拉菜单。 为此,切换时将使用不同的动画。 它不会出现/消失,而是会上下滑动。

    标记 (The markup)

    
    <div id="dd" class="wrapper-dropdown-5" tabindex="1">John Doe
    	<ul class="dropdown">
    		<li><a href="#"><i class="icon-user"></i>Profile</a></li>
    		<li><a href="#"><i class="icon-cog"></i>Settings</a></li>
    		<li><a href="#"><i class="icon-remove"></i>Log out</a></li>
    	</ul>
    </div>
    
    

    CSS(The CSS)

    
    .wrapper-dropdown-5 {
        /* Size & position */
        position: relative;
        width: 200px;
        margin: 0 auto;
        padding: 12px 15px;
    
        /* Styles */
        background: #fff;
        border-radius: 5px;
        box-shadow: 0 1px 0 rgba(0,0,0,0.2);
        cursor: pointer;
        outline: none;
        transition: all 0.3s ease-out;
    }
    
    .wrapper-dropdown-5:after { /* Little arrow */
        content: "";
        width: 0;
        height: 0;
        position: absolute;
        top: 50%;
        right: 15px;
        margin-top: -3px;
        border-width: 6px 6px 0 6px;
        border-style: solid;
        border-color: #4cbeff transparent;
    }
    
    

    Basic stuff there. Let’s go to the dropdown, which is a little bit different than usual.

    那里的基本东西。 让我们转到下拉菜单,该下拉菜单与平时有点不同。

    
    .wrapper-dropdown-5 .dropdown {
        /* Size & position */
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
    
        /* Styles */
        background: #fff;
        border-radius: 0 0 5px 5px;
        border: 1px solid rgba(0,0,0,0.2);
        border-top: none;
        border-bottom: none;
        list-style: none;
        transition: all 0.3s ease-out;
    
        /* Hiding */
        max-height: 0;
        overflow: hidden;
    }
    
    

    This time, we don’t turn the opacity to 0 to hide the menu. We set its max-height to 0 and its overflow to hidden. Why its max-height and not its height? Because we don’t know the exact height of the expanded drop-down. So no need of pointer-events this time since the menu is really not there.

    这次,我们不将不透明度设置为0以隐藏菜单。 我们将其最大高度设置为0,并将其溢出设置为隐藏。 为什么是最大高度而不是高度? 因为我们不知道扩展下拉列表的确切高度。 因此,由于菜单实际上不存在,因此这次不需要指针事件。

    Quick and simple styles for the list elements.

    列表元素的快速和简单样式。

    
    .wrapper-dropdown-5 .dropdown li {
        padding: 0 10px ;
    }
    
    .wrapper-dropdown-5 .dropdown li a {
        display: block;
        text-decoration: none;
        color: #333;
        padding: 10px 0;
        transition: all 0.3s ease-out;
        border-bottom: 1px solid #e6e8ea;
    }
    
    .wrapper-dropdown-5 .dropdown li:last-of-type a {
        border: none;
    }
    
    .wrapper-dropdown-5 .dropdown li i {
        margin-right: 5px;
        color: inherit;
        vertical-align: middle;
    }
    
    /* Hover state */
    
    .wrapper-dropdown-5 .dropdown li:hover a {
        color: #57a9d9;
    }
    
    

    And now, the active state:

    现在,处于活动状态:

    
    /* Active state */
    
    .wrapper-dropdown-5.active {
        border-radius: 5px 5px 0 0;
        background: #4cbeff;
        box-shadow: none;
        border-bottom: none;
        color: white;
    }
    
    .wrapper-dropdown-5.active:after {
        border-color: #82d1ff transparent;
    }
    
    .wrapper-dropdown-5.active .dropdown {
        border-bottom: 1px solid rgba(0,0,0,0.2);
        max-height: 400px;
    }
    
    

    When the dropdown is open, we change the bottom corners of the button, its color, its arrow direction and arrow color and remove both, its box-shadow and its border. And to show the menu, we set the max-height of the dropdown to 400px. We could have set it to 500px, 1000px ou 1000000px; it doesn’t matter as long as it’s taller than its height.

    打开下拉菜单后,我们将更改按钮的底角,其颜色,箭头方向和箭头颜色,并同时删除其框阴影和边框。 为了显示菜单,我们将下拉菜单的最大高度设置为400px。 我们可以将其设置为500px,1000px或1000000px; 只要它比它的高度高就没有关系。

    JavaScript (The JavaScript)

    
    function DropDown(el) {
        this.dd = el;
        this.initEvents();
    }
    DropDown.prototype = {
        initEvents : function() {
            var obj = this;
    
            obj.dd.on('click', function(event){
                $(this).toggleClass('active');
                event.stopPropagation();
            }); 
        }
    }
    
    

    后备(Fallbacks)

    Okay guys, we now have 5 awesome drop-downs working like a charm, but what about legacy browsers? These browsers don’t understand the opacity property. And if some of these do with filters, they don’t understand pointer-events. It sucks and this is why you might want to put a fallback in place.

    好的,我们现在有5个很棒的下拉菜单,就像一个超级按钮,但是旧版浏览器呢? 这些浏览器不了解opacity属性。 而且,如果其中一些使用过滤器,它们将无法理解指针事件。 这很糟糕,这就是为什么您可能想要放置一个备用的原因。

    This is where our friend Modernizr is coming into play. Roughly, for those who don’t know what Modernizr is, it’s a JavaScript library that detects HTML5 and CSS3 features in the user’s browser. Thanks to this awesome script, we can basically tell the browser “if you don’t support *this* property, then do *that*”. With Modernizr we can have classes added to the html, for example, “no-pointerevents” if there is no support for pointer-events (make sure to select that in the non-core detects when you build your Modernizr). The following is an example of how we can manage the fallback for browsers that don’t support certain CSS properties:

    这是我们的朋友Modernizr发挥作用的地方。 粗略地说,对于那些不知道Modernizr是什么的人来说,它是一个JavaScript库,可以检测用户浏览器中HTML5和CSS3功能。 由于有了这个出色的脚本,我们基本上可以告诉浏览器“如果您不支持* this *属性,那么请执行* that *” 。 使用Modernizr,我们可以将类添加到html中,例如,如果不支持指针事件(请确保在构建您的Modernizr时在非核心中选择该选项),则可以使用“ no-pointerevents”。 以下是一个示例,说明如何为不支持某些CSS属性的浏览器管理后备广告:

    
    /* No CSS3 support */
    
    .no-opacity       .wrapper-dropdown-1 .dropdown,
    .no-pointerevents .wrapper-dropdown-1 .dropdown {
        display: none;
        opacity: 1; /* If opacity support but no pointer-events support */
        pointer-events: auto; /* If pointer-events support but no pointer-events support */
    }
    
    .no-opacity       .wrapper-dropdown-1.active .dropdown,
    .no-pointerevents .wrapper-dropdown-1.active .dropdown {
        display: block;
    }
    
    

    If the browser doesn’t support either opacity or pointer-events, then we hide the drop-down with a simple display: none;. If the browser doesn’t support opacity but does support pointer-events, we set those to auto to allow the user to click on the menu once expanded. In the other hand, if the browser doesn’t support pointer-events but does support opacity, we set it to 1 to make the dropdown appear once the .active class is toggled.

    如果浏览器不支持不透明度或指针事件,那么我们用简单的display: none;隐藏下拉菜单display: none; 。 如果浏览器不支持不透明度,但支持指针事件,则将其设置为auto以允许用户在展开菜单后单击菜单。 另一方面,如果浏览器不支持指针事件但支持不透明度,则将其设置为1,以在切换.active类后使下拉菜单出现。

    When the .active class is toggled, we show the drop-down with display: block;. Easy peasy!

    切换.active类时,我们使用display: block;下拉列表display: block; 。 十分简单!

    Note: of course this doesn’t apply for the demo with the max-height animation. Only for the others with opacity and pointer-events.

    注意:当然,这不适用于具有max-height动画的演示。 仅适用于具有不透明度和指针事件的其他对象。

    最后的话 (Final words)

    I hope this tutorial helped you understand how to make your custom drop-downs. As you can see, it is fairly straight forward and pretty simple both, the CSS and the JavaScript. Please, don’t forget to use fallbacks or tell your users to enable JavaScript. Thank you for reading this tutorial. And of course if you have any question or related work to show, please do! 🙂

    我希望本教程可以帮助您了解如何制作自定义下拉菜单。 如您所见,CSS和JavaScript都非常简单明了。 请不要忘记使用后备功能或告诉您的用户启用JavaScript。 感谢您阅读本教程。 当然,如果您有任何疑问或需要展示的相关工作,请这样做! 🙂

    翻译自: https://tympanus.net/codrops/2012/10/04/custom-drop-down-list-styling/

    安卓自定义下拉列表样式

    展开全文
  • 主要介绍了jquery自定义下拉列表示例,需要的朋友可以参考下
  • 主要介绍了使用jQuery实现自定义下拉列表的方法及代码分享,效果非常不错,兼容性也很棒,这里推荐给小伙伴们。
  • 主要介绍了Vue.js实现在下拉列表区域外点击即可关闭下拉列表的功能(自定义下拉列表) ,需要的朋友可以参考下
  • 这篇文章主要介绍了wxpython自定义下拉列表框过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 自定义wxpython下拉列表框,支持修改边框颜色,按钮图标...
  • Android 自定义下拉列表 源码。简易的封装,代码易懂
  • WPF 自定义下拉列表

    2019-04-02 11:46:00
    WPF 自定义下拉列表 原文:WPF 自定义下拉列表XAML代码: <Popup x:Name="popupStrategy" StaysOpen="False" PopupAnimation="Scroll" Width="190" MaxHeight="300" AllowsTransparency="True...
    原文:WPF 自定义下拉列表

    XAML代码:

    <Popup x:Name="popupStrategy" StaysOpen="False" PopupAnimation="Scroll" Width="190" MaxHeight="300" AllowsTransparency="True">
        <Border Background="#0c5ab0" BorderThickness="1" BorderBrush="#1992d6">
            <ItemsControl x:Name="itemsCtrlStrategy" Grid.Row="1" Margin="0 5 0 0">
                <ItemsControl.Template>
                    <ControlTemplate>
                        <ScrollViewer HorizontalScrollBarVisibility="Auto" MinHeight="{Binding ElementName=itemsCtrlStrategy,Path=ActualHeight}" MinWidth="{Binding ElementName=itemsCtrlStrategy, Path=ActualWidth}">
                            <ItemsPresenter></ItemsPresenter>
                        </ScrollViewer>
                    </ControlTemplate>
                </ItemsControl.Template>
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <StackPanel/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Orientation="Horizontal" Margin="5 0 5 5" Background="#00234E">
                            <Button x:Name="btnStrategySel" Click="btnStrategySel_Click_1" CommandParameter="{Binding}" Width="120" Margin="5" VerticalAlignment="Center" HorizontalAlignment="Center">
                                <Button.Template>
                                    <ControlTemplate>
                                        <TextBlock Text="{Binding Info.STRATEGYNAME}" ToolTip="{Binding Info.STRATEGYNAME}" Width="120" Foreground="#1ba4f6" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
                                    </ControlTemplate>
                                </Button.Template>
                            </Button>
                            <Button x:Name="btnStrategyDel" Margin="5" CommandParameter="{Binding}" Click="btnStrategyDel_Click_1" Height="12" Width="12" VerticalAlignment="Center" HorizontalAlignment="Center">
                                <Button.Template>
                                    <ControlTemplate>
                                        <Image Name="img" Width="12" Height="12" VerticalAlignment="Center" Source="/SunCreate.CombatPlatform.Client.Resources;component/Image/CaseExportStrategy/删除.png"></Image>
                                    </ControlTemplate>
                                </Button.Template>
                            </Button>
                            <Button x:Name="btnStrategyEdit" Margin="5" CommandParameter="{Binding}" Click="btnStrategyEdit_Click_1" Height="12" Width="12" VerticalAlignment="Center" HorizontalAlignment="Center">
                                <Button.Template>
                                    <ControlTemplate>
                                        <Image Name="img" Width="12" Height="12" VerticalAlignment="Center" Source="/SunCreate.CombatPlatform.Client.Resources;component/Image/CaseExportStrategy/编辑.png"></Image>
                                    </ControlTemplate>
                                </Button.Template>
                            </Button>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.ItemTemplate>
            </ItemsControl>
        </Border>
    </Popup>
    View Code

    后台代码:

    itemsCtrlStrategy.ItemsSource = strategyViewModelList;
    
    popupStrategy.PlacementTarget = sender as Button;
    popupStrategy.Placement = PlacementMode.Bottom;
    popupStrategy.IsOpen = true;
    View Code

    效果图:

     

    posted on 2019-04-02 11:46 NET未来之路 阅读(...) 评论(...) 编辑 收藏

    转载于:https://www.cnblogs.com/lonelyxmas/p/10641700.html

    展开全文
  • IOS自定义下拉列表

    2013-05-07 09:47:41
    自定义下拉列表,很全面,有注释,可以选择滚动的行数
  • angular自定义下拉列表以及tab切换的实现
  • 对于下拉列表大家都不会陌生,经常使用。虽然Android自带有spinner控件,但是其使用的效果其实并不理想。现在给大家推荐一款我封装的万能适配自定义下拉列表PopSpinner,[源码]请自行下载查看

    Android 敏捷开发助手

    1. 强大无匹的自定义下拉列表
    2. Lottie动画 轻松使用
    3. PNG、JPG等普通图片高保真转SVG图

    博客创建时间:2021.05.05
    博客更新时间:2021.05.07

    以Android studio build=4.2.0,gradle=6.7.1,SdkVersion 30来分析讲解。如图文和网上其他资料不一致,可能是别的资料版本较低而已


    前言

    对于下拉列表大家都不会陌生,经常使用。虽然Android自带有spinner控件,但是其使用的效果其实并不理想。如果我们的下拉列表类有数据类型int、String、classA、classB。则我们使用过程中可能需要多个Spinner搭配多个适配器来实现,这样就比较麻烦且重复造轮子,现在给大家推荐一款我封装的万能适配自定义下拉列表PopSpinner,源码请自行下载查看
    在这里插入图片描述

            val adapter = StringAdapter(this)
            adapter.setDatas(data)
         
            val adapter = StudentAdapter(this)
            adapter.setDatas(data)
            
            val adapter = PersonAdapter(this)
            adapter.setDatas(data)
    

    PopSpinner 核心

    PopListAdapter
    下拉内容显示适配器,通过泛型的方式可以适配多种类型实体类,通过PopSpinnerItemClickListener接口的实现可以由使用者决定Item的内容显示某个类的某字段。

    如果实际开发中,我们需要的适配器Item只用显示一字段信息,该适配器也是完美的万能百搭。

    public class PopListAdapter<T> extends RecyclerView.Adapter<PopListAdapter.ViewHolder> {
        private List<T> list;
    
        private PopSpinnerItemClickListener<T> listener;
        
        ......
        @Override
        public void onBindViewHolder(@NonNull final ViewHolder holder, @SuppressLint("RecyclerView") final int position) {
            T t = list.get(position);
            if (listener != null) {
                holder.getBinding().textView.setText(listener.setContent(t));
            } else {
                holder.getBinding().textView.setText("");
            }
    
            holder.getBinding().getRoot().setOnClickListener(v -> {
                if (listener != null) {
                    listener.onItemSelected(position, t, listener.setContent(t));
                }
            });
            //立即执行绑定
            holder.getBinding().executePendingBindings();
        }
        
       ......
    }
    

    PopWindow
    自定义的PopupWindow,下拉的List将在此PopWindow中显示

    class PopWindow<T>(private val mContext: Context) : PopupWindow(mContext) {
        private lateinit var mListView: RecyclerView
        private var mAdapter: PopListAdapter<T>? = null
        fun setAdatper(adapter: PopListAdapter<T>) {
            mAdapter = adapter
            mListView.adapter = mAdapter
        }
    
        init {
            init()
        }
    
        private fun init() {
            val view = LayoutInflater.from(mContext).inflate(R.layout.layout_spinner_window, null)
            contentView = view
            width = ViewGroup.LayoutParams.WRAP_CONTENT
            height = ViewGroup.LayoutParams.WRAP_CONTENT
    
            mListView = view.findViewById<View>(R.id.listView) as RecyclerView
            // 初始化 RecyclerView
            val layoutManager = LinearLayoutManager(mContext)
            mListView.layoutManager = layoutManager
        }
    }
    

    PopSpinner
    PopSpinner有一个内容显示的TextView和一个下拉指示ImageView两子控件。该部分主要控制数据的刷新和下拉列表的显示和退出。

    class PopSpinner<T> : LinearLayout {
        /**
         * 下拉监听接口
         */
        var listener: PopSpinnerItemClickListener<T>? = null
    
        /**
         * 弹出view
         */
        private lateinit var view: View
    
        constructor(context: Context) : super(context) {
            mcontext = context
            init()
        }
    
        constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
            mcontext = context
            init()
        }
    
        private fun init() {
            val mInflater = LayoutInflater.from(mcontext)
            view = mInflater.inflate(R.layout.layout_pop_spinner, null)
            addView(view)
            tvValue = view.findViewById<View>(R.id.tv_value) as TextView
            btDropdown = view.findViewById<View>(R.id.btnDropdown) as ImageView
            tvValue.setOnClickListener(spinnerOnClickListener)
            btDropdown.setOnClickListener(spinnerOnClickListener)
    
    
            mSpinerPopWindow = PopWindow(mcontext)
            mAdapter = PopListAdapter<T>()
            mAdapter.setListener(object : PopSpinnerItemClickListener<T> {
                override fun onItemSelected(position: Int, t: T, value: String) {
                    tvValue.text = value
                    listener?.onItemSelected(position, t, value)
                }
    
                override fun setContent(t: T): String {
                    val value = listener?.setContent(t)
                    return value ?: ""
                }
            })
        }
    
        /**
         * 设置控件是否可用
         *
         * @param enable true:可用
         */
        fun setEnable(enable: Boolean) {
            tvValue.isEnabled = enable
            btDropdown.isEnabled = enable
        }
    
        /**
         * 自定义的 MySpinner 被点击
         */
        private val spinnerOnClickListener = OnClickListener {
            isShowing = if (isShowing) {
                dismiss()
                false
            } else {
                showSpinWindow()
                true
            }
        }
    
        private fun showSpinWindow() {
            mAdapter.setDatas(mItems)
            mSpinerPopWindow.setAdatper(mAdapter)
    
            this.mSpinerPopWindow.width = view.width
            if (mItems == null || mItems?.size == 0) {
                this.mSpinerPopWindow.height = 0
            }
            this.mSpinerPopWindow.showAsDropDown(view)
        }
    
        fun dismiss() {
            this.mSpinerPopWindow.dismiss()
        }
    }
    

    PopSpinner 使用

    Activity中使用

    public class MainActivity extends AppCompatActivity {
        PopSpinner<String> sp1;
        PopSpinner<Student> sp2;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            sp1 = findViewById(R.id.pop1);
            sp2 = findViewById(R.id.pop2);
    
            initData1();
            initData2();
        }
    
        void initData1() {
            String[] names = new String[]{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17"};
            sp1.setData(Arrays.asList(names));
            sp1.setListener(new PopSpinnerItemClickListener<String>() {
                @Override
                public void onItemSelected(int position, @NonNull String s, @NonNull String value) {
                    Toast.makeText(MainActivity.this, "你点击的是:" + value, Toast.LENGTH_SHORT).show();
                    sp1.dismiss();
                }
    
                @NonNull
                @Override
                public String setContent(@NonNull String s) {
                    return s;
                }
            });
            sp1.setText("8");
        }
    
        void initData2() {
    
            ArrayList<Student> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                Student student = new Student();
                student.setAge(10 + i);
                student.setName("学生 " + i);
                list.add(student);
            }
    
            sp2.setData(list);
            sp2.setListener(new PopSpinnerItemClickListener<Student>() {
                @Override
                public void onItemSelected(int position, @NonNull Student s, @NonNull String value) {
                    Toast.makeText(MainActivity.this, "你点击的是:" + value, Toast.LENGTH_SHORT).show();
                    sp2.dismiss();
                }
    
                @NonNull
                @Override
                public String setContent(@NonNull Student s) {
                    return s.getName();
                }
            });
            sp2.setText("学生 7");
        }
    }
    

    PopSpinner一定要实现PopSpinnerItemClickListener接口,其中onItemSelected()是列表Item处理逻辑。setContent()方法非常重要,该方法的返回值决定着下拉列表中的内容显示class的哪个字段内容。

    布局配置

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        ...
        tools:context="com.xuanyuan.MainActivity">
    
        <com.xuanyuan.popspinner.PopSpinner
            android:id="@+id/pop1"
            android:layout_margin="3dp"
            android:layout_width="match_parent"
            android:layout_height="40dp" />
    
        <com.xuanyuan.popspinner.PopSpinner
            android:id="@+id/pop2"
            android:layout_margin="3dp"
            android:layout_width="match_parent"
            android:layout_height="40dp" />
    </LinearLayout>
    

    PopSpinner控件的使用灰常简单,可以匹配多种类型的数据


    总结

    PopSpinner经过封装和修改后,对于单字段显示的下拉列表 是万能匹配的,无论提供的数据是何种类型。希望这样的小工具类控件能帮助大家少造轮子多干事。

    gitee源码
    gitee源码


    相关链接

    1. 强大无匹的自定义下拉列表
    2. Lottie动画 轻松使用
    3. PNG、JPG等普通图片高保真转SVG图

    扩展链接:

    1. Android CameraX 使用入门
    2. Android 今日头条屏幕适配详细使用攻略

    扩展训练:

    1. 怎么使用PopSpinner
    2. 为何能适配多种类型类,完成万能适配

    博客书写不易,您的点赞收藏是我前进的动力,千万别忘记点赞、 收藏 ^ _ ^ !

    展开全文
  • 为IOS创建自定义下拉列表 屏幕截图 执行 将SKDropDownList.h和SKDropDownList.m添加到您的项目 然后分析ViewController.h和ViewController.m类 初始化下拉项 @interface ViewController : UIViewController @...
  • Android 自定义下拉列表

    千次阅读 2015-09-18 15:30:12
    Android 自定义下拉列表。效果图如下。 首先,创建一个标题及箭头布局,点击后弹出下拉菜单。,代码如下所示: android:id="@+id/spiner" android:layout_width="match_par

    Android 下拉列表也是一个比较常用的控件,但是Android自带的下拉框样式效果较差,没办法,只好自己来自定义一个。其实主要是利用弹窗来实现的,看一下效果图先~~


    我这边仅仅是实现简单的自定义控件,简单易懂,布局上有需要其他效果如边框、虚线等可自行加上。下拉列表是List,所以item也是可以根据需要进行内容上的丰富,修改适配器便可以。

    好了,进入正题。首先,我们先创建一个标题及箭头布局,目的是用于点击后弹出下拉菜单。,代码如下所示:

    接下来,创建下拉列表ListView布局,代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    
    创建ListView,自然也要对应创建其Item的布局,代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    
    接下来,我们来封装一个自定义控件MySpinerView,由于我没有去找向上箭头的图片资源,大家箭头自行替换。代码如下:
    package com.newland.myspinerdemo;
    
    import android.content.Context;
    import android.graphics.Color;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.WindowManager;
    import android.widget.ImageView;
    import android.widget.LinearLayout;
    import android.widget.RelativeLayout;
    import android.widget.TextView;
    
    import java.util.List;
    
    /**
     * 封装好的下拉列表,包括头部
     */
    public class MySpinerView extends LinearLayout implements View.OnClickListener, MySpinerAdapter.IOnItemSelectListener {
        private String mExampleString = "";
        private int mExampleColor = Color.RED;
        private float mExampleDimension = 0;
    
        private Context context;
        private RelativeLayout spiner;
        private TextView tvSpiner;
        private ImageView ivSpiner;
        private List nameList;
    
        private MySpinerPopWindow mSpinerPopWindow;
    
        public MySpinerView(Context context, AttributeSet attrs) {
            super(context, attrs);
            this.context = context;
            LayoutInflater.from(context).inflate(R.layout.sample_my_spiner_view, this);
            init(attrs, 0);
            spiner = (RelativeLayout) this.findViewById(R.id.spiner);
            spiner.setOnClickListener(this);
            tvSpiner = (TextView) this.findViewById(R.id.tv_spiner);
            ivSpiner = (ImageView) this.findViewById(R.id.iv_spiner);
        }
    
        /**
         * 设置弹出下拉表单的数据,在Activity那边得到控件后记得调用否则抛异常
         * @param nameList
         */
        public void setData(List nameList) {
            this.nameList = nameList;
            mSpinerPopWindow = new MySpinerPopWindow(context);
            mSpinerPopWindow.refreshData(nameList, 0);
            mSpinerPopWindow.setItemListener(this); // 设置下拉列表item点击的监听,响应onItemClick回调函数
        }
    
        /**
         * 头部点击事件
         * @param v
         */
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.spiner:
                    showSpinWindow();
                    break;
            }
        }
    
        /**
         * 弹出下拉列表
         */
        public void showSpinWindow() {
            /**这里还有一步要做,就是让右边箭头向上。自己替换掉ivSpiner图片**/
            mSpinerPopWindow.setWidth(((WindowManager) context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth());
            mSpinerPopWindow.showAsDropDown(tvSpiner);
        }
    
        /**
         * 下拉列表项点击事件,把选中的值显示在界面上
         * @param pos
         */
        @Override
        public void onItemClick(int pos) {
            /**这里还有一步要做,就是让右边箭头还原向下。自己替换掉ivSpiner图片**/
            if (pos >= 0 && pos <= nameList.size()) { // pos为-1就是弹窗消失,不管他
                String value = nameList.get(pos);
                tvSpiner.setText(value);
            }
        }
    
        /**
         * 初始化顶部显示数据
         * @param txt
         */
        public void initText(String txt){
            tvSpiner.setText(txt);
        }
    }
    
    自定义控件创建完毕,点击后弹出的下拉列表。

    下拉列表实际上是一个PopWindow,里面有一个ListView,所以我们新建一个自定义弹窗PopWindow。代码如下:
    package com.newland.myspinerdemo;
    
    import java.util.List;
    
    import android.content.Context;
    import android.graphics.drawable.ColorDrawable;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup.LayoutParams;
    import android.widget.AdapterView;
    import android.widget.AdapterView.OnItemClickListener;
    import android.widget.ListView;
    import android.widget.PopupWindow;
    
    /**
     * 下拉列表弹窗
     */
    public class MySpinerPopWindow extends PopupWindow implements OnItemClickListener {
    
        private Context mContext;
        private ListView mListView;
        private MySpinerAdapter mAdapter;
        private MySpinerAdapter.IOnItemSelectListener mItemSelectListener;
    
    
        public MySpinerPopWindow(Context context) {
            super(context);
            mContext = context;
            init();
        }
    
        /**
         * 为MySpinnerView提供一个item点击事件的监听器,MySpinnerView实例调用此方法设置监听
         * @param listener
         */
        public void setItemListener(MySpinerAdapter.IOnItemSelectListener listener) {
            mItemSelectListener = listener;
        }
    
        /**
         * 初始化弹窗布局
         */
        private void init() {
            View view = LayoutInflater.from(mContext).inflate(R.layout.spiner_window_layout, null);
            setContentView(view);
            setWidth(LayoutParams.WRAP_CONTENT);
            setHeight(LayoutParams.WRAP_CONTENT);
    
            setFocusable(true);
            ColorDrawable dw = new ColorDrawable(0x00);
            setBackgroundDrawable(dw);
    
            mListView = (ListView) view.findViewById(R.id.listview);
    
            mAdapter = new MySpinerAdapter(mContext);
            mListView.setAdapter(mAdapter);
            mListView.setOnItemClickListener(this);
            this.setOnDismissListener(new OnDismissListener() { // 弹窗消失的监听
                @Override
                public void onDismiss() {
                    if (mItemSelectListener != null) {
                        mItemSelectListener.onItemClick(-1); // 弹窗消失,要让布局那边的箭头还原向下,所以那边还得判断一下,>=0的数据在显示,-1就忽略掉,箭头还原
                    }
                }
            });
        }
    
        /**
         * 刷新下拉列表的数据
         * @param list
         * @param selIndex
         */
        public void refreshData(List list, int selIndex) {
            if (list != null && selIndex != -1) {
                mAdapter.refreshData(list, selIndex);
            }
        }
    
        /**
         * 下拉列表ListView的点击事件。
         * @param arg0
         * @param view
         * @param pos
         * @param arg3
         */
        @Override
        public void onItemClick(AdapterView<?> arg0, View view, int pos, long arg3) {
            dismiss();
            if (mItemSelectListener != null) {
                mItemSelectListener.onItemClick(pos); //点击后调用此方法,则MySpinerView会监听到(因为mItemSelectListener是MySpinerView那边设置的监听器)
            }
        }
    }
    
    既然是ListView,那么马上想到的就是适配器,那么我们接下来设置弹窗里面的ListView适配器,代码如下:
    package com.newland.myspinerdemo;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.content.Context;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.BaseAdapter;
    import android.widget.TextView;
    
    public class MySpinerAdapter extends BaseAdapter {
    
        private Context mContext;
        private List mObjects = new ArrayList();
    
        private LayoutInflater mInflater;
    
        public MySpinerAdapter(Context context) {
            mContext = context;
            mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        }
    
        /**
         * 刷新数据
         * @param objects
         * @param selIndex
         */
        public void refreshData(List objects, int selIndex) {
            mObjects = objects;
            if (selIndex < 0) {
                selIndex = 0;
            }
            if (selIndex >= mObjects.size()) {
                selIndex = mObjects.size() - 1;
            }
        }
    
    
        @Override
        public int getCount() {
            return mObjects.size();
        }
    
        @Override
        public Object getItem(int pos) {
            return mObjects.get(pos).toString();
        }
    
        @Override
        public long getItemId(int pos) {
            return pos;
        }
    
        @Override
        public View getView(int pos, View convertView, ViewGroup arg2) {
            ViewHolder viewHolder;
            if (convertView == null) {
                convertView = mInflater.inflate(R.layout.spiner_item_layout, null);
                viewHolder = new ViewHolder();
                viewHolder.mTextView = (TextView) convertView.findViewById(R.id.textView);
                convertView.setTag(viewHolder);
            } else {
                viewHolder = (ViewHolder) convertView.getTag();
            }
            String item = (String) getItem(pos);
            viewHolder.mTextView.setText(item);
            return convertView;
        }
    
        public static class ViewHolder {
            public TextView mTextView;
        }
    
        /**
         * 提供一个设置点击事件监听的接口回调
         */
        public interface IOnItemSelectListener {
            void onItemClick(int pos);
        }
    
    }
    
    好了,功能性的东西都完成了,来看看主页面布局

    主页面布局由4个自定义控件(MySpinerView)组成,代码如下:
    <?xml version="1.0" encoding="utf-8"?>
    
    最后一步,编写Activity,代码如下
    package com.newland.myspinerdemo;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.app.Activity;
    import android.os.Bundle;
    
    public class MainActivity extends Activity{
    
        /**
         * 四个下拉列表头部数据
         */
        private String name1 = "课程类型";
        private String name2 = "教练";
        private String name3 = "卡路里";
        private String name4 = "时间";
        /**
         * 四个下拉列表数据
         */
        private List nameList1 = new ArrayList();
        private List nameList2 = new ArrayList();
        private List nameList3 = new ArrayList();
        private List nameList4 = new ArrayList();
    
        /**
         * 四个自定义下拉列表
         */
        private MySpinerView mySpinerView1;
        private MySpinerView mySpinerView2;
        private MySpinerView mySpinerView3;
        private MySpinerView mySpinerView4;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            setupViews();
        }
    
        /**
         * 初始化四个下拉列表
         */
        private void setupViews() {
    
            mySpinerView1 = (MySpinerView)findViewById(R.id.mysv1);
            mySpinerView1.initText(name1);
            String[] names1 = { "高级课程", "中级课程", "所有课程" };
            for (int i = 0; i < names1.length; i++) {
                nameList1.add(names1[i]);
            }
            mySpinerView1.setData(nameList1);
    
    
            mySpinerView2 = (MySpinerView)findViewById(R.id.mysv2);
            mySpinerView2.initText(name2);
            String[] names2 = {"小鱼","布拉特", "杰克逊", "菲尔顿", "希伯特"};
            for (int i = 0; i < names2.length; i++) {
                nameList2.add(names2[i]);
            }
            mySpinerView2.setData(nameList2);
    
            mySpinerView3 = (MySpinerView)findViewById(R.id.mysv3);
            mySpinerView3.initText(name3);
            String[] names3 = {"10.0","20.0", "30.0", "40.0", "50.0"};
            for (int i = 0; i < names3.length; i++) {
                nameList3.add(names3[i]);
            }
            mySpinerView3.setData(nameList3);
    
            mySpinerView4 = (MySpinerView)findViewById(R.id.mysv4);
            mySpinerView4.initText(name4);
            String[] names4 = {"1min","1hour", "1day", "1year", "forever"};
            for (int i = 0; i < names4.length; i++) {
                nameList4.add(names4[i]);
            }
            mySpinerView4.setData(nameList4);
        }
    }
    

    大功告成~~~


    附上源码下载链接:Android 自定义下拉列表 源码

    展开全文
  • 35_Flutter之自定义下拉列表组件

    千次阅读 2020-01-08 15:20:30
    Flutter之自定义下拉列表组件 一.实现思路 通过自定义路由继承自PopupRoute,并结合Navigator.push使弹出的下拉列表能够覆盖在当前页面显示 使用CustomSingleChildLayout组件,自定义SingleChildLayoutDelegate并结合...
  • 自定义下拉列表,跟spinner的效果一样,但不会像spinner一样弹出一个dialog,而是一popupwindow的形式弹出
  • 自定义了QComboBox,将下拉框的原有左对齐的文字改为右对齐,包括下拉列表的文字,增大了下拉列表的高度,调整下拉列表的宽度的自适应。下拉框的下拉列表改成了仿手机的滑动操作方式,此为工程源码,Qt5亲测可用。
  • MlSkin.Demo.自定义下拉列表.2.x
  • 自定义下拉列表框: 下拉框提示信息,,prompt,,必须是dialog才可使用,添加下面style,,必须用字符串资源 style="@android:style/Widget.Spinner" android:prompt="@string/tishi" android:spinnerMode=...
  • Android自定义下拉列表,注释详细,重用性好,代码易懂
  • 自定义下拉列表select样式

    千次阅读 2018-01-25 17:15:51
    jq: ...$(this).click(function(event) {//自定义下拉列表框显示和隐藏 console.log(0); $(this).siblings("ul.option").toggleClass("hide");//切换hide样式 $(this).parent().toggleClass("se
  • 然而当编写自定义下拉列表的时候,就会碰到一个问题:如果用户在下拉列表的范围外进行鼠标点击的操作,如何关闭已经打开的下拉列表? 解决思路如下:在 DOM 的根节点上添加一个 click 事件,同时下拉列表内阻止事件...
  • jQuery+div+css模拟select自定义下拉列表框,简单轻巧实用。

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,918
精华内容 1,167
关键字:

自定义下拉列表