首页

Android5.0以后,materialDesign风格的加阴影和裁剪效果

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

5.0以后,materialDesign风格,出现了立体这种概念,高光,阴影,也就是Z轴,凸显层次;同时,裁剪view也变得方便简单了很多。
1,先说说阴影的实现。
方案1:在xml中设置 
xml中设置有两个方式,android:elevation="2dp" 
android:translationZ="2dp"这两句代码是可以同时并存的,而且是叠加的效果;当然只使用其中一个属性进行z轴的阴影设置也是OK的。

方案2:在代码中设置 
(下面说这个实现方式,其实就是轮廓的实现)

设置阴影,有一个需要注意的地方:
①:view的大小要比它的父布局小,才会有阴影效果,如果相同大小,是看不到阴影效果的; 
②:给图片设置阴影的时候,如果这种图片的background属性是shape,那直接通过xml设置阴影是OK的,但是,如果是一张png或者其他格式的图片,直接通过xml设置android:elevation="2dp" 
android:translationZ="2dp"阴影是看不到效果的,得通过其他代码设置才行。。。**

2,view的轮廓,轮廓其实也是阴影
默认情况下,所有的view都是矩形的,虽然可以给view设置背景圆形的图片,即可以在界面显示出圆形的内容,但是view的大小实际上依然是矩形,并且设置的图片实际上也是矩形的,只是圆形以外的区域是透明色。 
如果根据view大小来生成对应的阴影,就会出现很奇怪的效果,(一个看起来圆形的view展示出的确实一个矩形的阴影)我了解决这个问题,view增加了一个新的描述来指明内容显示的形状,这就是 轮廓

轮廓的实现
①通过shape设置的背景,view会自动根据shape的形状进行轮廓判定,
②通过color设置的背景,view默认其轮廓和view的大小一样。
③但是通过图片进行背景设置,view则无法获知轮廓的形状,这个时候就需要手动进行指定了。
1
2
3
一:在xml中可以通过android:outlineProvider来指定轮廓的判定方式: 
1,none即使设置了Z属性,也不会显示阴影 
2,background会按照背景来设置阴影形状 
3,bounds会按照view的大小来描绘阴影

**对于①和②这种情况,也是可以通过设置`android:outlineProvider`
来改变阴影的形状以及轮廓外观的。**

对于③这种背景是一张png或者其他格式的图片的情况,
`android:outlineProvider=“background”`
是没有效果的,属性设置成`android:outlineProvider=bounds`
虽然也是有效果的,但是阴影轮廓是一个方形的轮廓,
并不是我们想要的效果了。

不设置`android:outlineProvider`属性就更没有效果了。
1
2
3
4
5
6
7
8
9
10
对于这种使用了png图片作为背景的view加阴影轮廓的时候情况解决办法也非常简单,解决办法就是:
就通过Java代码设置,也就是说,一个圆形的png图(我们知道,看起来是圆形的,
但是它其实还是方形的图片,只是圆形之外的区域是透明不可见的),
 通过Java代码设置轮廓,就会显示出圆形的阴影轮廓了。
1
2
3
具体实现,继续看: 
二:在代码中,课通过setOutlineProvider来指定一个view的轮廓。 
对于③这种情况在代码中设置轮廓才会有效果。

TextView textView= findViewById(R.id.tv);
ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
         //x,y轴表示位置,后两个参数表示长,宽 
               outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
1
2
3
4
5
6
7
8
9
强调:
如果采用圆形图片作为背景,即使在xml布局中指定android:outlineProvider=“background”,也不会显示阴影,设置为android:outlineProvider=bounds,虽然也有效果,但是效果很差,所以一般都是通过代码来指定轮廓显示。

1,一个shape圆形作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


2,一个圆形png作为背景,设置阴影,设置android:outlineProvider的4种属性的效果:


3,一个png作为背景,设置阴影,通过代码设置的效果:


3,view的裁剪
裁剪,默认的ImageView是矩形的,很多时候,需要的是圆角的ImageView或者圆形的ImageView,这就需要裁剪view了。

实现,裁剪圆形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆形oval
                outline.setOval(0,0,textView.getWidth(),textView.getHeight());
            }
        };
//设置裁剪
textView.setClipToOutline(true);
1
2
3
4
5
6
7
8
9
10
11
实现,裁剪圆角矩形:

final TextView textView= findViewById(R.id.tv);

ViewOutlineProvider viewOutlineProvider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                //设置圆角矩形
               outline.setRoundRect(0,0,view.getWidth(),view.getHeight(),25);
            }
        };
textView.setOutlineProvider(viewOutlineProvider);
//设置裁剪
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

TabLayout 全面总结

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

一、简介

TabLayout提供了一个水平布局用于展示tabs,继承自HorizontalScrollView。一般与Viewpager结合使用实现页面和标签联动的效果,是时下APP中非常常用的一个控件



二、基本用法

  1. 添加design依赖

    compile 'com.android.support:design:25.3.1'

    1
  2. xml引用
  3. xml中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab1"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab2"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab3"/>

        <android.support.design.widget.TabItem

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="Tab4"/>

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21
  4. 代码中添加tab

    <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content">

    </android.support.design.widget.TabLayout>

    1

    2

    3

    4

    5

    // tablayout,Tab是TabLayout的内部类,且Tab的构造方法是包访问权限

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText("Tab1"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab2"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab3"));

    tabLayout.addTab(tabLayout.newTab().setText("Tab4"));

    1

    2

    3

    4

    5

    6





    三、属性详解

    <declare-styleable name="TabLayout">

        <!--指示器颜色-->

        <attr name="tabIndicatorColor" format="color"/>

        <!--指示器高度-->

        <attr name="tabIndicatorHeight" format="dimension"/>

        <!--tabs距TabLayout开始位置的偏移量,但app:tabMode="scrollable"才生效-->

        <attr name="tabContentStart" format="dimension"/>

        <!--仅是Tab背景,设置TabLayout背景用android:background-->

        <attr name="tabBackground" format="reference"/>

        <!--默认fixed,所有Tab只能在屏幕内显示,超出会被挤压;scrollable,tab数量多会超出屏幕,可滑动-->

        <attr name="tabMode">

            <enum name="scrollable" value="0"/>

            <enum name="fixed" value="1"/>

        </attr>

        <!--默认fill,tab填满TabLayout,但tabMode=“fixed”才生效;center,tabs位于TabLayout的中间-->

        <attr name="tabGravity">

            <enum name="fill" value="0"/>

            <enum name="center" value="1"/>

        </attr>

        <!--Tab的最小宽度-->

        <attr name="tabMinWidth" format="dimension"/>

        <!--Tab的最大宽度-->

        <attr name="tabMaxWidth" format="dimension"/>

        <!--Tab文本设置样式-->

        <attr name="tabTextAppearance" format="reference"/>

        <!--Tab未选中字体颜色-->

        <attr name="tabTextColor" format="color"/>

        <!--Tab选中字体颜色-->

        <attr name="tabSelectedTextColor" format="color"/>

        <!--Tab内填充相关-->

        <attr name="tabPaddingStart" format="dimension"/>

        <attr name="tabPaddingTop" format="dimension"/>

        <attr name="tabPaddingEnd" format="dimension"/>

        <attr name="tabPaddingBottom" format="dimension"/>

        <attr name="tabPadding" format="dimension"/>

    </declare-styleable>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    使用示例



     <android.support.design.widget.TabLayout

        android:id="@+id/tab_layout"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        app:tabIndicatorColor="@color/colorPrimaryDark"

        app:tabIndicatorHeight="2dp"

        app:tabContentStart="50dp"

        app:tabBackground="@color/colorAccent"

        app:tabMode="scrollable"

        app:tabGravity="fill"

        app:tabTextAppearance="@style/MyTabTextAppearance"

        app:tabTextColor="@android:color/black"

        app:tabSelectedTextColor="@android:color/white"/>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    <style name="MyTabTextAppearance" parent="TextAppearance.Design.Tab">

        <item name="textAllCaps">false</item>

        <item name="android:textSize">18sp</item>

    </style>

    1

    2

    3

    4





    四、图文混排,Tab中添加图片
  5. 通过SpannableString设置图片

    @NonNull

    private SpannableString setImageSpan(String string,int drawableId) {

        SpannableString ss = new SpannableString("  "+string);

        Drawable drawable = ContextCompat.getDrawable(this, drawableId);

        drawable.setBounds(0,0,drawable.getIntrinsicWidth(),drawable.getIntrinsicHeight());

        ImageSpan imageSpan = new ImageSpan(drawable);

        ss.setSpan(imageSpan,0,1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

        return ss;

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab1",R.drawable.ic_home)));

    tabLayout.addTab(tabLayout.newTab().setText(setImageSpan("Tab2",R.drawable.ic_info)));

    ……

    1

    2

    3

    4





    我们会发现个问题,通过ImageSpan设置的图片和文字没有对齐,先百度到一个可用方法解决:重写ImageSpan的draw()方法



    package com.strivestay.tablayoutdemo;



    import android.graphics.Bitmap;

    import android.graphics.Canvas;

    import android.graphics.Paint;

    import android.graphics.drawable.Drawable;

    import android.support.annotation.NonNull;

    import android.text.style.ImageSpan;



    public class CenterImageSpan extends ImageSpan {

        public CenterImageSpan(Drawable drawable) {

            super(drawable);



        }



        public CenterImageSpan(Bitmap b) {

            super(b);

        }



        @Override

        public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom,

                         @NonNull Paint paint) {



            Drawable b = getDrawable();

            Paint.FontMetricsInt fm = paint.getFontMetricsInt();

            int transY = (y + fm.descent + y + fm.ascent) / 2 - b.getBounds().bottom / 2;//计算y方向的位移

            canvas.save();

            canvas.translate(x, transY);//绘制图片位移一段距离

            b.draw(canvas);

            canvas.restore();

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    将上面的ImageSpan替换为现在的CenterImageSpan,即可实现图文混排时对齐






  6. 通过Tab.setCustomView()设置图片
  7. 自定义view布局

    <?xml version="1.0" encoding="utf-8"?>

    <LinearLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:orientation="vertical"

        android:gravity="center">

        <ImageView

            android:id="@+id/iv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:src="@drawable/ic_home"/>

        <TextView

            android:id="@+id/tv"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_margin="2dp"

            android:textSize="16sp"

            android:text="首页"/>

    </LinearLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20
  8. 代码设置

     TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_home,"首页")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_info,"资讯")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_live,"直播")));

    tabLayout.addTab(tabLayout.newTab().setCustomView(setCustomView(R.drawable.ic_me,"我")));

    1

    2

    3

    4

    5

     private View setCustomView(int drawableId,String tabText) {

        View view = View.inflate(this, R.layout.item_tab, null);

        ImageView iv = (ImageView) view.findViewById(R.id.iv);

        TextView tv = (TextView) view.findViewById(R.id.tv);

        iv.setImageResource(drawableId);

        tv.setText(tabText);

        return view;

    }

    1

    2

    3

    4

    5

    6

    7

    8





    五、TabLayout与Viewpager联动
  9. xml设置TabLayout和Viewpager

    第一种:TabLayout放置在Viewpager的上方,放在AppbarLayout中会有阴影效果



    <?xml version="1.0" encoding="utf-8"?>

    <android.support.design.widget.CoordinatorLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        xmlns:app="http://schemas.android.com/apk/res-auto"

        xmlns:tools="http://schemas.android.com/tools"

        android:id="@+id/main_content"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        android:fitsSystemWindows="true"

        tools:context="com.strivestay.tablayoutdemo.MainActivity">



        <android.support.design.widget.AppBarLayout

            android:id="@+id/appbar"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            android:paddingTop="@dimen/appbar_padding_top"

            android:theme="@style/AppTheme.AppBarOverlay">



            <android.support.v7.widget.Toolbar

                android:id="@+id/toolbar"

                android:layout_width="match_parent"

                android:layout_height="?attr/actionBarSize"

                android:background="?attr/colorPrimary"

                app:layout_scrollFlags="scroll|enterAlways"

                app:popupTheme="@style/AppTheme.PopupOverlay">



            </android.support.v7.widget.Toolbar>



            <android.support.design.widget.TabLayout

                android:id="@+id/tab_layout"

                android:layout_width="match_parent"

                android:layout_height="wrap_content"

                app:tabIndicatorColor="@color/colorAccent"

                app:tabIndicatorHeight="2dp"

                app:tabBackground="@android:color/white"

                app:tabTextAppearance="@style/MyTabTextAppearance"

                app:tabTextColor="@android:color/black"

                app:tabSelectedTextColor="@android:color/holo_blue_light">

            </android.support.design.widget.TabLayout>



        </android.support.design.widget.AppBarLayout>



        <android.support.v4.view.ViewPager

            android:id="@+id/container"

            android:layout_width="match_parent"

            android:layout_height="match_parent"

            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>



        <android.support.design.widget.FloatingActionButton

            android:id="@+id/fab"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:layout_gravity="end|bottom"

            android:layout_margin="@dimen/fab_margin"

            app:srcCompat="@android:drawable/ic_dialog_email"/>



    </android.support.design.widget.CoordinatorLayout>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58





    第二种:TabLayout直接放在Viewpager,无阴影



    <android.support.v4.view.ViewPager

        android:id="@+id/container"

        android:layout_width="match_parent"

        android:layout_height="match_parent"

        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <android.support.design.widget.TabLayout

            android:id="@+id/tab_layout"

            android:layout_width="match_parent"

            android:layout_height="wrap_content"

            app:tabIndicatorColor="@color/colorAccent"

            app:tabIndicatorHeight="2dp"

            app:tabBackground="@android:color/white"

            app:tabTextAppearance="@style/MyTabTextAppearance"

            app:tabTextColor="@android:color/black"

            app:tabSelectedTextColor="@android:color/holo_blue_light">

        </android.support.design.widget.TabLayout>

    </android.support.v4.view.ViewPager>

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17




  10. 为Viewpager创建适配器

    /

      fragment

     
    /

    public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SECTION = "section";



        public PlaceholderFragment() {

        }



        public static PlaceholderFragment newInstance(String section) {

            PlaceholderFragment fragment = new PlaceholderFragment();

            Bundle args = new Bundle();

            args.putString(ARG_SECTION, section);

            fragment.setArguments(args);

            return fragment;

        }



        @Override

        public View onCreateView(LayoutInflater inflater, ViewGroup container,

                                 Bundle savedInstanceState) {

            View rootView = inflater.inflate(R.layout.fragment_main, container, false);

            TextView textView = (TextView) rootView.findViewById(R.id.section_label);

            textView.setText(getArguments().getString(ARG_SECTION));

            return rootView;

        }

    }



    /


      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        String[] tabs = {"首页","资讯","直播","我"};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

            return tabs[position];

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    主要是重写getPageTitle()方法


  11. 代码设置 TabLayout和Viewpager绑定

     // tablayout

    TabLayout tabLayout = (TabLayout) findViewById(R.id.tab_layout);



    // vp

    mViewPager = (ViewPager) findViewById(R.id.container);

    mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

    mViewPager.setAdapter(mSectionsPagerAdapter);



    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    调用setupWithViewPager()方法,则使用TabLayout.addtab()方法无效,TabLayout会清除之前添加的所有tabs,并将根据Viewpager的页数添加Tab,Tab标题为对应页通过getPageTitle()返回的文本






  12. 图文混排
  13. 同上,使用SpannableString

    修改Adapter如下:



    /*

     
    pagerAdapter

     */

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

            return setImageSpan(tabs[position],imgs[position]);

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    setImageSpan()方法同上






  14. 同上,使用Tab.setCustomView()

    修改pagerAdapter如下:



    /

      pagerAdapter

     
    /

    public class SectionsPagerAdapter extends FragmentPagerAdapter {



        String[] tabs = {"首页","资讯","直播","我"};

        int[] imgs = {R.drawable.ic_home,R.drawable.ic_info,R.drawable.ic_live,R.drawable.ic_me};



        public SectionsPagerAdapter(FragmentManager fm) {

            super(fm);

        }



        @Override

        public Fragment getItem(int position) {

            return PlaceholderFragment.newInstance(tabs[position]);

        }



        @Override

        public int getCount() {

            return tabs.length;

        }



        @Override

        public CharSequence getPageTitle(int position) {

    //            return tabs[position];

    //            return setImageSpan(tabs[position],imgs[position]);

            return null;

        }



        /


          设置自定义view

         
    @param position

          @return

         
    /

        public View setCustomView(int position) {

            View view = View.inflate(getApplicationContext(), R.layout.item_tab, null);

            ImageView iv = (ImageView) view.findViewById(R.id.iv);

            TextView tv = (TextView) view.findViewById(R.id.tv);

            iv.setImageResource(imgs[position]);

            tv.setText(tabs[position]);

            return view;

        }

    }

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    代码修改如下:



    …………

    // 绑定,要在viewpager设置完数据后,调用此方法,否则不显示 tabs文本

    tabLayout.setupWithViewPager(mViewPager);



    // 为绑定viewpager后的TabLayout的tabs设置自定义view

    for (int i = 0; i < mSectionsPagerAdapter.getCount(); i++) {

        tabLayout.getTabAt(i).setCustomView(mSectionsPagerAdapter.setCustomView(i));

    }

    1

    2

    3

    4

    5

    6

    7

    8

    发现问题:我使用的仍然是上面的item_tab,但是只显示图片,不显示文字如下







    翻了翻源码,也没发现有对Tab的标题有特别的设置;后来,就感觉是不是颜色问题,给item_tab中的textview加上属性android:textColor="@android:color/black",就显示出来了







    六、FlycoTabLayout

    这是一个不错的TabLayout开源项目,效果挺好,可以了解一下。





    蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

jQuery中的Ajax操作

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

jQuery对Ajax操作进行了封装,常用的方法包括 $.get(),$.post(),$.ajax()。 
分别对其进行介绍

$.get()
$.get()方法使用GET方式来进行异步请求。
$.get()结构
$.get(url,[. data][. callback][. type])
1
$.get()方法参数解释
参数名称 类型 说明
url String 请求的HTML页的url地址
data(可选) Object 发送至服务器的key/value数据会作为QueryString附加到请求的url中
callback(可选) Function 载入成功时回调函数(只有当Response的返回状态是success才调用该方法)自动将请求结果和状态传递给该方法
type(可选) String 服务器端返回内容的格式,包括xml、html、script、json、text和_default
示例 
json数据:data.json(后面的$.post()和$.ajax()方法都用这个数据)
{
    "name":"龙猫",
    "hobby":"睡觉",
    "friend":"加菲猫"
}

jq_get.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>

</head>
<body>
    <input type="button" value="$.get方法" id="jQget">
    <div id="content"></div>
</body>
</html>
<!-- 导入jquery.js文件 -->
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQget').on('click',function(){

            /*

            参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写
                注意
                    如果type 为json 
                        并且服务端返回的就是 json格式字符串
                        jq内部 会帮助我们自动转化
                        在回调函数中 获取的 实参 就是转化完成的 js对象 直接使用即可

                参数的 顺序 是更换的
                    但是 如果 把data 放到后面 会出现 无法传递数据的问题,
                    所以 不要擅自更换 严格按照 jq文档中的 顺序 进行使用
            */
            $.get('jq_get.php',{name:"jack",age:18},function(data){
                    console.log(data);

                    $('#content').html('name:'+data.name+'<br>'+'hobby:'+data.hobby+'<br>'+'friend:'+data.friend); 

            },'json');
        });

    });
</script>

jq_get.php (后面的$.post()和$.ajax()方法都用这个页面的内容,只是在html请求时分别对应的php页面)

<?php
    header('content-type:text/html;charset=utf-8');
    echo file_get_contents('datas/data.json');
?>

结果展示: 


$.post()方法
  它与$.get()方法的结构和使用方式都相同,不过它们之间仍然有以下区别:

GET请求会将参数跟在URL后进行传递,而POST请求则是作为HTTP消息的实体内容发送个Web服务器,当然,在Ajax中,这种区别对用户是不可见的。
GET方式对传输的数据有大小限制(通常不能大于2KB),而使用POST方式传递的数据量要比GET方式大得多(理论上不受限制,但是可以在服务端进行限制)。
GET方式请求的数据会被浏览器缓存起来,因此其他人就可以从浏览器的历史记录中读取这些数据,例如账号和密码等。在某种情况下,GET方式会带来严重的安全性问题,而POST方式相对来说就可以避免这些问题。(但是也是不安全的,所以密码之类的还是要加密的)
GET方式和POST方式传递的数据在服务器的获取方式也不相同。在PHP中,GET方式数据可以用$_GET[]获取,而POST可以用$_POST[]获取、两种方式都可以用$_REQUEST[]来获取。 
其实这完全是对这篇文章中post()和get()方法不同的总结啊!(点击查看) 
$.post()演示
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jQpost').on('click',function(){
            // 跟$.get用法及其类似
            /*
                参数1:url
                参数2:发送的数据 支持 直接写js对象的方式
                参数3:回调函数
                参数4:从服务端获取的 数据类型 可以不写,如果写为json jq内部 会帮我们进行一个 JSON.parse()的转化 
            */
             $.post('jq_post.php',{name:"kong",age:18},function(data){
                    console.log(data);
             },'json');
        });
    });
</script>

$.ajax()
$.ajax()方法是jQuery最底层的Ajax实现
其结构为
$.ajax(options)
1
该方法只有1个参数,但在这个对象里包含了$.ajax()方法所需要的请求设置以及回调函数等信息,参数以key/value的形式存在,所有参数都是可选的,只写几个常用的参数,如下:

参数名称 类型 说明
url String 请求的HTML页的url地址
type String 请求方式,默认GET。注意其他的HTTP请求方法,例如PUT和DELETE也可以使用,但仅部分浏览器支持
data Object或String 发送到服务器的数据,如果已经不是字符串,将自动转换为字符串格式。
dataType String 服务器端返回内容的格式,包括xml、html、script、json、jsonp 、jQuery
beforeSend Function 发送请求前可以修改XMLHttpRequest对象的函数,例如添加自定义HTTP头。在beforeSend中如果返回false可以取消本次Ajax请求。XMLHttpRequest对象的唯一参数。
success Function 请求成功后嗲用的回调函数,有两个参数。
(1)由服务器返回,并根据dataType参数进行处理后的数据。
(2)描述状态的字符串。
function(data,textStatus){
        //data可能是xmlDoc、jsonObj、html、text等等。
        this//调用本次Ajax请求时传递的options参数
  }
error Function 请求失败时被调用的函数,该函数有3个参数,即
XMLHttpRequest对象、错误信息、捕获的错误对象(可选)。
Ajax事件函数如下。
function(XMLHttpRequest,textStatus,errorThrown){//通常情况下textStatus和errorThown只有其中一个包含信息
this;//调用本次Ajax请求时传递的options参数
}
示例
<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript">
    $(function(){
        $('#jqAjax').on('click',function(){
    /*
                常见参数:
                    url:请求的地址
                    success:请求成功的回调函数
                    type:不写是get 可以指定 get,post
                    dataType:数据的类型
                    data:发数据 可以写js对象
                    beforeSend:发送之前调用的匿名函数
                        可以return false 阻止该次请求
                        验证用户的数据 是否填了
                    error:请求失败以后 会调用
            */
            $.ajax({
                url:'jq_ajax.php',
                success:function(data){
                    console.log(data);
                    $('#box').append(data.name+'<br>'+data.hobby);
                },
                type:'post',
                dataType:'json',
                data:{"name":"张信哲","skill":"情歌王子"},
                beforeSend:function(){
                    console.log('发送之前调用');
                },
                error:function(){
                    console.log('请求失败了');
                }
            });
        });

    });
</script>
--------------------- 
作者:diligentkong 
来源:CSDN 
原文:https://blog.csdn.net/diligentkong/article/details/72851443 
版权声明:本文为博主原创文章,转载请附上博文链接!
蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

ionic用插件(cordova-plugin-baidumaplocation)定位并调百度地图在上面显示

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

之前研究了定位,想用百度地图,但是用百度地图的 
JavaScript API里面的浏览器定位根本不行,要用插件,很多人说本身带的这个cordova-plugin-geolocation插件因为网络问题,只有ios可以用,然后找到了专门针对安卓的cordova-qdc-baidu-location插件,但是这个插件不知道是不是我使用的问题,得到的数据可以弹出来,但是数据并不像这个插件所说的数据格式是

{
  latitude : 纬度,
  lontitude: 经度, ... }
    
  • 1
  • 2
  • 3
  • 4
  • 5

这样的,而是字符串,不是json字符串,弄了半天还是取不到里面的关于经纬度的值,然后发现了现在的这个定位插件cordova-plugin-baidumaplocation这个插件返回的数据格式是json的,可以直接获取。 
因为网络配代理的原因,一直添加不上插件,今天才发现用cordova-plugin-baidumaplocation插件定位其实挺简单的。 
1.申请AK值。 
地址:http://lbsyun.baidu.com/ 
需要申请两个或者三个(配置ios),一个是js的,一个是android的(三个的话还有一个ios的,但是这边直接只写安卓的,其实ios是一样的) 
注:包名要一致 
2.添加插件. 
命令:

cordova plugin add cordova-plugin-baidumaplocation --variable ANDROID_KEY="<API_KEY_ANDROID>" --variable IOS_KEY="<API_KEY_IOS>"
    
  • 1

注意:是没有<>这种尖括号的。 
到此为止准备工作基本上晚了,开始代码部分: 
1.引入百度地图:

<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=nLsK9qUii8uBZlkPAQUozAf9mR5xNVZF"></script>
    
  • 1

这个引入是为了转化经纬度为地址和显示地图。 
2.在html页面上写两个 标签:

<button class="button" ng-click="getarea()">点击我获取地址百度</button> <div id='allmap' style=""></div>
    
  • 1
  • 2

div标签是为了放地图的。 
3.js部分:

$scope.getarea=function(){ //myaddr(116.324499,39.899216); // 进行定位 baidumap_location.getCurrentPosition(function (result) { var latitude=result.latitude; var lontitude=result.lontitude;
        myaddr(lontitude,latitude);
      }, function (error) { });
    } //根据定位得到的经纬度对地址进行解析 function myaddr(lontitude,latitude){ //alert("我的地址是:"+lontitude+","+latitude); // 百度地图API功能 var map = new BMap.Map("allmap"); var point = new BMap.Point(lontitude, latitude);//34.7534880000,113.6313490000 map.centerAndZoom(point, 12); var marker = new BMap.Marker(point); // 创建标注 map.addOverlay(marker); // 将标注添加到地图中 //把地址在地图上标出来 var geoc = new BMap.Geocoder();
      geoc.getLocation(point, function(rs){ var addrmsg=rs.address; //var addComp = rs.addressComponents;  //详细的分省市县街道的信息 //alert(addComp.province + ", " + addComp.city + ", " + addComp.district + ", " + addComp.street + ", " + addComp.streetNumber); var opts = {
          width : 200, // 信息窗口宽度 height: 50, // 信息窗口高度 } var infoWindow = new BMap.InfoWindow("地址:"+addrmsg, opts); //创建信息窗口对象  map.openInfoWindow(infoWindow,point); //开启信息窗口 }); 

    }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

4.css部分:其实可以不要的,这是因为地图中的地址显示的窗口看起来有点问题,虽然改了依旧不好看,但是功能实现了。

.BMap_pop{ top: 70px !important; } .BMap_bubble_content{ width: 95% !important; } .BMap_center{ top: 26px !important; }
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

注:现在得到的地址是省市县街道地址,想得到诸如:北京市朝阳区XX大厦附近这样的地址的话还没有研究,等研究出来了再补上。 

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


js 模块化编程

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

了解一个技术,首先要了解这个技术产生的背景及解决的问题,而不应该只是单纯的知道该怎么用。之前的状态可能就是只是为了了解而了解,并不知道实际产生的原因及带来的好处,所以今天就来总结一下。

1. 什么是模块化编程

来看百度百科的定义

模块化程序设计是指在进行程序设计时将一个大程序按照功能划分为若干小程序模块,每个小程序模块完成一个确定的功能,并在这些模块之间建立必要的联系,通过模块的互相协作完成整个功能的程序设计方法。

比如 java 的 import,C# 的 using。我的理解是通过模块化编程,可以将不同的功能独立出来,修改某个功能时不会对其他功能产生影响。

2. 为什么要模块化

来看下面一个例子

// A.js function sayWord(type){ if(type === 1){
        console.log("hello");
    }else if(type === 2){
        console.log("world");
    }
} // B.js function Hello(){ sayWord(1);
} // C.js Hello()  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

假设上面三个文件,B.js 引用了 A.js 里面的内容,C.js 又引用了 B.js 里面的内容,如果编写 C.js 的人只知道引用了 B.js,那他就不会引用 A.js 就会导致程序出错,而且文件的引用顺序也不能出错。给整体代码的调试修改带来不便。

还有个问题,上述代码暴露了两个全局变量,容易造成全局变量的污染

3. AMD

AMD 即 Asynchronous Module Definition(异步模块定义)。采取异步加载的方式加载模块,模块的加载不会影响它后面的语句执行。而且只有用到的时候才会去加载相关文件,属于浏览器端的标准

假设下面这种情况

// util.js define(function(){ return {
        getFormatDate:function(date,type){ if(type === 1){ return '2018-08-9' } if(type === 2){ return '2018 年 8 月 9 日' }
        }
    }
}) // a-util.js define(['./util.js'],function(util){ return {
        aGetFormatDate:function(date){ return util.getFormatDate(date,2)
        }
    }
}) // a.js define(['./a-util.js'],function(aUtil){ return {
        printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
        }
    }
}) // main.js require(['./a.js'],function(a){ var date = new Date()
    a.printDate(date)
})
console.log(1); // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>   
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

页面上先打印 1,然后才会打印 2018 年 8 月 9 日。因此 AMD 的加载并不会影响后续的语句执行。

如果不是异步加载会出现什么情况呢

var a = require('a');
console.log(1) 
  • 1
  • 2

后面的语句需要等待 a 加载完成才能执行,如果加载时间过长,整个程序都会卡在这。因此,浏览器不能同步加载资源,这也是 AMD 的产生背景。

AMD 是在浏览器端实现模块化开发的规范。由于该规范不是 JavaScript 原始支持的,使用 AMD 规范进行开发的时候需要引入第三方的库函数,也就是 RequireJS。

RequireJS 主要解决的问题

  • 使 JS 异步加载,避免页面失去响应
  • 管理代码之间的依赖性,有利于代码的编写和维护

下面来看看如何使用 require.js

要想使用 require.js,首先要 define

// ? 代表该参数可选 define(id?, dependencies?, factory); 
  • 1
  • 2
  • id:指的是定义的模块的名字
  • dependencies:是定义的模块所依赖模块的数组
  • factory:为模块初始化要执行的函数或对象。如果为函数,它应该只被执行一次。如果是对象,此对象应该为模块的输出值。

    具体的规范说明可以参考 AMD (中文版) 
    举个例子,创建一个名为 “alpha” 的模块,使用了 require,exports,和名为 “beta” 的模块:

define("alpha", ["require", "exports", "beta"], function (require, exports, beta) { exports.verb = function() { return beta.verb(); //Or: return require("beta").verb();
       }
   }); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

一个返回对象的匿名模块:

define(["alpha"], function (alpha) { return {
         verb: function(){ return alpha.verb() + 2;
         }
       };
   }); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

一个没有依赖性的模块可以直接定义对象:

define({
     add: function(x, y){ return x + y;
     }
   }); 
  • 1
  • 2
  • 3
  • 4
  • 5

如何使用

AMD 采用 require 语句加载模块

require([module],callback); 
  • 1
  • module:是一个数组,里面的成员是要加载的模块
  • callback:加载成功之后的回调函数

例如

require(['./a.js'],function(a){ var date = new Date()
    a.printDate(date)
}) 
  • 1
  • 2
  • 3
  • 4

具体的使用方法如下

// util.js define(function(){ return {
        getFormatDate:function(date,type){ if(type === 1){ return '2018-08-09' } if(type === 2){ return '2018 年 8 月 9 日' }
        }
    }
}) // a-util.js define(['./util.js'],function(util){ return {
        aGetFormatDate:function(date){ return util.getFormatDate(date,2)
        }
    }
}) // a.js define(['./a-util.js'],function(aUtil){ return {
        printDate:function(date){ console.log(aUtil.aGetFormatDate(date))
        }
    }
}) // main.js require(['./a.js'],function(a){ var date = new Date()
    a.printDate(date)
}) // 使用 // <script src = "/require.min.js" data-main="./main.js"></script>  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

假设这里有 4 个文件,util.js,a-util.js 引用了 util.js,a.js 引用了 a-util.js,main.js 引用了 a.js。

其中,data-main 属性的作用是加载网页程序的主模块。

上例演示了一个主模块最简单的写法,默认情况下,require.js 假设依赖和主模块在同一个目录。

使用 require.config() 方法可以对模块的加载行为进行自定义。require.config() 就写在主模块(main.js)的头部,参数是一个对象,这个对象的 paths 属性指定各个模块的加载路径

require.config({
    paths:{ "a":"src/a.js", "b":"src/b.js" }
}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

还有一种方法是改变基础目录(baseUrl)

require.config({

    baseUrl: "src",

    paths: { "a": "a.js", "b": "b.js",

    }

  }); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

4. CommonJS

commonJS 是 nodejs 的模块化规范,现在被大量用在前端,由于构建工具的高度自动化,使得使用 npm 的成本非常低。commonJS 不会异步加载 JS,而是同步一次性加载出来

在 commonJS 中,有一个全局性的方法 require(),用于加载模块,例如

const util = require('util'); 
  • 1

然后,就可以调用 util 提供的方法了

const util = require('util'); var date = new date();
util.getFormatDate(date,1); 
  • 1
  • 2
  • 3

commonJS 对于模块的定义分三种,模块定义(exports),模块引用(require)和模块标示(module)

exports() 对象用于导出当前模块的变量或方法,唯一的导出口。require() 用来引入外部模块。module 对象代表模块本身。

举个栗子

// util.js module.exports = {
    getFormatDate:function(date, type){ if(type === 1){ return '2017-06-15' } if(type === 2){ return '2017 年 6 月 15 日' }
    }
} // a-util.js const util = require('util.js')
module.exports = {
    aGetFormatDate:function(date){ return util.getFormatDate(date,2)
    }
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

或者下面这种方式

 // foobar.js // 定义行为 function foobar(){ this.foo = function(){ console.log('Hello foo');
        } this.bar = function(){ console.log('Hello bar');
          }
 } // 把 foobar 暴露给其它模块 exports.foobar = foobar; // main.js //使用文件与模块文件在同一目录 var foobar = require('./foobar').foobar,
test = new foobar();
test.bar(); // 'Hello bar' 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

5. ES6 Module

ES6 模块的设计思想是尽量静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量,而 CommonJS 和 AMD 模块都只能在运行时确定这些关系。如 CommonJS 加载方式为 “运行时加载”,ES6 的加载方式为 “编译时加载” 或者静态加载,即 ES6 可以在编译时就完成模块加载,效率比 CommonJS 模块的加载方式高。

ES6 模块自动采用严格模式,不管有没有在模块头部加上 “use strict”。

ES6 export 语句输出的接口与其对应的值是动态绑定关系,即通过该接口可以取到模块内部实时的值。而 CommonJS 模块输出的是值的缓存,不存在动态更新。

ES6 与 CommonJS 模块的差异

  • CommonJS 模块输出的是一个值的复制,ES6 模块输出的是值的引用。
  • CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
  • CommonJS 中的 this 指向当前模块,ES6 模块 this 为 undefined

第二个差异是因为 CommonJS 加载的是一个对象(即 Module.exports 属性),该对象只有在脚本运行结束时才会生成,而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。

总结

CommonJS 采用了服务器优先的策略,使用同步方式加载模块,而 AMD 采用异步加载的方式。所以如果需要使用异步加载 js 的话建议使用 AMD,而当项目使用了 npm 的情况下建议使用 CommonJS。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


微信小程序开发(四)获取用户openid

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

在小程序里面有两个地方获取用户的openid。 
一个是wx.login(OBJECT),第二个是wx.getUserInfo(OBJECT)。 
这里我使用的是第一种wx.login(OBJECT)

步骤

 wx.login({
  success: function(res) { if (res.code) { //  第一步: 获取code //发起网络请求 wx.request({
        url: '后台接口', // 获取openid data: {
          code: res.code
        }
      })
    } else {
      console.log('获取用户登录态失败!' + res.errMsg)
    }
  }
}); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

后端的实现

后端的实现就是后端调用这个接口:https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code。 
这里写图片描述

/*
 * 根据code获取微信用户的openid
 */ router.get('/api/getWxCode', function(req, res, next) { var param = req.query || req.params; var code = param.code; var urlStr = 'https://api.weixin.qq.com/sns/jscode2session?appid=' + wxConfig.AppID + '&secret=' + wxConfig.Secret + '&js_code=' + code + '&grant_type=authorization_code';
    request(urlStr, function (error, response, body) { if (!error && response.statusCode == 200) { var jsBody = JSON.parse(body); 
            jsBody.status = 100;
            jsBody.msg = '操作成功';
            res.end(JSON.stringify(jsBody));
        }
    })
}); 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

具体实例

/**
 * 生命周期函数--监听页面加载
 */ onLoad: function (options) { var self = this;
  wx.login({
    success: function (res) { if (res.code) { //发起网络请求 wx.request({
          url: 'https://www.hgdqdev.cn/api/getWxCode',
          data: {
            code: res.code
          },
          success: function(res){ if(res.data.status == 100){ self.setData({
                openid: res.data.openid
              })
            }
          },
          fail: function(){ }
        })
      } else {
        console.log('获取用户登录态失败!' + res.errMsg)
      }
    }
  });
},

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


关于Python+selenium 定位浏览器弹窗元素

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

我也是刚学自动化,在自学过程中发现浏览器中有一些弹窗元素,无法定位。经过自己的摸索,有一些心得,写下来供日后自己回顾。
首先要确定弹窗的类型:
(1)div弹窗
(2)新标签页弹窗
(3)alert弹窗 
    
  • 1
  • 2
  • 3
  • 4
  • 5

一,div弹窗 
div弹窗是浏览器中比较好定位的弹窗,定位的方法与普通的元素一样。不过这里会有一个坑,明明可以找到这个按钮,但是就是定位不到。这个就是因为当前有div弹窗弹出的时候,需要设置一下等待时间,等页面元素加载完毕,再去做其他操作。 
这里用百度登陆为例子:

from selenium import webdriver import time def login_baidu(url,username,password): driver.get(url)
    driver.find_element_by_xpath('//*[@id="u1"]/a[7]').click()
    time.sleep(2)
    driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__footerULoginBtn"]').click()
    time.sleep(2) # 弹窗出现后,使页面等待2S login_username = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__userName"]')
    login_username.click()
    login_username.send_keys(username)

    login_passwork = driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__password"]')
    login_passwork.click()
    login_passwork.send_keys(password)

    driver.find_element_by_xpath('//*[@id="TANGRAM__PSP_10__submit"]').click() # 登陆按钮 if __name__ == "__main__":
    driver = webdriver.Firefox()
    username = r'xxx@qq.com' password = r'xxxx' url = r'https://www.baidu.com' login_baidu(url,username,password) 
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

二,新标签页弹窗 
新标签页弹窗,则需要进行窗口的切换。此处第一个窗口打开百度首页,在打开一个新窗口打开京东首页,在两个窗口之间进行切换。切换到不同的窗口之后,就可以用常规的方法进行元素的定位。

from selenium import webdriver import time def open_window1(): driver.get("https://www.baidu.com")
   time.sleep(2) def open_window2(): # 用JS的方法打开新窗口,模拟新标签页弹窗 js = "window.open('https://www.jd.com')" driver.execute_script(js)
    time.sleep(2) def Switch_Window(): handles = driver.window_handles
    print("打印当前已打开的窗口:"+str(handles)) while(5): # 在两个窗口之间做五次切换动作 driver.switch_to.window(handles[0])
        time.sleep(5)
        driver.switch_to.window(handles[1])
        time.sleep(5) if __name__ == "__main__" :
    driver = webdriver.Firefox()
    open_window1()
    open_window2()
    Switch_Window() 
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
handles = driver.window_handles # 获取当前打开的所有窗口的句柄
driver.switch_to.window(handles[N]) # 切换到其中一个窗口
其中,获取的句柄下标从0开始,即第一个窗口为[0]、第二个窗口为[1],如此类推。使用switch_to.window方法切换到新标签页后就可以做其他操作了。 
    
  • 1
  • 2
  • 3

三、alert弹窗 
该类型的弹窗暂没有合适的项目进行练习,待后续完善

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务

CSS学习-选择器

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

选择器

学习目的 熟练使用 css 选择器


css1 中的选择器


E #myid         id选择器

E .warning      类选择器

E F             包含选择器

E:link          定义超链接未被访问

E:visited       定义超链接已经被访问

E:actice        匹配被激活的元素

E:hover     鼠标经过的元素

E:focus     获取焦点

E::first-line   元素第一行

E::first-letter 元素第一个字符


css2


*               通配选择文档中所有元素

E[foo]          包含foo属性的元素

E[foo="bar"]    包含属性foo值为bar的元素


CSS3 中的选择器可替代 了解即可

E[foo~="bar"]  含有属性foo值包括bar的元素例如 <a foo="bar bar1 bar2">link</a>

E[foo|="en"]    属性值是一个“-”分割的 比如 en-us


E:first-child   父元素的第一个子元素

E:lang(fr)      匹配属性,元素显示内容为语言为 fr

E::before       在元素前面插入内容

E::after        在元素后面插入内容

E>F             子包含

E+E             相邻兄弟选择器 后面的兄弟


css3


E[foo^="bar"]   属性foo的值开头是bar

E[foo$="bar"]  属性foo的值得结尾是bar

E[foo*="bar"]   属性foo的值包含bar <a foo="abc_bar_as">link</a>


结构类选择器


E:root          属性文档所在的根元素

E:nth-child(n)  E元素第n个位置的子元素 n可以是 (1,2,3) 关键字(odd,even) 公式(2n,2n+3) 起始值为1

E:nth-last-child(n) 与上面的使用方法一样 倒数的第N个位置的子元素

E:nth-of-type(n)    匹配父元素中与E相同的元素中的第n个元素

E:nth-last-of-type(n)   匹配父元素中与E相同的倒数第n个元素

E:last-child    选择位于其父元素的最后一个位置,且匹配E的子元素

E:first-of-type 选择在其父元素中匹配E的第一个同类型的子元素

E:last-of-type  选择在其父元素中匹配E的最后一个同类型的子元素

E:only-child    选择其父元素只包含一个子元素,且该子元素匹配E

E:only-of-type  选择其父元素只包含一个同类型的子元素,且该子元素匹配E

E:empty         选择匹配E的元素,且该元素不包含子节点,文本也是节点


E~F 通用兄弟选择器

E:not(s)    否定伪类选择器


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务



bootstrap table实现x-editable的行单元格编辑及解决数据Empty和支持多样式

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

前言

  • 最近在研究bootstrap table的表格的单元格编辑功能,实现点击单元格修改内容,其中包括文本(text)方式修改,下拉选择(select)方式修改,日期(date)格式修改等。
  • 本文着重解决x-editable编辑的数据动态添加和显示数据为Empty的问题,还有给表格单元格的内容设置多样式,使得显示多样化。
  • 由于官网给的demo的数据都是html文件里写好的,select类型的不能动态添加(所以网上的大多都是官网的类似例子,本篇博客就是在这种情况下以自己的经验分享给大家,有问题可以留言哦),一旦动态添加就会出现显示数据为Empty,我表格原本是有数据的,但是一用这个插件就把数据变成Empty了,这可不是我想要的,所以笔者就自行解决了这个问题。

对比网上的例子

  • 比如以下这种数据不是Empty的例子,但是是由于在html中写死了数据(awesome),不适合动态添加。
<a href="#" id="username" data-type="text" data-pk="1">awesome</a> <script> $(function(){ $('#username').editable({
        url: '/post',
        title: 'Enter username' });
}); </script>
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 另外一种就是使用bootstrap table动态添加的,但是select类型就会出现数据为Empty的情况。
$('#db_dependences').bootstrapTable({
        method:'POST',
        dataType:'json',
        contentType: "application/x-www-form-urlencoded",
        cache: false,
        striped: true, //是否显示行间隔色 sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*) showColumns:true,
        pagination:true,
        minimumCountColumns:2,
        pageNumber:1, //初始化加载第一页,默认第一页 pageSize: 10, //每页的记录行数(*) pageList: [10, 15, 20, 25], //可供选择的每页的行数(*) uniqueId: "id", //每一行的唯一标识,一般为主键列 showExport: true,                    
        exportDataType: 'all',
        exportTypes:[ 'csv', 'txt', 'sql', 'doc', 'excel', 'xlsx', 'pdf'], //导出文件类型 onEditableSave: function (field, row, oldValue, $el) { $.ajax({
                success: function (data, status) { if (status == "success") {
                        alert("编辑成功");
                    }
                },
                error: function () { alert("Error");
                },
                complete: function () { }
            });
        },
        data: [{
            id: 1,
            name: '张三',
            sex: '男',
            time: '2017-08-09' }, {
            id: 2,
            name: '王五',
            sex: '女',
            time: '2017-08-09' }, {
            id: 3,
            name: '李四',
            sex: '男',
            time: '2017-08-09' }, {
            id: 4,
            name: '杨朝来',
            sex: '男',
            time: '2017-08-09' }, {
            id: 5,
            name: '蒋平',
            sex: '男',
            time: '2017-08-09' }, {
            id: 6,
            name: '唐灿华',
            sex: '男',
            time: '2017-08-09' }],
        columns: [{
            field: 'id',
            title: '序号' }, {
            field: 'name',
            title: '姓名',
            editable: {
                type: 'text',  
                validate: function (value) { if ($.trim(value) == '') { return '姓名不能为空!';  
                    }  
                }
            } 
        }, {
            field: 'sex',
            title: '性别',
            editable: {
                type: 'select',
                pk: 1,
                source: [
                    {value: 1, text: '男'},
                    {value: 2, text: '女'},
                ]
            }
        },  {
            field: 'time',
            title: '时间',
            editable: {
                type: 'date',
                format: 'yyyy-mm-dd',    
                viewformat: 'yyyy-mm-dd',    
                datepicker: {
                    weekStart: 1 }
            } 
        }]
    });
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101

结果图如下:

这里写图片描述

由于开源,很快就找到原因,由于formatter我们没有写这个function导致调用的默认的formatter,默认的没有把表格的值传入html中,bootstrap-table-editable.js源码如下,初始定义_dont_edit_formatter为false,我们没有实现noeditFormatter的function就会执行第二个if语句,其中的标签中没有对内容赋值,导致最后显示结果为它默认的Empty:

column.formatter = function(value, row, index) { var result = column._formatter ? column._formatter(value, row, index) : value;

                $.each(column, processDataOptions);

                $.each(editableOptions, function(key, value) {
                    editableDataMarkup.push(' ' + key + '="' + value + '"');
                }); var _dont_edit_formatter = false; if (column.editable.hasOwnProperty('noeditFormatter')) {
                    _dont_edit_formatter = column.editable.noeditFormatter(value, row, index);
                } if (_dont_edit_formatter === false) { return ['<a href="javascript:void(0)"', ' data-name="' + column.field + '"', ' data-pk="' + row[that.options.idField] + '"', ' data-value="' + result + '"',
                        editableDataMarkup.join(''), '>' + '</a>' ].join('');
                } else { return _dont_edit_formatter;
                }

            };
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

由于要实现多样式,则把上面的代码改变,并在使用的时候实现noeditFormatter:function(value){…}就是了。将上面的代码改为如下(此为我自己改的,你可以根据自己的需要做修改):

column.formatter = function(value, row, index) { var result = column._formatter ? column._formatter(value, row, index) : value;

                $.each(column, processDataOptions);

                $.each(editableOptions, function(key, value) {
                    editableDataMarkup.push(' ' + key + '="' + value + '"');
                }); var _dont_edit_formatter = false; if (column.editable.hasOwnProperty('noeditFormatter')) { var process = column.editable.noeditFormatter(value, row, index); if(!process.hasOwnProperty('class')){
                        process.class = '';
                    } if(!process.hasOwnProperty('style')){
                        process.style = '';
                    }
                    _dont_edit_formatter = ['<a href="javascript:void(0)"', ' data-name="'+process.filed+'"', ' data-pk="1"', ' data-value="' + process.value + '"', ' class="'+process.class+'" style="'+process.style+'"', '>' + process.value + '</a>' ].join('');
                } if (_dont_edit_formatter === false) { return ['<a href="javascript:void(0)"', ' data-name="' + column.field + '"', ' data-pk="' + row[that.options.idField] + '"', ' data-value="' + result + '"',
                        editableDataMarkup.join(''), '>' + value + '</a>' ].join('');
                } else { return _dont_edit_formatter;
                }

            };
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

结果如下:

这里写图片描述

这里写图片描述

然后是bootstrap table的使用js文件,在其中实现noeditFormatter函数。返回的result必须包含filed和value,class和style可以不需要,class可以额外用其它插件之类,比如badge,style是增加样式(背景,颜色,字体等)。

$('#db_dependences').bootstrapTable({
        method:'POST',
        dataType:'json',
        contentType: "application/x-www-form-urlencoded",
        cache: false,
        striped: true, //是否显示行间隔色 sidePagination: "client", //分页方式:client客户端分页,server服务端分页(*) showColumns:true,
        pagination:true,
        minimumCountColumns:2,
        pageNumber:1, //初始化加载第一页,默认第一页 pageSize: 10, //每页的记录行数(*) pageList: [10, 15, 20, 25], //可供选择的每页的行数(*) uniqueId: "id", //每一行的唯一标识,一般为主键列 showExport: true,                    
        exportDataType: 'all',
        exportTypes:[ 'csv', 'txt', 'sql', 'doc', 'excel', 'xlsx', 'pdf'], //导出文件类型 onEditableSave: function (field, row, oldValue, $el) { $.ajax({
                success: function (data, status) { if (status == "success") {
                        alert("编辑成功");
                    }
                },
                error: function () { alert("Error");
                },
                complete: function () { }
            });
        }, //      onEditableHidden: function(field, row, $el, reason) { // 当编辑状态被隐藏时触发 //          if(reason === 'save') { //              var $td = $el.closest('tr').children(); //          //    $td.eq(-1).html((row.price*row.number).toFixed(2)); //          //    $el.closest('tr').next().find('.editable').editable('show'); //编辑状态向下一行移动 //          } else if(reason === 'nochange') { //              $el.closest('tr').next().find('.editable').editable('show'); //          } //      }, data: [{
            id: 1,
            name: '张三',
            sex: '男',
            time: '2017-08-09' }, {
            id: 2,
            name: '王五',
            sex: '女',
            time: '2017-08-09' }, {
            id: 3,
            name: '李四',
            sex: '男',
            time: '2017-08-09' }, {
            id: 4,
            name: '杨朝来',
            sex: '男',
            time: '2017-08-09' }, {
            id: 5,
            name: '蒋平',
            sex: '男',
            time: '2017-08-09' }, {
            id: 6,
            name: '唐灿华',
            sex: '男',
            time: '2017-08-09' }, {
            id: 7,
            name: '马达',
            sex: '男',
            time: '2017-08-09' }, {
            id: 8,
            name: '赵小雪',
            sex: '女',
            time: '2017-08-09' }, {
            id: 9,
            name: '薛文泉',
            sex: '男',
            time: '2017-08-09' }, {
            id: 10,
            name: '丁建',
            sex: '男',
            time: '2017-08-09' }, {
            id: 11,
            name: '王丽',
            sex: '女',
            time: '2017-08-09' }],
        columns: [{
            field: 'id',
            title: '序号' }, {
            field: 'name',
            title: '姓名',
            editable: {
                type: 'text',  
                validate: function (value) { if ($.trim(value) == '') { return '姓名不能为空!';  
                    }  
                }
            } 
        }, {
            field: 'sex',
            title: '性别',
            editable: {
                type: 'select',
                pk: 1,
                source: [
                    {value: 1, text: '男'},
                    {value: 2, text: '女'},
                ],
                noeditFormatter: function (value,row,index) { var result={filed:"sex",value:value,class:"badge",style:"background:#333;padding:5px 10px;"}; return result;
                }
            }
        },  {
            field: 'time',
            title: '时间',
            editable: {
                type: 'date',
                format: 'yyyy-mm-dd',    
                viewformat: 'yyyy-mm-dd',    
                datepicker: {
                    weekStart: 1 },
                noeditFormatter: function (value,row,index) { var result={filed:"time",value:value,class:"badge",style:"background:#333;padding:5px 10px;"}; return result;
                }
            } 
        }]
    });
    
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143

关于bootstrap table的导出及使用可以看我另外一篇博客

下载和引用

下载x-editable,并如下引用。

<link href="js/bootstrap_above/x-editable-develop/dist/bootstrap-editable/css/bootstrap-editable.css" rel="stylesheet"> <script src="js/bootstrap_above/x-editable-develop/dist/bootstrap-editable/js/bootstrap-editable.js"></script> <script src="js/bootstrap_above/bootstrap-table-develop/dist/extensions/editable/bootstrap-table-editable.js"></script>
    
  • 1
  • 2
  • 3

然后讲上诉的一些文件修改添加,就完成了。

另外项目的结果展示

这里写图片描述

这里写图片描述

其中的样式都是自行在x-editable的基础上添加的。如配置出问题,以下是源码链接。

蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


HTML2.1表单标签及属性介绍

seo达人

如果您想订阅本博客内容,每天自动发到您的邮箱中, 请点这里

<!DOCTYPE html>

<html>

   <head>

       <meta charset="UTF-8">

       <title>表单标签及属性介绍</title>

   </head>

   <body>

   <!--form:表单标签,在html页面创建一个表单(浏览器上不显示),若要提交数据到服务器则负责收集数据的标签要放到form内 ;-->

       <!--action:(确定表单提交的路径);-->

       <!--method提交方式:get(默认值)有内容 ,post没有-->

       <form action="#" method="get">


           <!--input:输入域标签,获取用户输入信息;-->

           <!--type值不同收集方式不同:hidden(隐藏字段,数据会发送到服务器但浏览器不显示),text(文本框),password(密码框),radio(单选框),checkbox(复选框),

               file(文件上传组件),submit(提交按钮),button(普通按钮),reset(重置按钮);-->

           <!--name:元素名(表单数据需提交到服务器必提供name属性值),服务器通过属性值获取提交数据;-->

           <!--readonly:只读-->

           <!--value:设置input默认值。submit和reset为按键上显示数据-->

           <!--size:大小-->

           <!--maxlength:允许输入的最大长度-->

           隐藏字段:<input type="hidden" name="id" value=""/><br/>

           用户名:<input type="text" name="username" readonly="readonly" value="zhangsan" size="40px" maxlength="20"/><br/>

           密码:<input type="password" name="password"/><br/>

           确认密码:<input type="password" name="repassword"/><br/>

           性别:<input type="radio" name="sex" value="man"/>男

           <input type="radio" name="sex" value="woman"/>女<br/>

           爱好:<input type="checkbox" name="hobby" value="钓鱼"/>钓鱼

           <input type="checkbox" name="hobby" value="打电动"/>打电动

           <!--checked:单选或复选框默认勾选-->

           <input type="checkbox" name="hobby" value="画画" checked="checked"/>画画<br/>

           头像:<input type="file" /><br/>

           <!--select:下拉列表标签-->

           籍贯:<select name="province">

               <!--option:子标签,下拉列表中的一个选项-->

               <option>---请选择---</option>

               <!--value:发送得服务器的选项值-->

               <option value="北京">北京</option>

               <option value="上海">上海</option>

               <!--selected:勾选当前列表项-->

               <option value="广州" selected="selected">广州</option>

           </select><br/>

           自我介绍:

               <!--textarea:文本域-->

               <textarea>


               </textarea><br/>

           提交按钮:<input type="submit" value="注册"/><br/>

           普通按钮:<input type="button" value="普通按钮"><br/>

           重置按钮:<input type="reset"/>

       </form>

   </body>

</html>


蓝蓝设计www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 平面设计服务


日历

链接

个人资料

蓝蓝设计的小编 http://www.lanlanwork.com

存档