RemoteControl应用介绍
来源:互联网 发布:mac 视频播放器推荐 编辑:程序博客网 时间:2024/06/05 01:59
本文介绍了RemoteControl应用,该应用来自《Android权威编程指南》一书。
RemoteControl简介
RemoteControl应用只有一个activity。应用界面的最顶端区域可以显示当前频道。下面紧接着的区域显示用户正在输入的新频道。点击Delete按钮可以清除输入区域的频道;点击Enter按钮可变换频道,即更新当前频道并清除输入区域的频道。
通过本应用可以学到的知识点:
- 自定义style样式、继承父类的style样式,并将样式加入到XML代码中;
- 自定义include标签以消除重复代码;
- 学习各种类型的drawable(state list drawable、shape drawable、layer list drawable、inset drawable、nine patch drawable),通过这些drawable给应用赋予一种全新的独特视觉体验。
本应用的效果图如下所示:
为相同的view定义style
由上图可以看出,屏幕的下面是button区域,用于输入不同的频道号,这些button都具有相同或相似的外观,不妨为button设置一个统一的样式,这样一来消除了重复的代码、是代码看起来更加简洁,二来方便后期维护。下面将结合代码对style样式做一介绍。
样式可用于适配各种UI控件,避免重复性编写具有相似控件属性的代码。样式定义在res/values/styles.xml文件中,该文件以resources标签为根标签,每一种样式均以style标签作为元素节点,节点内包含一个或多个item子节点,每个样式item都是以XML属性进行命名的,元素内的文字即为属性值。下面为每个button定义了一组统一的样式:
<!-- res/styles.xml --><!-- 用于定义样式及主题 --><style name="RemoteButton"> <item name="android:layout_width">0dp</item> <item name="android:layout_height">match_parent</item> <item name="android:textColor">@drawable/button_text_color</item> <item name="android:textSize">20sp</item> <item name="android:layout_margin">3dp</item> <item name="android:paddingTop">24dp</item> <item name="android:paddingBottom">24dp</item> <item name="android:background">@drawable/button_shape_shadowed</item> </style>
在上面的XML代码中,style标签的属性name=”RemoteButton”就是该样式的名字,当需要在其他XML代码中引用该样式,可使用下面的方式:
style="@style/RemoteButton"
在子标签item中定义了button的共同属性,其中name为该item的属性名,而元素内为属性值。
为了突出Delete按钮和Enter按钮,将这两个按钮的文字加粗,但其余属性不变,可以设置一个新的style样式”RemoteButtonBold”,该样式的parent属性指定为”RemoteButton”,表示样式”RemoteButtonBold”继承了”RemoteButton”样式的所有属性,同时还可以添加子样式特有的文字加粗属性:
<!-- 样式"RemoteButtonBold"继承了父样式"RemoteButton"的全部属性,并添加自己的特有属性android:textStyle --><style name="RemoteButtonBold" parent="RemoteButton"> <item name="android:textStyle">bold</item> </style>
XML drawable
Android把任何可绘制在屏幕上的图形称为 drawable。drawable是一种抽象的图形、一个继承drawable类的子类,或是一张位图图像。常见的drawable有state list drawable、shape drawable、layer list drawable、nine patch drawable。由于前三者通常定义在XML文件中,故统一将他们称为XML drawable类别。XML drawable有与像素密度无关的优良特性,故可以将他们定义在默认的res/drawable目录下。下面将结合代码说明这几种XML drawable。
注意到在上个小节中定义的style中,有两个特殊的item:
<!-- 自定义state list drawable;不同状态下View的状态不同 --><item name="android:textColor">@drawable/button_text_color</item><!-- 自定义layer list drawable;使View产生阴影效果 --><item name="android:background">@drawable/button_shape_shadowed</item>
以上代码通过引用drawable的方式(@drawable/)将名为”button_text_color”的XML文件引用进来,该文件就是定义在res/drawable目录下的XML drawable,由于该XML drawable负责指定处于点击与非点击状态下button的drawable,所以这个自定义的XML drawable属于state list drawable,”button_text_color”文件的内容如下:
<!-- button_text_color.xml --><!-- state list drawable --><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_pressed="false" android:color="#ffffff"></item> <item android:state_pressed="true" android:color="#556699"></item></selector>
state list drawable必须有一个selector作为根标签,每一个子标签item表示各个状态下button的表现形式。
第二个引用的drawable文件名为”button_shape_shadowed”,同样定义在res/drawable目录中,代码如下所示:
<!-- button_shape_shadowed.xml --><!-- layer list drawable --><layer-list xmlns:android="http://schemas.android.com/apk/res/android" > <item> <shape android:shape="rectangle" > <corners android:radius="5dp" /> <gradient android:angle="90" android:centerColor="#303339" android:centerY="0.05" android:endColor="#000000" android:startColor="#00000000" /> </shape> </item> <item> <inset android:drawable="@drawable/button_shape" android:insetBottom="5dp" /> </item></layer-list>
上面XML代码的根标签是layer-list,表示这是一个layer list drawable,该drawable主要用于使UI控件在不同状态切换时产生层次效果,使控件具有立体感,提高用户的交互体验。
每个子标签item中,都包含了一个drawable,并以从后至前的顺序进行排序,第二个drawable是一个inset drawable,其任务就是在已创建的drawable底部做5dp单位的位移,并刚好落在位移形成的阴影上,同时又引入了一个名为”button_shape”的drawable,该drawable是一个state list drawable,具体代码见本段文字的下面;第一个drawable是一个shape drawable,通过shape标签定义控件的形状,若不指定,系统将默认指定为rectangle,shape内的子标签corners和gradients分别定义了控件的四角圆滑半径和渐变色。
<!-- button_shape.xml --><!-- state list drawable --><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/button_shape_normal" android:state_pressed="false"></item> <item android:drawable="@drawable/button_shape_pressed" android:state_pressed="true"></item></selector>
button_shape.xml中的引用drawable:”button_shape_normal”和”button_shape_pressed”是两个shape drawable,定义如下:
<!-- button_shape_normal.xml --><!-- shape drawable --><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <corners android:radius="3dp" /> <gradient android:angle="90" android:endColor="#cccccc" android:startColor="#acacac" /></shape>
<!-- button_shape_pressed.xml --><!-- shape drawable --><shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" > <corners android:radius="3dp" /> <gradient android:angle="270" android:endColor="#cccccc" android:startColor="#acacac" /></shape>
引用style样式、引用include标签
将主activity(fragment)的布局以TableLayout为根标签,则每一行button可以由一个TableRow包含,即每个TableRow包含三个button,由于每一行的TableRow的布局都一样,故可以单独定义一个layout资源,最后通过include标签引入至主布局:
<!-- button_row.xml --><!--使用 @style/ 的方式为控件添加样式--><TableRow xmlns:android="http://schemas.android.com/apk/res/android" > <Button style="@style/RemoteButton" /> <Button style="@style/RemoteButton" /> <Button style="@style/RemoteButton" /></TableRow>
<!-- button_row_bottom.xml --><!-- 最后一行按钮需特殊定制 --><TableRow xmlns:android="http://schemas.android.com/apk/res/android" > <Button style="@style/RemoteButtonBold" /> <Button style="@style/RemoteButton" /> <Button style="@style/RemoteButtonBold" /></TableRow>
以下是主布局XML:
<!-- fragment_remote_control.xml --><TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/fragment_remote_control_tableLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/remote_background" android:stretchColumns="*" > <TextView android:id="@+id/fragment_remote_control_selectedTextView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:background="@drawable/window_patch" android:gravity="center" android:text="0" android:textColor="#ffffff" android:textSize="50sp" /> <TextView android:id="@+id/fragment_remote_control_workingTextView" android:layout_width="match_parent" android:layout_height="0dp" android:layout_margin="16dp" android:layout_weight="1" android:background="@drawable/bar_patch" android:gravity="center" android:text="0" android:textColor="#cccccc" android:textSize="20sp" android:textStyle="italic" /> <include layout="@layout/button_row" /> <include layout="@layout/button_row" /> <include layout="@layout/button_row" /> <include layout="@layout/button_row_bottom" /></TableLayout>
以上XML有如下几点说明:
- 属性android:stretchColumns= “*” 表示TableRow中的每一个控件大小均分;
- 最上面的两个TextView分别使用了nine-patch图片作为背景,有关nine-patch图片也属于drawable的一种(nine patch drawable),有关nine-patch图片的定义及制作,请参见我的博文《Nine-Patch格式图片浅析》。
- 两个TextView分别设置了android:layout_weight属性,比例为2:1,表示在竖直方向上,两个TextView按照2:1的高度分配空间。注意:由于button属性中定义了android:layout _height=”0dp”,同时未指定android:layout _weight,所以在高度的分配上,应先为TableRow所需空间占用竖直方向的高度,剩余的高度空间再按2:1 的比例分配给两个TextView。
实现逻辑功能
代码如下:
public class ReomoteControlFragment extends android.support.v4.app.Fragment { private TextView mSelectedTextView; private TextView mWorkingTextView; @Override @Nullable public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // TODO Auto-generated method stub final View view = inflater.inflate(R.layout.fragment_remote_control, container, false); mSelectedTextView = (TextView) view .findViewById(R.id.fragment_remote_control_selectedTextView); mWorkingTextView = (TextView) view .findViewById(R.id.fragment_remote_control_workingTextView); View.OnClickListener numberButtonListener = new View.OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub TextView textView = (TextView) v; String working = mWorkingTextView.getText().toString(); String text = textView.getText().toString(); if (working.equals("0")) { mWorkingTextView.setText(text); } else { mWorkingTextView.setText(working + text); } } }; // 为每个按钮动态设置内容、批量绑定监听器 TableLayout tableLayout = (TableLayout) view .findViewById(R.id.fragment_remote_control_tableLayout); int number = 1; // getChildCount返回tableLayout中直接子控件的个数 for (int _i = 2; _i < tableLayout.getChildCount() - 1; ++_i) { TableRow row = (TableRow) tableLayout.getChildAt(_i); for (int _j = 0; _j < row.getChildCount(); _j++) { Button button = (Button) row.getChildAt(_j); button.setText("" + number); button.setOnClickListener(numberButtonListener); ++number; } } // 最后一排按钮的内容及监听器特殊处理 TableRow bottomRow = (TableRow) tableLayout.getChildAt(tableLayout .getChildCount() - 1); // 最后一排第一个按钮为"delete" Button deleteButton = (Button) bottomRow.getChildAt(0); deleteButton.setText("Delete"); deleteButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub mWorkingTextView.setText("0"); } }); // 最后一排第二个按钮为"0" Button zeroButton = (Button) bottomRow.getChildAt(1); zeroButton.setText("0"); zeroButton.setOnClickListener(numberButtonListener); // 最后一排第三个按钮为"Enter" Button enterButton = (Button) bottomRow.getChildAt(2); enterButton.setText("Enter"); enterButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub CharSequence working = mWorkingTextView.getText(); if (working.length() > 0) { mSelectedTextView.setText(working); } mWorkingTextView.setText("0"); } }); return view; }}
注:逻辑代码添加在了Fragment的onCreateView方法中,这与将代码逻辑写在Activity的onCreate方法中是一样的。
最后,为了强制activity竖屏显示,应在AndroidManifest中为activity指定如下属性:
android:screenOrientation="portrait"
- RemoteControl应用介绍
- IOS Audio RemoteControl
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
- iOS音频播放 (八):NowPlayingCenter和RemoteControl
- JAVA实现远程控制(JAVA in RemoteControl)
- JAVA实现远程控制(JAVA in RemoteControl)
- DirectShow应用程序设计介绍
- 应用层截包介绍
- Struts应用框架介绍
- Perl命令行应用介绍
- cad应用技巧介绍
- Perl命令行应用介绍
- Perl命令行应用介绍
- 智能卡应用的介绍
- Perl命令行应用介绍
- 京东钱包App体检报告
- 使用SDwebImage缓存图片并在断网时候显示
- 【SDOI2011】【BZOJ2244】拦截导弹
- C++实现RTMP协议发送H.264编码及AAC编码的音视频,摄像头直播
- SDWebImage,缓存下载,缓存管理,
- RemoteControl应用介绍
- cocos2d-x移植到android如何读取Excel文件
- 判断GPS定位服务是否打开
- 东汉官职列表
- Java调用Kettle执行任务或转换
- SQL SERVER数据库备份时出现“操作系统错误5(拒绝访问)。”错误的解决办法
- PHP Memcache详解
- poi 单元格内容换行
- Win10无法重置