观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

前言

  此篇博客简略介绍android sdk自带的一些特别好用但是常常忘记的组件。常用的TextView、Button、ImageView和几个常用布局就不介绍了

标题栏组件

<androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:title="@string/forget_password"//标题文字
        app:titleTextAppearance="@style/TitleText"//设置标题文字风格
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">
    </androidx.appcompat.widget.Toolbar>
<style name="TitleText" parent="TextAppearance.Widget.AppCompat.Toolbar.Title">
        <item name="android:color">@color/colorWhite</item>
        <item name="android:textSize">20dp</item>
    </style>

滚动组件

        <ScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></ScrollView>

横向滚动组件

注意点:

1.滚动布局下,只能包含一个子布局,但是子布局下面可以包含多个布局。

主要api

<HorizontalScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal">

                <ImageView
                    android:layout_width="200dp"
                    android:layout_height="200dp"
                    android:background="#ff00ff" />

                <ImageView
                    android:layout_width="200dp"
                    android:layout_height="200dp"
                    android:background="#000000" />

                <ImageView
                    android:layout_width="200dp"
                    android:layout_height="200dp"
                    android:background="#b7a500" />
            </LinearLayout>
        </HorizontalScrollView>

 

网格列表组件

更详细的博客

<GridView
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:horizontalSpacing="1dp"
        android:numColumns="3"
        android:verticalSpacing="1dp">
    </GridView>

常用的属性:

android:numColumns="auto_fit" ,GridView的列数设置为自动

android:columnWidth="90dp",每列的宽度,也就是Item的宽度

android:stretchMode="columnWidth",缩放与列宽大小同步

android:verticalSpacing="10dp",两行之间的边距

android:horizontalSpacing="10dp",两列之间的边距

例子1 使用ArrayAdapter:

List<String> stringList = new ArrayList<>();
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<>(this,R.layout.text_parent_select_item,stringList);
gridView.setAdapter(arrayAdapter);
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/name"
    android:layout_width="75dp"
    android:layout_height="37dp"
    android:textSize="@dimen/font_size_16"
    android:textColor="@color/fontBlack1"
    android:gravity="center"
    android:maxLines="1"
    android:background="@drawable/bg_orange_edge_rectangle">

</TextView>

例子2 使用SimpleAdapter:

Activity类

public class MainActivity extends Activity {
    private GridView gridView;
    private List<Map<String, Object>> dataList;
    private SimpleAdapter adapter;
    //如果只有TextView 可以考虑使用ArrayAdapter 适配器,当然你也可以自定义适配器

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        gridView = (GridView) findViewById(R.id.gridview);
        //初始化数据
        initData();

        String[] from={"img","text"};

        int[] to={R.id.img,R.id.text};

        adapter=new SimpleAdapter(this, dataList, R.layout.gridview_item, from, to);

        gridView.setAdapter(adapter);

        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
            AlertDialog.Builder builder= new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("提示").setMessage(dataList.get(arg2).get("text").toString()).create().show();
            }
        });
    }

    void initData() {
        //图标
        int icno[] = { R.drawable.i1, R.drawable.i2, R.drawable.i3,
                R.drawable.i4, R.drawable.i5, R.drawable.i6, R.drawable.i7,
                R.drawable.i8, R.drawable.i9, R.drawable.i10, R.drawable.i11, R.drawable.i12 };
        //图标下的文字
        String name[]={"时钟","信号","宝箱","秒钟","大象","FF","记事本","书签","印象","商店","主题","迅雷"};
        dataList = new ArrayList<Map<String, Object>>();
        for (int i = 0; i <icno.length; i++) {
            Map<String, Object> map=new HashMap<String, Object>();
            map.put("img", icno[i]);
            map.put("text",name[i]);
            dataList.add(map);
        }
    }

} 


GridView主布局文件activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#000"
    tools:context="com.example.l7.MainActivity" >
    <GridView
        android:id="@+id/gridview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:columnWidth="80dp"
        android:stretchMode="spacingWidthUniform"
        android:numColumns="3"
         />
</LinearLayout>
列表项布局gridview_item.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:id="@+id/img"
        android:layout_width="60dp"
        android:layout_height="60dp"
        android:layout_marginTop="10dp"
        android:src="@drawable/ic_launcher" />
    <TextView
        android:id="@+id/text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="2dp"
        android:layout_gravity="center"
        android:textColor="#FFF"
        android:text="文字"
        />

</LinearLayout>

格外注意!如果你是滚动布局(ListView、ScrollView等等)包裹GridView,就出现不会自动换行的问题。这个时候需要你如下自定义view。

    package com.weijie.app_user.activity.order;  
      
    import android.content.Context;  
    import android.util.AttributeSet;  
    import android.widget.GridView;  
      
    public class MyGridView extends GridView {  
      
         public MyGridView(Context context, AttributeSet attrs) {   
                super(context, attrs);   
            }   
      
            public MyGridView(Context context) {   
                super(context);   
            }   
      
            public MyGridView(Context context, AttributeSet attrs, int defStyle) {   
                super(context, attrs, defStyle);   
            }   
      
            @Override   
            public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {   
      
                int expandSpec = MeasureSpec.makeMeasureSpec(   
                        Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);   
                super.onMeasure(widthMeasureSpec, expandSpec);   
            }   
    }  

网格布局

更详细的博客

本身属性

  • android:alignmentMode
  • 说明:当设置alignMargins,使视图的外边界之间进行校准。可以取以下值:
  • alignBounds – 对齐子视图边界。
  • alignMargins – 对齐子视距内容。
  • android:columnCount
  • 说明:GridLayout的最大列数
  • android:rowCount
  • 说明:GridLayout的最大行数
  • android:columnOrderPreserved
  • 说明:当设置为true,使列边界显示的顺序和列索引的顺序相同。默认是true。
  • android:orientation
  • 说明:GridLayout中子元素的布局方向。有以下取值:
  • horizontal – 水平布局。
  • vertical – 竖直布局。
  • android:rowOrderPreserved
  • 说明:当设置为true,使行边界显示的顺序和行索引的顺序相同。默认是true。
  • android:useDefaultMargins
  • 说明: 当设置ture,当没有指定视图的布局参数时,告诉GridLayout使用默认的边距。默认值是false。

子元素属性

  • android:layout_column
    说明:显示该子控件的列,例如android:layout_column=”0”,表示当前子控件显示在第1列,android:layout_column=”1”,表示当前子控件显示在第2列。
  • android:layout_columnSpan
    说明:该控件所占的列数,例如android:layout_columnSpan=”2”,表示当前子控件占两列。

  • android:layout_row
    说明:显示该子控件的行,例如android:layout_row=”0”,表示当前子控件显示在第1行,android:layout_row=”1”,表示当前子控件显示在第2行。

  • android:layout_rowSpan
    说明:该控件所占的列数,例如android:layout_rowSpan=”2”,表示当前子控件占两行。

  • android:layout_columnWeight
    说明:该控件的列权重,与android:layout_weight类似,例如有GridLayout上两列,都设置android:layout_columnWeight = “1”,则两列各占GridLayout宽度的一半

  • android:layout_rowWeight
    说明:该控件的行权重,原理同android:layout_columnWeight。
<GridLayout
       android:layout_width="match_parent"
       android:layout_height="match_parent"></GridLayout>

表格布局

适合在桌面这种需要显示多个图标功能的情况下使用,所以别用ListView套GridView了,会麻烦死的。

<TableRow></TableRow> 为列表行

更详细的博客

<TableLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></TableLayout>
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TableRow >
        <Button
            android:id="@+id/button01"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮1"      
        ></Button>
        <Button
            android:id="@+id/button02"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮2"      
        ></Button>
        <Button
            android:id="@+id/button03"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮3"      
        ></Button>
    </TableRow>

    <TableRow >
        <Button
            android:id="@+id/button04"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮4"      
        ></Button>
        <Button
            android:id="@+id/button05"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮5"      
        ></Button>
        <Button
            android:id="@+id/button06"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮6"      
        ></Button>
    </TableRow>

    <TableRow >
        <Button
            android:id="@+id/button07"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮7"      
        ></Button>
        <Button
            android:id="@+id/button08"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮8"      
        ></Button>
        <Button
            android:id="@+id/button09"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="按钮9"      
        ></Button>
    </TableRow>    
</TableLayout>

 

多媒体控制器组件

更详细的博客

有快进,快退,进度条

<MediaController
            android:layout_width="match_parent"
            android:layout_height="match_parent"></MediaController>

标签栏组件

更详细的博客

<TabHost
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></TabHost>

选项卡组件(配合标题栏组件一起使用)

更详细的博客

<TabWidget
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></TabWidget>

TabLayout页面切换布局

  <com.google.android.material.tabs.TabLayout
                    android:id="@+id/table"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content">

                    <com.google.android.material.tabs.TabItem
                        android:id="@+id/into"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="到校"/>

                    <com.google.android.material.tabs.TabItem
                        android:id="@+id/out"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="离校"/>   
//常用的属性
app:tabIndicatorColor :指示线的颜色 app:tabIndicatorHeight :指示线的高度 app:tabSelectedTextColor : tab选中时的字体颜色
app:tabTextColor="@color/colorPrimary" :未选中字体颜色
app:tabBackground="color" :整个tablayout颜色 app:tabMode="scrollable" : 默认是fixed,固定的;scrollable:可滚动的

也可以在代码上添加子项

tabLayout.addTab(tabLayout.newTab());

用Tablayout属性写一个style,给需要的Tablayout引用:

    <style name="MyTablayoutstyle" parent="Base.Widget.Design.TabLayout">
        <item name="tabBackground">@color/white</item>
        <item name="tabIndicatorColor">@color/green</item>
        <item name="tabIndicatorHeight">2dp</item>
        <item name="tabSelectedTextColor">@color/green</item>
        <item name="android:textSize">15sp</item>
        <item name="android:textColor">@color/text</item>
    </style>

Tablayout引用:

  <android.support.design.widget.TabLayout
        android:id="@+id/tab1"
        style="@style/MyTablayoutstyle"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

去掉指示线:

给tabIndicatorHeight属性设置0dp,或者给tabSelectedTextColor属性设置透明,就不显示指示线了

添加图标:
tabLayout.getTabAt(i).setText(titles[i]).setIcon(pics[i]);

添加自定义布局:

tabLayout2.getTabAt(i).setCustomView(makeTabView(i));

按键监听:

tabLayout.setOnTabSelectedListener(newTabLayout.OnTabSelectedListener() {
@Override
public voidonTabSelected(TabLayout.Tab tab) {
//选中了tab的逻辑
}
@Override
public voidonTabUnselected(TabLayout.Tab tab) {
//未选中tab的逻辑
}
@Override
public voidonTabReselected(TabLayout.Tab tab) {
//再次选中tab的逻辑
}
});

Spinner下拉列表选择框组件

    <Spinner
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:entries="@array/books"
        android:popupBackground="#66ccff"
        android:dropDownWidth="230dp"></Spinner>
public class MainActivity extends AppCompatActivity {
    Spinner spinner;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //获取界面布局文件的Spinner组件
        spinner= (Spinner) findViewById(R.id.spinner);
        String[] arr={"孙悟空","猪八戒","唐僧"};
        //创建ArrayAdapter对象
        ArrayAdapter<String> adapter=new ArrayAdapter<String>(this,android.R.layout.simple_list_item_multiple_choice,arr);
        spinner.setAdapter(adapter);
     String spinnerContent =(String)spinner.getSelectedItem();//获取选中的内容

    spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
      Override
      public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        //选中回调

      }

      @Override
      public void onNothingSelected(AdapterView<?> parent) {
        //未选中回调

      }
    });

    }
}

列表内容下拉扩展组件

其实就是 ListView 加上 下拉列表框 功能的二合一

更详细的博客

 <ExpandableListView
        android:id="@+id/ev_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorWhite"
        android:divider="@null"
        android:groupIndicator="@null"
        android:cacheColorHint="#00000000"
        android:listSelector="#00000000" />

快速关联联系人组件(快速添加到联系人或者获取信息)

更详细的博客

    <QuickContactBadge 
        android:id="@+id/badge"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:src="@drawable/zgdx"/>

图片按钮组件

      <ImageButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@mipmap/ic_phone_book"/>

文本切换组件(支持有动画切换)

文字也要有切换动画才够酷炫!

更详细的博客 

        <TextSwitcher
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"></TextSwitcher>

图片切换组件(支持有动画切换)

有动画切换图片了,肯定更加酷炫

更详细的博客

根据滑动方向切换图片

<ImageSwitcher
            android:layout_width="match_parent"
            android:layout_height="match_parent"></ImageSwitcher>

视频切换组件(支持有动画切换)

是的,三兄弟到齐了,为了切换动画!

更详细的博客,3种切换一起说明

       <ViewSwitcher
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"></ViewSwitcher>

图片轮播组件

你天天逛的淘宝,上面的让你心动的物品图片轮播,就是这种效果

  AdapterViewAnimator支持的XML属性如下:

  • android:animateFirstView:设置显示组件的第一个View时是否使用动画。

  • android:inAnimation:设置组件显示时使用的动画。

  • android:loopViews:设置循环到最后一个组件时是否自动跳转到第一个组件。

  • android:outAnimation:设置组件隐藏时使用的动画。

<AdapterViewFlipper
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"></AdapterViewFlipper>

Switch滑动按钮组件

一键双状态,但是是滑动开关图标的样子

<!--滑动按钮-->
    <Switch
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

textOn:控件打开时显示的文字 
textOff:控件关闭时显示的文字 
thumb:控件开关的图片 
track:控件开关的轨迹图片 
typeface:设置字体类型 
switchMinWidth:开关最小宽度 
switchPadding:设置开关 与文字的空白距离 
switchTextAppearance:设置文本的风格 
checked:设置初始选中状态 
splitTrack:是否设置一个间隙,让滑块与底部图片分隔(API 21及以上) 
showText:设置是否显示开关上的文字(API 21及以上)

SwitchCompat滑动按钮组件

自定义背景

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_checked="true">
        <shape android:shape="rectangle">
            <corners android:radius="15dp"/>
            <solid android:color="@color/color_FF5E27"/>
        </shape>
    </item>
    <item
        android:state_checked="false" >
        <shape android:shape="rectangle">
            <corners android:radius="15dp"/>
            <solid android:color="@color/gray99"/>
        </shape>
    </item>

</selector>

设置

app:track="@drawable/selected_switch"

自定义点thumb

<?xml version="1.0" encoding="utf-8"?>
<!-- 按钮的选择器,可以设置按钮在不同状态下的时候,按钮不同的颜色 -->
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    
<item android:state_checked="true"  android:drawable="@drawable/green_thumb" />
<item                               android:drawable="@drawable/gray_thumb" />
</selector>
 android:thumb="@drawable/dot"

叠堆组件

类似图片叠放在一起的效果

 <StackView
        android:layout_width="100dp"
        android:layout_height="100dp"></StackView>

单选按钮

<RadioButton
    android:id="@+id/sick_leave"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginRight="23dp"
    android:background="@drawable/bg_btn_selector_tow"
    android:button="@null"
    android:gravity="center"
    android:minWidth="80dp"
    android:minHeight="40dp"
    android:text="病假"
    android:textSize="@dimen/font_size_14"
    android:textColor="@color/fontWhite" />

android:button="@null"这条语句将原来系统的RadioButton图标给隐藏起来。

单选按钮组

只能在多个选择里,选中一个的按钮组件,选择一个后,另外一个选中的会自动取消

<!--单选按钮组-->
    <RadioGroup
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:checkedButton="@id/a">
        <!--android:checkedButton="@id/a" 默认选择值-->
        <RadioButton
            android:id="@+id/a"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="A"/>
        <RadioButton
            android:id="@+id/b"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="B"/>
    </RadioGroup>

代码上添加默认选中值

((RadioButton)radioGroup.getChildAt(0)).setChecked(true);

获取选中的值

selectData.getCheckedRadioButtonId();

复选框组件

<CheckBox
        android:id="@+id/check_agreement"
        android:text="我已阅读并同意"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="true"//默认选中状态
    />
mCheckAgreement = (CheckBox)findViewById(R.id.check_agreement);
        mCheckAgreement.isChecked();//查询当前选中状态
        mCheckAgreement.setChecked(true);//设置默认
        mCheckAgreement.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                L.e("点击状态"+isChecked);
            }
        });

替换选择图片:

ic_checkbox.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/ic_round_check_orange" android:state_checked="true"></item>
    <item android:drawable="@drawable/ic_round_check_gray" android:state_checked="false"></item>

</selector>
<!--在styles.xml文件里添加   checkbox的图片风格-->
    <style name="loginCheckbox" parent="@android:style/Widget.CompoundButton.CheckBox">
        <item name="android:button">@drawable/ic_checkbox</item>
    </style>
<CheckBox
        android:id="@+id/check_agreement"
        android:text="我已阅读并同意"
        android:textColor="@color/colorGray3"
        android:textSize="@dimen/font_size_14"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:checked="true"
        style="@style/loginCheckbox"/>

带文字的复选框组件(可能已经废弃了,使用上面的复选框一样可以带文字)

什么?你还在用TextView在加CheckBox实现复选框功能?快使用带文字的复选框试试吧,优点比CheckBox 有更大的点击范围,点击文字也可以支持勾选,用户操作上更舒服。

<CheckedTextView
                    android:layout_width="wrap_content"
                    android:layout_height="?android:attr/listPreferredItemHeightSmall"
                    android:textAppearance="?android:attr/textAppearanceListItemSmall"
                    android:gravity="center_vertical"
                    android:drawableLeft="?android:attr/listChoiceIndicatorMultiple"
                    android:checkMark="?android:attr/listChoiceIndicatorMultiple"
                    android:focusableInTouchMode="true"//在触摸模式下可聚焦,触摸就选中
                    android:filterTouchesWhenObscured="true"//遮挡时过滤触摸
                    android:text="@string/order" />

其中:android:drawableLeft控制显示在左边,checkMark控制显示在右边。
?android:attr/listChoiceIndicatorMultiple 表示复选框,?android:attr/listChoiceIndicatorSingle表示单选框

mCheckAgreement.setChecked(true);//设置默认选中
mCheckAgreement.isChecked();//查看选中状态

 

设置选着框的样式:
selector必须要使用drawable,不能使用color,否者会报xml错误

//incompetence_item_selector  xml名称
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:drawable="@drawable/uncheck" android:state_enabled="true" android:state_focused="true" android:state_pressed="false" />
    <item android:drawable="@drawable/check" android:state_enabled="true" android:state_pressed="true"  />
    <item android:drawable="@drawable/check" android:state_checked="true" android:state_enabled="true" />
    <item android:drawable="@drawable/uncheck" />

</selector>

 

    <CheckedTextView
        android:id="@+id/incompetence_item_ctv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:button="@null"
        android:ellipsize="marquee"
        android:filterTouchesWhenObscured="true"
        android:focusableInTouchMode="true"
        android:gravity="center_vertical"
        android:padding="@dimen/padding_size_two"
        android:text="CheckedTextView 注意事项" />

设置背景的selector一定要在代码里面设置,不能再xml中设置:

incompetence_item_ctv.setCheckMarkDrawable(R.drawable.incompetence_item_selector)

双向开关组件ToggleButton

跟你家里的灯的开关按钮一样,它一个按键支持两种状态

 <!--双向开关按钮组件-->
   <ToggleButton
        android:id="@+id/btn_offAndOn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textOff="关闭功能"
        android:textOn="启用功能"/>
mBtn = (ToggleButton)findViewById(R.id.btn_offAndOn);
mBtn.setOnClickListener(this);
@Override
    public void onClick(View view) {
        switch (view.getId()){
           case R.id.btn_offAndOn:
                Intent intent = new Intent(MainActivity.this,PhoneServer.class);
                if (mBtnWiFiAP.isChecked()){
                    startService(intent);
                }else {
                    stopService(intent);
                }
                break;
            default:
                break;
        }

所属专用适配器

public class GuideAdapter extends PagerAdapter {
    private List<Integer> mImageIdList = new ArrayList<>();
    private View mLastPageView;

    public GuideAdapter(List<Integer> imageIdList,View lastPageView){
        mImageIdList.clear();
        this.mImageIdList.addAll(imageIdList);
        this.mLastPageView = lastPageView;

    }
    @Override
    public int getCount() {
        if (mLastPageView == null){
            return mImageIdList.size();
        }else {
            return mImageIdList.size()+1;
        }
    }

    @Override
    public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
        return view == object;
    }

    @NonNull
    @Override
    public Object instantiateItem(@NonNull ViewGroup container, int position) {
        L.e("position="+position);
        L.e("getCount()="+getCount());
        if (position == getCount()-1 && mLastPageView != null){ //判断是不是最后一页,如果是就导入一个带有按键的布局
            container.addView(mLastPageView);
            return mLastPageView;
        }else { //如果不是就使用一个ImageView填充
            ImageView imageView = new ImageView(container.getContext());
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setImageResource(mImageIdList.get(position));
            container.addView(imageView);
            return imageView;
        }

    }

    @Override
    public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
        container.removeView((View)object);
    }

}

视图翻页的兄弟ViewFlipper(快速翻页)

这是一个需要创建适配器的View,最常用的场景是在图库里的图片浏览界面,翻页方式为快速拖动

更详细的博客

<ViewFlipper
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"></ViewFlipper>

自动补全文本框

更详细的博客

<MultiAutoCompleteTextView
           android:layout_width="match_parent"
           android:layout_height="match_parent" />

输入框自动提示组件

<AutoCompleteTextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

更详尽的博客

属性 对应方法 描述
android:completionHint setCompletionHint(CharSequence) 设置下拉菜单中的提示标题
android:completionHintView   设置下拉菜单中提示标题的视图
android:completionThreshold setThreshold(int) 设置用户至少输入几个字符才会显示提示。默认为 2 个
android:dropDownSelector   设置选中的item背景色
android:dropDownAnchor setDropDownAnchor(int id) 它的值是一个View的ID,指定后,AutoCompleteTextView会在这个View下弹出自动提示。
android:dropDownWidth   设置自动提示列表的宽度。
android:dropDownHeight   设置自动提示列表的高度。
原属性之外的几个常用方法
android:dropDownHorizontalOffest   设置下拉菜单与文本框之间的水平偏移,下拉菜单默认与文本框左对齐
adnroid:dropDownVerticalOffest   设置下拉菜单与文本框之间的垂直偏移,下拉菜单默认紧跟文本框
android:popupBackground setDropDownBackgroundResource(int) 设置下拉菜单的背景

评分组件(给产品快速评分)

        <RatingBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

ProgressBar进度条组件

         <!--默认圆环进度条-->
        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:max="100"/>

        <!--水平进度条-->
       <ProgressBar
           android:layout_width="200dp"
           android:layout_height="wrap_content"
           style="?android:attr/progressBarStyleHorizontal"
           android:max="100"/>
  • @android:style/Widget.ProgressBar.Horizontal:水平进度条(可以显示刻度,常用)。
  • @android:style/Widget.ProgressBar.Small:小进度条。
  • @android:style/Widget.ProgressBar.Large:大进度条。
  • @android:style/Widget.ProgressBar.Inverse:不断跳跃、旋转画面的进度条。
  • @android:style/Widget.ProgressBar.Large.Inverse:不断跳跃、旋转动画的大进度条。
  • @android:style/Widget.ProgressBar.Small.Inverse:不断跳跃、旋转动画的小进度条
  • android:max:设置进度的最大值。
  • android:progress:设置当前第一进度值。
  • android:secondaryProgress:设置当前第二进度值。
  • android:visibility:设置是否显示,默认显示。

自定义样式:

1.不确定样式(就是转圈)

android:indeterminateDrawable="" 也可以配置 <animation-list 属性的帧动画

android:indeterminateDrawable="@anim/pull_up_ic"
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@mipmap/ic_rolling"
    android:fromDegrees="0"
    android:toDegrees="650"
    android:pivotX="50%"
    android:pivotY="50%"
    android:visible="true"
    android:duration="3000"
    android:repeatCount="infinite">

</rotate>

2.进度条样式(可以设置正向和反向进度条)

style="@android:style/Widget.ProgressBar.Horizontal"
android:progressDrawable="@drawable/progress_bar"
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <color android:color="@color/colorGray5"/>
    </item>

    <item android:id="@android:id/secondaryProgress">
        <clip>
            <shape>
                <corners android:radius="5dp"/>
                <gradient
                    android:startColor="@color/colorGray5"
                    android:endColor="@color/colorGray5"/>
            </shape>
        </clip>
    </item>

    <item android:id="@android:id/progress">
        <clip
            android:clipOrientation="horizontal"
            android:gravity="right">
            <shape>
                <corners android:radius="5dp"/>
                <gradient
                    android:startColor="@color/colorDarkGreen"
                    android:endColor="@color/colorDarkGreen"/>
            </shape>
        </clip>
    </item>
</layer-list>

此样式为反向进度条,改变绘制方向的属性为android:gravity="right"

两个方向圆角

效果图

xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <color android:color="@android:color/transparent"/>
    </item>

    <item android:id="@android:id/secondaryProgress">
        <color android:color="@android:color/transparent"/>
    </item>

    <item android:id="@android:id/progress">
        <scale android:scaleWidth="100%"
            android:drawable="@drawable/main_progress_bar_ct"/>
    </item>
</layer-list>

main_progress_bar_ct.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <solid android:color="@color/main_color_BF6700" />
    <corners android:radius="10dp" />
</shape>

数字选择器组件(自定义选择器)

更详细的博客

<NumberPicker
           android:layout_width="match_parent"
           android:layout_height="match_parent"></NumberPicker>

日历组件

 <CalendarView
        android:layout_width="match_parent"
        android:layout_height="match_parent"></CalendarView>

计时器组件

<Chronometer
    android:id="@+id/cRecordPopTime"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center_horizontal"
    android:layout_marginBottom="@dimen/d24"
    android:fontFamily="sans-serif-light"
    android:textColor="@color/fontHint"
    android:textSize="@dimen/s13"
    tools:targetApi="jelly_bean" />
Chronometer mChronometer;
mChronometer.setOnChronometerTickListener(new Chronometer.OnChronometerTickListener() {
    @Override
    public void onChronometerTick(Chronometer cArg) {
        long time =System.currentTimeMillis() - cArg.getBase();
        Date d = new Date(time);
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss", Locale.US);
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        timeView.setText(sdf.format(d));
    }
});
timeView.setBase(System.currentTimeMillis());
timeView.start();

时间显示组件

<TextClock
    android:id="@+id/time"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:format24Hour="yyyy年MM月dd日 HH时mm分ss秒"
    android:format12Hour="yyyy年MM月dd日 hh时mm分ss秒"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"/>
android:format24Hour="HH:mm" HH为24小时格式
android:format12Hour="hh:mm" hh为12小时格式
如果你希望强制显示24小时格式可以将 format12Hour 里的时间设置HH,同理强制12小时可以相反设置
android:format12Hour="aa" 显示AM/PM 上午下午

 建议12小时和24小时格式都需要写上,否则会出现机器设置为12小时制,你设置为24小时制,导致年月日无法显示的问题。

<TextClock
    android:id="@+id/tc_eeee"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textColor="@color/white"
    android:format12Hour="EEEE"
    android:format24Hour="EEEE"
    android:textSize="16sp" /> 

EEEE是星期

setFormatHour(tc_hhmm,"hh:mm");//当前时钟
setFormatHour(tc_yyyymmdd,"yyyy年M月dd日");//年月日
setFormatHour(tc_eeee,"EEEE");//星期

时间选择器组件

<TimePicker
        android:id="@+id/tiem_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:timePickerMode="spinner"
        android:layout_gravity="center"
        android:numbersTextColor="@color/theme_color"
        android:scaleY="1.5"
        android:scaleX="1.5"/>
//时间值传入,并且设置修改时间选择器的时间显示
    public void timeDataInit(){
        Intent intent = getIntent();
        mHour = intent.getIntExtra(KEY_HOUR,-1);
        mMinute = intent.getIntExtra(KEY_MINUTE,-1);
        if(mHour != -1 && mMinute != -1){
            mTiemPicker.setCurrentHour(mHour);
            mTiemPicker.setCurrentMinute(mMinute);
        }else {
            Log.e("SelectionTiem","传入的时间值为空");
        }
    }

@Override
    public void initData() {
        //将时间选择器里的值传出
        mTiemPicker.setOnTimeChangedListener(new TimePicker.OnTimeChangedListener() {
            @Override
            public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
                mHour = hourOfDay;
                mMinute = minute;
            }
        });
    }

时间选择器对话框组件

new TimePickerDialog(this,new TimePickerDialog.OnTimeSetListener() {

            @Override
            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
                houre = hourOfDay;
                WuraoActivity.this.minute = minute;
                if (WuraoActivity.this.minute < 10){
                    endTimeTv.setText(houre+":"+"0"+WuraoActivity.this.minute);
                }else {
                    endTimeTv.setText(houre+":"+WuraoActivity.this.minute);
                }
            }
        }, 0, 0, true).show();

日期选择器组件

<DatePicker
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"></DatePicker>

日期选择器对话框组件

例子一:

/**
 * 日期选择
 * @param activity
 * @param themeResId
 * @param tv
 * @param calendar
 */
public static void showDatePickerDialog(Activity activity, int themeResId, final TextView tv, Calendar calendar) {
    new DatePickerDialog(activity , themeResId,new DatePickerDialog.OnDateSetListener() {
        @Override
        public void onDateSet(DatePicker view, int year,  int monthOfYear, int dayOfMonth) {
            // 此处得到选择的时间,可以进行你想要的操作
            tv.setText("您选择了:" + year + "年" + (monthOfYear+1)+ "月" + dayOfMonth + "日");

        }
    }
            // 设置初始日期
            , calendar.get(Calendar.YEAR)
            ,calendar.get(Calendar.MONTH)
            ,calendar.get(Calendar.DAY_OF_MONTH)).show();
}

例子二:

DatePickerDialog datePickerDialog = new DatePickerDialog(TStudentAttendanceActivity.this,new DatePickerDialog.OnDateSetListener() {
            @Override
            public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {

            }
        },2019,1,1);
        datePickerDialog.updateDate(2019,1,1);
        datePickerDialog.show();

 设置时间选择范围:

        DatePicker datePicker = mDatePickerDialog.getDatePicker();
        datePicker.setMaxDate(System.currentTimeMillis()-1000);//注意时间不能等于当前时间,否则会报错
        datePicker.setMinDate(1);   

 年月选择对话框(隐藏日期选择,修改分割线颜色)

public void showDatePickerDialog() {
        if (mDatePickerDialog == null) {
            mDatePickerDialog = new DatePickerDialog(TStudentAttendanceStatisticsActivity.this,DatePickerDialog.THEME_HOLO_LIGHT, new DatePickerDialog.OnDateSetListener() {//重点!DatePickerDialog.THEME_HOLO_LIGHT 这里是选择日期对话框风格
                @Override
                public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
                    Calendar calendar = Calendar.getInstance();
                    calendar.set(Calendar.YEAR,year);
                    calendar.set(Calendar.MONTH,month);
                    calendar.set(Calendar.DAY_OF_MONTH,dayOfMonth);
                    mCurrentTime = calendar.getTimeInMillis();

                }
            }, 2019,1,1);
        }
        mDatePickerDialog.setOnDismissListener(new DialogInterface.OnDismissListener() {
            @Override
            public void onDismiss(DialogInterface dialog) {

            }
        });
        DatePicker datePicker = mDatePickerDialog.getDatePicker();
        datePicker.setMaxDate(System.currentTimeMillis()-10);//设置最大选择日期
        ((ViewGroup) ((ViewGroup) datePicker.getChildAt(0)).getChildAt(0)).getChildAt(2).setVisibility(View.GONE);//隐藏日期
        setDatePickerDividerColor(datePicker);//修改分割线颜色
        mDatePickerDialog.updateDate(TimeUtil.getYear(mCurrentTime),TimeUtil.getMonth(mCurrentTime),TimeUtil.getDayOfMonth(mCurrentTime));
        mDatePickerDialog.show();
    }

    /**
     * 设置时间选择器的分割线颜色
     * @param datePicker
     */
    private void setDatePickerDividerColor(DatePicker datePicker) {
        // Divider changing:
        // 获取 mSpinners
        LinearLayout llFirst = (LinearLayout) datePicker.getChildAt(0);
        // 获取 NumberPicker
        LinearLayout mSpinners = (LinearLayout) llFirst.getChildAt(0);
        for (int i = 0; i < mSpinners.getChildCount(); i++) {
            NumberPicker picker = (NumberPicker) mSpinners.getChildAt(i);
            Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, new ColorDrawable(Color.parseColor("#fea239")));//设置分割线颜色
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (Resources.NotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
        }
    }

效果图:

视频播放组件

         <VideoView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

视频动画组件

更详细的博客

在Android中,ViewAnimatorFrameLayout的一个子类,用来做Views之间的切换。它是一个变换控件的
元素,帮助我们在Views之间(如TextView, ImageView或者其他layout)添加变换。它有助于在屏幕view添加动画。ViewAnimator可以在两个及以上Views上平滑的切换,通过合适动画,提供从一个View到另外一个View变换的方式。

        <ViewAnimator
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"></ViewAnimator>

视图存根组件

更详细的博客

要显示某些控件了,在加载,节省内存~   跟android:visibility="gone"属性说拜拜

        <ViewStub
           android:layout_width="wrap_content"
           android:layout_height="wrap_content" />

曲面视图  SurfaceView,SurfaceTexture,TextureView,

  首先SurfaceView, SurfaceTexture,TextureView都是为了实现单独刷新帧数的View(与UI线程的帧数无关).

  •   SurfaceView API 1.0 加入
  •   GLSurfaceView API 1.5加入
  •   SurfaceTexture API 11加入
  •   TextureView Android4.0(API level 14)加入

  

SurfaceView

  从Android 1.0(API level 1)时就有 。它继承自类View,因此它本质上是一个View。但与普通View不同的是,它有自己的Surface。我们知道,一般的Activity包含的多个View会组成View hierachy的树形结构,只有最顶层的DecorView,也就是根结点视图,才是对WMS可见的。这个DecorView在WMS中有一个对应的WindowState。而SurfaceView就是在Window上挖一个洞,它就是显示在这个洞里,其他的View是显示在Window上,所以View可以显示在 SurfaceView之上,你也可以添加一些层在SurfaceView之上。(例如在上面设置一些按钮控件)我们知道View的更新只能在UI线程中,所以使用自定义View没办法这么做,但是SurfaceView就可以了。它一个很好用的地方就是允许其他线程(不是UI线程)绘制图形(使用Canvas),根据它这个特性,你就可以控制它的帧数,你如果让这个线程1秒执行50次绘制,那么最后显示的就是50帧。(一般使用thread.sleep(20);代表一秒刷新50次)SurfaceView能够自己控制执行帧数的对象,这样可以弥补View的不足,因为有时候View的帧数太低了,这会导致画面效果不顺畅,影响体验效果。

  SurfaceView是在一个新起的单独线程中可以重新绘制画面,而View必须在UI的主线程中更新画面。那么在UI的主线程中更新画面 可能会引发问题,比如你更新画面的时间过长,那么你的主UI线程会被你正在画的函数阻塞。那么将无法响应按键,触屏等消息。当使用surfaceView 由于是在新的线程中更新画面所以不会阻塞你的UI主线程。但这也带来了另外一个问题,就是事件同步。比如你触屏了一下,你需要surfaceView中 thread处理,一般就需要有一个event queue的设计来保存touch event,这会稍稍复杂一点,因为涉及到线程同步。
所以基于以上,根据游戏特点,一般分成两类
1 被动更新画面的。比如棋类,这种用view就好了。因为画面的更新是依赖于 onTouch 来更新,可以直接使用 invalidate。 因为这种情况下,这一次Touch和下一次的Touch需要的时间比较长些,不会产生影响。
2 主动更新。比如一个人在一直跑动。这就需要一个单独的thread不停的重绘人的状态,避免阻塞main UI thread。所以显然view不合适,需要surfaceView来控制。
本质区别:
View:必须在UI的主线程中更新画面,用于被动更新画面。
surfaceView:UI线程和子线程中都可以。在一个新启动的线程中重新绘制画面,主动更新画面。

<SurfaceView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
       SurfaceHolder surfaceHolder = surfaceView.getHolder();
            surfaceHolder.addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(SurfaceHolder holder) {

                }

                @Override
                public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

                }

                @Override
                public void surfaceDestroyed(SurfaceHolder holder) {

                }
            });

 

SurfaceTexture

从Android 3.0(API level 11)加入。和SurfaceView不同的是,它对图像流的处理并不直接显示,而是转为GL外部纹理,因此可用于图像流数据的二次处理(如Camera滤镜,桌面特效等)。比如Camera的预览数据,变成纹理后可以交给GLSurfaceView直接显示,也可以通过SurfaceTexture交给TextureView作为View heirachy中的一个硬件加速层来显示。首先,SurfaceTexture从图像流(来自Camera预览,视频解码,GL绘制场景等)中获得帧数据,当调用updateTexImage()时,根据内容流中最近的图像更新SurfaceTexture对应的GL纹理对象,接下来,就可以像操作普通GL纹理一样操作它了。从下面的类图中可以看出,它核心管理着一个BufferQueue的Consumer和Producer两端。Producer端用于内容流的源输出数据,Consumer端用于拿GraphicBuffer并生成纹理。SurfaceTexture.OnFrameAvailableListener用于让SurfaceTexture的使用者知道有新数据到来。JNISurfaceTextureContext是OnFrameAvailableListener从Native到Java的JNI跳板。其中SurfaceTexture中的attachToGLContext()和detachToGLContext()可以让多个GL context共享同一个内容源。

TextureView

在4.0(API level 14)中引入。它可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。值得注意的是TextureView必须在硬件加速的窗口中它显示的内容流数据可以来自App进程或是远端进程。从类图中可以看到,TextureView继承自View,它与其它的View一样在View hierachy中管理与绘制。TextureView重载了draw()方法,其中主要把SurfaceTexture中收到的图像数据作为纹理更新到对应的HardwareLayer中(这句话是重点因为Camera2需要从TextureView里拿到SurfaceTexture)。SurfaceTexture.OnFrameAvailableListener用于通知TextureView内容流有新图像到来。SurfaceTextureListener接口用于让TextureView的使用者知道SurfaceTexture已准备好,这样就可以把SurfaceTexture交给相应的内容源。Surface为BufferQueue的Producer接口实现类,使生产者可以通过它的软件或硬件渲染接口为SurfaceTexture内部的BufferQueue提供graphic buffer。

更详细的博客

<TextureView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

使用TextureView需要开启硬件加速功能.开启硬件加速方法如下:

在AndroidManifest.xml 清单文件里,你需要实现相机功能的activity添加 android:hardwareAccelerated="true"

 

SurfaceTextureListener接口

 mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
                @Override
                public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
                    //可用
                    //此处一般加载内容,比如相机预览图像
                }

                @Override
                public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
                    //尺寸变化
                }

                @Override
                public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
                    //销毁
                    return false;
                }

                @Override
                public void onSurfaceTextureUpdated(SurfaceTexture surface) {
                    //更新

                }
            });

QuickContactBadge

关联联系人组件

      badge = (QuickContactBadge) findViewById(R.id.badge);
        
        // 指定联系人的电话号码
        // 先搜索该号码,如果没有则提醒是否添加到联系人
        // 第二个参数为延迟匹配,若为true,则直到被点击时才会查找该地址
        badge.assignContactFromPhone("15958455037", false); 

 

 

 

 

 

 

 

 

end

posted on 2018-08-15 10:45  观心静  阅读(918)  评论(0编辑  收藏  举报