让我们创建屏幕- Android(安卓)UI布局和控件
- 下载LifeCycleTest.zip - 278.9 KB
- 下载ViewAndLayoutLessons_-_Base.zip - 1.2 MB
- 下载ViewAndLayoutLessons_-_Completed.zip - 1.1 MB
指数 介绍背景,论述基础 android活动生命周期的大小 视图 在屏幕上显示视图 让我们的代码 登录活动 TextView 编辑视图属性 edittext imageview按钮 单击事件 复选框创建视图布局的公共属性loginactivity 线性布局,相对布局,框架布局 创建LoginActivity(续) 受欢迎的活动 选项菜单创建WelcomeActivity 报名活动 单选按钮/单选组开关创建注册活动 概要文件的活动 添加逻辑 User类userservice类loginactivity signupactivity欢迎活动配置文件activity 用户列表的活动 创建UserListActivity 已完成的项目存储库感兴趣的历史点 , 介绍 在本文中,您将了解UI组件的概述。Android提供了基本的布局和控件,你可以用来创建你的应用程序的用户界面。然而,如果你不满意他们或你想要更多的组件,你可以自己做。 背景 Android应用UI是一件你必须学习的有趣的事情。它与其他平台有一点不同,但它的设计很棒。要学习这一课,您需要了解Android应用程序的基础,比如项目结构和资源。你可以从Hello Android文章中学习。 这些交易 在学习这篇文章之前,我想确保每个人都在同一个页面上。我已经为您提供了用于管理我们的课程材料的基础项目,您可以从下面的链接下载。 下载ViewAndLayoutLessons_- _base .zip - 436.5 KB 要打开基础项目,您需要解压缩它并打开Android Studio,然后单击file菜单并选择open。 选择项目文件夹并单击OK按钮。 如果你打开了另一个项目,Android Studio会要求你选择你想要打开项目的窗口。 现在,基地项目开放了。 创建项目并运行它。 你会看到这个应用程序的主屏幕只有一个列表。列表中有两个示例项目,您可以单击该项目查看示例活动。在我们的课程中,你将学习创建更多的活动,并将其添加到这个列表中。 活动模板 在本文中,我们将使用空白活动模板创建一个新的活动。 空白活动模板将生成Java代码、布局文件,并将活动自动应用到清单。 为了方便访问活动,当您创建活动时,您需要将其添加到MainActivity中的列表中。 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);//set the activity_main.xml as screen content List activityDataList = new ArrayList();//List of the ActivityData instance, put you ActivityData here activityDataList.add(new ActivityData(getString(R.string.title_activity_sample_inflate_view_from_xml),SampleInflateViewFromXmlActivity.class));//add the ActivityData to the List activityDataList.add(new ActivityData(getString(R.string.title_activity_sample_create_view_in_java_code),SampleCreateViewInJavaCodeActivity.class)); ...}
我们使用,add()语句将活动添加到ListView中。您需要创建一个ActivityData实例,其中包含活动的标题和it类。 这是ActivityData类的构造函数: 隐藏,复制Code
ActivityData(String title,Class activityClass);
现在,尝试创建一个名为“MyFirstActivity”的新活动,并将其添加到列表中。 这是我的主活动。java代码: 隐藏,复制Code
....public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);//set the activity_main.xml as screen content List activityDataList = new ArrayList();//List of the ActivityData instance, put you ActivityData here activityDataList.add(new ActivityData(getString(R.string.title_activity_sample_inflate_view_from_xml),SampleInflateViewFromXmlActivity.class));//add the ActivityData to the List activityDataList.add(new ActivityData(getString(R.string.title_activity_sample_create_view_in_java_code),SampleCreateViewInJavaCodeActivity.class)); activityDataList.add(new ActivityData("My Fist Activity",MyFirstActivity.class)); .... } ....}
当您运行应用程序时,您将在列表中看到一个MyFirstActivity项。 的基础 Android应用UI系统由View和ViewGroup组成。View是显示在屏幕上并且用户可以与之交互的元素,而ViewGroup用于对视图进行分组和对齐。 上图显示了Android应用程序UI是一个视图树。只能在根目录下放置一个元素。因此,ViewGroup是您应该考虑的第一选择,因为它允许您在屏幕上放置许多元素。 的大小 Android建议开发者避免使用像素坐标来定位和调整视图的大小。Android提供了用于分组和安排的ViewGourp或布局,以及用于调整视图大小的特殊单元。 下面是用于调整视图大小和对齐的特殊单位和值: MATCH_PARENT:设置元素的大小(宽度或高度)以适应其父元素。FILL_PARENT:与MATCH_PARENT相同,但支持Android 2.2及以下版本。WRAP_CONTENT:设置元素的大小(宽度或高度)以适应其父元素。dp(dip)单元:根据屏幕的物理密度计算的抽象单元。可用于定义元素的大小或它的边距和填充。sp单元:与dp单元相似,但它也计算用户喜欢的字体大小,建议用于调整文本大小。 Android活动生命周期 当你打开应用程序,切换到另一个,然后关闭它时,你的应用程序发生了什么?应用程序的活动将在称为“活动生命周期”的状态之间转换。 Android为每个Activity的状态提供回调方法。这样你就可以管理活动在进入特定状态时是如何工作的。例如,当应用关闭时停止音乐,当用户切换时结束数据流,另一个应用程序。 上面的图片显示了Android的活动生命周期,状态转换和回调方法。 当活动接收到意图时,它将调用onCreate()方法,您可以在此状态下构造此活动的UI。 创建后,onStart()方法将被调用,在这种状态下,您可以添加一些代码,希望在UI可见之前进行操作。 现在,UI显示出来了。Android会调用onResume()方法,你可以在每次应用恢复时添加你想要操作的内容,比如刷新数据。 恢复后,应用程序已完全运行,您可以与应用程序的UI交互,直到它暂停。 当你切换到另一个应用程序或转到主屏幕时,Activity会pause, onPause()和onSaveInstanceState()方法会调用。您需要保存未保存的数据,停止动画或UI工作,并减少资源的使用。 注意:数据可能在此状态后丢失。你需要自己保存它。 当活动不再可见时,UI将隐藏并且Android将调用onStop()方法,您可以杀死不再使用的服务。 如果导航回活动,onRestart()方法将调用并允许您启动一个活动。 当另一个活动需要更多资源时,Android会杀死未使用的活动。杀死后,用户仍然可以导航到该活动,Android将调用onCreate()方法来重新创建it。您可以恢复在暂停状态下保存的数据。 当Activity结束或Android请求销毁Activity时,Android会调用onDestroy()方法来释放线程、数据等资源。 用你的眼睛看 我创建了一个应用程序,用来学习生命周期回调方法调用的顺序,你可以在这里下载。 下载LifeCycleTest.zip - 278.9 KB 只需要将应用程序部署到你的设备上,然后尝试切换到其他应用程序返回或做一些事情让Activity转换到另一种状态。您将看到在每个状态中从Toast消息(浮动气球内的文本)调用的回调方法。 视图 视图是显示在屏幕上的视觉元素,它可能与用户有一些交互。Android提供了许多可在应用程序中使用的预定义视图。 您可以用Java代码和XML创建视图。我建议您使用XML,因为讨论模型、视图和控件的MVC概念应该是分开的。 这是在XML代码中使用视图的例子: 隐藏,复制Code
<Viewandroid:layout_width="wrap_content"android:layout_height="wrap_content"/>
注意:创建视图时必须使用layout_width和layout_height属性。 如果您想在Java代码中调用此视图,则需要添加id属性来标识此视图。 注意:id属性的值必须以“@+id/”开头,后面跟着名字,或者你可以使用Android的预定义id,比如“@ Android:id/text1” 隐藏,复制Code
<Viewandroid:id="@+id/my_view"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
现在,您可以使用父视图的方法findViewById()在Java代码中调用这个视图,视图的id作为参数。 隐藏,复制Code
public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View myView = findViewById(R.id.my_view); }}
如果希望用Java代码创建视图,可以通过实例化该视图类的对象来实现。 隐藏,复制Code
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); View myView findViewById(R.id.my_view); View newView = new View(this); }}
现在,视图已经创建,但它不会显示在屏幕上,直到您将其添加到现有布局或将其设置为内容视图。 在屏幕上显示视图 在res/layout文件夹中创建布局文件之后,您需要在活动中放入一些代码来调用您想要在屏幕上显示的视图。Activity类提供了一个setContentView()方法,你可以传递布局的id或者视图实例作为参数。 示例1 看一下基本项目,文件名是“activity_sample_inflate_view_from_xml”。然后我想把它显示在SampleInflateViewFromXmlActivity中。 activity_sample_inflate_view_from_xml.xml SampleInflateViewFromXmlActivity.java 我必须将setContentView()语句放入到活动中,并使用布局id作为参数。 隐藏,复制Code
package me.vable.android.viewandlayoutlessons;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;public class SampleInflateViewFromXmlActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sample_inflate_view_from_xml); }}
注意:R类在Java代码中用于访问资源的id, 现在,构建并运行应用程序。 示例2 我有SampleCreateViewInJavaCodeActivity,但我不再想使用XML布局文件,但我想用Java代码创建视图。 注意:为了显示在java代码中构造的视图,你也必须使用setConTentView()方法,但是使用视图实例作为参数而不是布局的id。 以下是我的代码: 隐藏,复制Code
package me.vable.android.uiexample;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.widget.Button;public class SampleActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Button helloWorldButton = new Button(this); helloWorldButton.setText("Hello World"); setContentView(helloWorldButton); }}
我创建了按钮并将其设置为display content。结果如下: 现在,您可以在屏幕上显示视图。 , 让我们的代码 在这节课中,我将给你一个项目,你需要完成它。 这个项目叫做“UserSystem”,它包含5个活动,分别是登录活动、欢迎活动、注册活动、配置文件活动和用户列表活动。让我们看看屏幕模型。 登录活动 创建名为“LoginActivity”的新活动。那么请考虑它的UI。 注意:不要忘记将此活动添加到主页的列表中。 你会发现这个活动有5种类型的视图有图像,文本输入,复选框,文本链接,按钮。现在,将它们链接到Android基本视图类型。 要显示图像,你应该使用ImageView。文本输入——Android提供了EditText,它允许你设置输入类型,你也可以使用作为密码字段。Android在一个视图中提供带有标签的复选框。文本链接-没有文本链接的Android,因为你可以添加事件点击到每个视图。所以你可以用TextView代替。按钮-你可以使用按钮或其他你想要的视图 注:当我描述每个视图时,你可以创建一个新的活动来尝试它自己例如TextViewExampleActivity来学习如何使用TextView工作。 TextView 你可能知道一个TextView作为标签或文本块在其他平台。TextView是用来在屏幕上显示文本的最简单的视图。 创建TextView,只需拖动TextView从调色板,并拖到预览屏幕。 注:Android Studio提供了多种TextView,有纯文本、大文本、中文本和小文本。你可以选择一个你喜欢的。 打开XML视图,你会看到这样的TextView元素: 隐藏,复制Code
<TextViewandroid:text="New Text"android:layout_width="wrap_content"android:layout_height="wrap_content"/>
这些是有趣的属性的TextView: 文本—您希望在此视图上显示的文本。文本大小-文本的大小。文本颜色-文本的颜色。文本的样式(普通/斜体/粗体)。fontFamily—用于呈现文本的字体系列,如serif, sans-serif等。 示例:我想创建一个TextView,显示一个大红色粗体衬线文本“Hello World!” 隐藏,复制Code
android:text="Hello World" android:textSize="36dp" android:textColor="#FF0000" android:fontFamily="serif" />
编辑视图属性 在Android Studio中有很多设置视图属性的方法 1. 使用XML代码 在布局文件的视图元素中,你可以添加已知的属性,比如id。如果你不知道属性名,你可以按Ctrl +空格键(Windows/Linux),然后建议就会显示出来。 隐藏,复制Code
android:id="@+id/textview_hello_world" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World" android:textSize="36dp" android:textColor="#FF0000" android:fontFamily="serif" />
不喜欢XML吗?您还可以使用GUI属性面板来编辑视图属性。 2. 使用属性面板 转到设计视图并单击您想要的视图。在Android Studio屏幕的右边,你会看到属性面板,其中包含一个列表视图的属性。 如果没有找到属性面板,你可能会看到一个“组件树”菜单。单击它,将出现属性面板。 设置所需的属性。 3.双击视图 当您双击该视图时,该视图的公共属性将显示,您可以在这里进行编辑。 注意:在2。和3。你会发现有一个按钮[…在一些属性值的右边,该按钮用于浏览资源,如字符串、drawable等。 在Java代码中访问TextView 您可以从Java代码访问每个视图实例,最简单的方法是使用该视图的id来查找特定的视图。 EditText EditText也称为文本框、文本字段或文本区域,它允许用户使用键盘输入/编辑文本。您可以指定输入数据类型,如数字、电子邮件、密码等。 您可以通过从调色板中拖动EditText(纯文本)并拖放到预览屏幕中来将EditText添加到屏幕中。 你可能得到一个小的TextView后拖放在预览屏幕上,因为宽度被设置为WRAP_CONTENT,让我们试着改变它为MATCH_PARENT。 隐藏,复制Code
<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/editText"/>
当您运行应用程序并点击EditText时,将出现软键盘。 以下是EditText有趣的属性: text—EditText的值。password -如果你设置为true,当你在EditText中输入一些东西时,它将显示每个字符为“•”。文本颜色-文本的颜色。提示-当值为空时出现的文本,用来猜测用户应该输入什么。提示文本的颜色,它应该比文本颜色浅。默认情况下,EditTextView允许用户输入多行文本,如文本区域,如果你不想要多行,设置这个属性为真。maxLines——您可以使用此属性限制文本的行数。inputType—限制用户在此EditText中可以输入的字符类型。 如果你想限制EditText中的数据,你可以设置输入类型,Android提供了很多输入类型,比如number, textUri, textEmailAddress等等。如果软键盘支持输入类型,则输入类型将影响键盘样式。 注意:输入类型只过滤键盘输入。如果你在java代码中设置文本输入类型将不会工作。 示例:当我将输入类型设置为number时,软键盘样式将会改变。 隐藏,复制Code
<EditTextandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/edittext_test"android:layout_alignParentLeft="true"android:layout_alignParentStart="true"android:inputType="number"/>
访问Java代码中的EditText 现在,我们将访问Java中的EditText。设置EditText的id,然后可以使用findViewById()方法获取它的实例。 隐藏,复制Code
.... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_edit_text_example); EditText testEditText = (EditText) findViewById(R.id.edittext_test); }....
可以使用setText()方法设置EditText的值。 隐藏,复制Code
testEditText.setText("value from Java code");
这些是您应该知道的EditText的方法 getText()——返回EditText的值。通常与toString()方法一起使用,以获取作为字符串的值。setText()——设置EditText的值。setOnKeyListener()—设置用于检测一些关键事件(如enter key)的关键监听器。 ImageView 当您想要显示图像时,您应该使用ImageView。您可以通过从调色板中拖动它并拖放到预览屏幕中来创建ImageView。 当你把ImageView放到屏幕上时,它什么也不会显示,直到你设置它的src属性。src属性值是drawable resource,您需要向drawable-xxxx文件夹添加一个图像。 每个可绘制文件夹用于为特定设备提供图像。如果你在drawable-xhdpi中有图像,并且在小屏幕或低分辨率的设备上运行该应用程序,Android会将图像缩放到适合该设备的大小。我将在另一篇文章中描述替代资源。 注意:可绘制资源可以是图像文件和XML文件。 注意:如果可能的话,为每个dpi创建图像,因为自动缩放可能会降低性能。 要将图像添加到项目中,可以直接将其放入drawable-xxxx文件夹中。我建议你在XHDPI或XXHDPI上设计屏幕,使用Nexus 4(XHDPI)或5(XXHDPI)作为预览屏幕设备。 您可以双击ImageView来设置src属性。点击按钮[..]浏览可提取的资源。 , 这些是ImageView有趣的属性 调整视图边界- ImageView将保持高宽比(与图像相同)当你设置这个属性为真。缩放类型-如何缩放图像内容,如果它不适合ImageView。 您可以使用setImageDrawable()、setImageResource()或setImageBitmap()方法在Java代码中设置图像。 按钮 按钮是用户可以按下或单击以执行操作的视图。 你可以通过TextView这样的文本属性设置按钮上的文本,你可以通过属性drawableLeft, drawableRight, drawableTop,和drawableBottom添加图像到按钮。 单击事件 点击是你能与UI交互的最重要的动作,你可以通过实现OnClickListener接口来检测每个Android视图上的点击事件。 我有一个id为button的按钮 隐藏,复制Code
<Buttonandroid:id="@+id/button"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="New Button"/>
然后,实现一个OnClickListener并将其设置为Button实例。 隐藏,复制Code
import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;import android.widget.Toast;public class ButtonExampleActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_button_example); Button button = (Button)findViewById(R.id.button); button.setOnClickListener(onClickListener); } View.OnClickListener onClickListener= new View.OnClickListener() { @Override public void onClick(View view) { Toast.makeText(ButtonExampleActivity.this,"Button was clicked",Toast.LENGTH_SHORT).show(); } };}
当我点击(点击)这个按钮,吐司信息将会显示。 另外,您可以使用XML代码中的onClick 属性来检测单击事件,而无需实现OnClikListener。 注意:如果视图不是一个按钮,您需要将clickable 属性设置为true。 注意:onClick只调用Activity的方法,不要在Fragment中使用它。 隐藏,复制Code
您需要在活动中创建buttonClick(视图)方法 隐藏,复制Code
public void buttonClick(View view){ Toast.makeText(ButtonExampleActivity.this,"Invoke buttonClick() method",Toast.LENGTH_SHORT).show();}
熟悉的视图:ImageButton,每个视图都有onClikListener实现。 复选框 复选框是可被选中或未选中的双状态按钮。在我们的项目中,我们将使用复选框作为一个Remember Me选项,用户可以选择该选项来保持登录状态。 隐藏,复制Code
<CheckBoxandroid:id="@+id/checkbox_remember_me"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="remember me"/>
您可以使用checked属性将其作为默认值进行检查。 隐藏,复制Code
<CheckBoxandroid:id="@+id/checkbox_remember_me"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="remember me"android:checked="true"/>
现在,尝试在Java代码中使用复选框。您可以使用isChecked()方法来获取检查状态。 隐藏,复制Code
CheckBox rememberMeCheckBox = (CheckBox) findViewById(R.id.checkbox_remember_me);boolean rememberMe = rememberMeCheckBox.isChecked();
如果希望检测选中的更改,可以实现CompoundButton。OnCheckedChangeListener接口。 隐藏,复制Code
CompoundButton.OnCheckedChangeListener onRememberMeCheckBoxCheckedChange = new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton compoundButton, boolean checked) { if(checked) { Toast.makeText(CheckBoxExampleActivity.this, "rememberMeCheckBox was checked", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(CheckBoxExampleActivity.this, "rememberMeCheckBox was unchecked", Toast.LENGTH_SHORT).show(); } }};
并将其设置为复选框。 隐藏,复制Code
rememberMeCheckBox.setOnCheckedChangeListener(onRememberMeCheckBoxCheckedChange);
熟悉的视图:开关,切换按钮。 , 创建LoginActivity 现在,你已经学会了5种基本观点。这就足够创建我们项目的活动了,请尝试现在创建它!!(只有UI部分) 注:请将每个视图的名称与下图相同。 结果漂亮吗?:( 现在,您将了解更多关于视图属性和用于构建更漂亮UI的布局的信息。 , 视图的公共属性 当每个视图从相同的基类扩展时,它们将拥有共同的属性/属性。我只描述重要的性质。 使视图透明、半透明或不透明。可能的值在0.0和1.0之间。背景——设置视图的背景。可单击—定义此视图对单击事件作出反应。视图的描述。重力——设置视图的内容位置。可能的值是left、top、right、bottom、center、center_horizontal、center_vertical或combine中的值其中的一些。id -视图的id。minHeight -视图的最小高度。minWidth -视图的最小宽度。onClick—用于对Clik事件作出反应的方法的名称。填充-设置所有四条边的填充。设置底部边缘的填充。设置结束边的填充。设置左边缘的填充。设置右边的填充。设置起始边的填充。设置顶部边缘的填充。saveEnabled -设置如果你想保存状态时UI冻结。标记——设置此视图的标记。可见性——设置视图可见性。 当视图被放置在布局下时,它们会收到一些属性,用于实现布局行为,如layout_margin, layout_gravity。 当你把宽度/高度设置为WRAP_CONTENT时,Android会把视图的宽度/高度设置得尽可能小。但如果你添加minWidth/minHeight到视图,Android会比较width/height和minWidth/minHeight,然后选择最大的一个。 当填充是内容和视图边界之间的间隙时,空白是相反的,它是这个视图和其他视图之间的间隙。 重力属性定义了在视图中放置内容的位置,而layout_gravity定义了在父视图(布局)中放置视图的位置。 布局 布局是什么?布局是一种ViewGroup,用于定义应用程序的UI结构,Android提供了多种布局,如线性布局,框架布局等。在本节中,您将了解每个布局的行为以及如何使用它们。 线性布局 线性布局是最简单的布局,它将它的子元素排列在单个列或行中。 它很容易使用,但功能强大。 使用LinearLayout,你可以衡量视图的宽度或高度。 例如:你在LinearLayout中有一个ImageView和内容,你想将图像缩放到LinearLayout高度的40%,并使用所有剩余的区域来显示内容。 这是当前的XML代码: 隐藏,收缩,复制Code
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"> <ImageViewandroid:id="@+id/image_view_logo"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FF99FF"/> <LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="#999999"> </LinearLayout></LinearLayout>
这就是你想要的: 您需要为LinearLayout设置weightSum属性。 我将LinearLayout的权重和设置为10。 注意:weightSum值可以是整数或小数 隐藏,复制Code
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:weightSum="10"> ....
然后40%的10是4,你需要设置ImageView的权重为4。 隐藏,复制Code
<ImageViewandroid:id="@+id/image_view_logo"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#FF99FF"android:layout_weight="4"/>
剩下的高度是60%,你必须设置内容的重量(内部线性布局)为6。 隐藏,复制Code
<LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"android:background="#999999"android:layout_weight="6"></LinearLayout>
现在,你得到了你想要的UI。 注意:为了在使用权重行为时获得更好的性能,如果使用垂直线性布局,请将布局子元素的高度设置为0dp;如果使用水平线性布局,请将布局子元素的宽度设置为0dp。 隐藏,收缩,复制Code
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:weightSum="10"> <ImageViewandroid:id="@+id/image_view_logo"android:layout_width="match_parent"android:layout_height="0dp"android:background="#FF99FF"android:layout_weight="4"/> <LinearLayoutandroid:layout_width="match_parent"android:layout_height="0dp"android:orientation="vertical"android:background="#999999"android:layout_weight="6"> </LinearLayout></LinearLayout>
相对布局 RelativeLayout是一个非常灵活的布局,它将它的子节点安排到相对位置。每个子元素可以是相对于兄弟元素的特定位置,比如在另一个视图的上面,在另一个视图的左边。RelativeLayout允许视图重叠或浮动视图,它比嵌套LinearLayout有更好的性能。 在许多应用程序中都可以看到相对布局,比如Facebook和谷歌+。 这些是RelativeLayout子视图的有趣属性 layout_alignParentTop—将视图放在RelativeLayout的顶部。layout_alignParentBottom—将视图放置在RelativeLayout的底部。layout_alignParentLeft—将视图放在RelativeLayout的左侧。layout_alignParentRight—将视图放置在RelativeLayout的右侧。layout_centerInParent 把视图放在相对距离的中心。layout_centerHorizontal—将视图置于相对布局的水平中心位置。layout_centerVertical—将视图置于相对布局的垂直中心位置。layout_toLeftOf—将该视图放置到其他视图的左侧。layout_toRightOf—将视图放置到其他视图的右侧。layout_above—将视图放在其他视图的上面。layout_below—将视图放到其他视图的下面。 似乎很难吗?您可以在design视图的RelativeLayout上拖放视图来定位它们。 注意:您需要为每个RelativeLayout的子视图设置id属性,以便在相对位置引用。 示例:你想创建一个论坛应用程序,在线程列表页面上,你想创建这样的列表项: 你决定使用相对线程项目UI,让我们现在尝试一下!! 下图展示了各视图之间的关系 以下是我的代码: 隐藏,收缩,复制Code
<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="70dp"android:background="#252525"android:padding="8dp"android:layout_margin="8dp"> <ImageViewandroid:id="@+id/imageview_icon"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:layout_alignParentTop="true"android:src="@drawable/ic_launcher"/> <TextViewandroid:id="@+id/textview_title"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_above="@+id/textview_content"android:layout_alignParentRight="true"android:layout_alignParentTop="true"android:layout_toRightOf="@+id/imageview_icon"android:text="Title"android:textColor="@android:color/white"android:textSize="24sp"/> <TextViewandroid:id="@+id/textview_content"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_toRightOf="@+id/imageview_icon"android:text="Content"android:textColor="@android:color/secondary_text_dark"android:textSize="18sp"/></RelativeLayout>
这就是结果!! 框架布局 FrameLayout设计为只显示一个子元素,将其放置在布局中心的边框上。但是,您可以向FrameLayout添加多个子视图,但是视图可能会与其他视图重叠,因此您无法控制它。 当视图在FrameLayout可以重叠,你可以创建覆盖元素像谷歌+的写按钮。 注意:要在FrameLayout中定位视图,您可以在子视图上使用layout_gravity和layout_margin属性。 FramLayout示例代码: 隐藏,收缩,复制Code
<FrameLayoutxmlns: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"tools:context="me.vable.android.viewandlayoutlessons.FrameLayoutExampleActivity"> <TextViewandroid:text="top|left"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="top"/> <TextViewandroid:text="right|bottom"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="right|bottom"/> <TextViewandroid:text="bottom|center"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="center_horizontal|bottom"/> <TextViewandroid:text="left|bottom"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="left|bottom"/> <TextViewandroid:text="right|center"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="right|center_vertical"/> <TextViewandroid:text="center"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="center"/> <TextViewandroid:text="left|center"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="left|center_vertical"/> <TextViewandroid:text="top|right"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="right|top"/> <TextViewandroid:text="top|center"android:textSize="20sp"android:gravity="center"android:layout_width="100dp"android:layout_height="100dp"android:background="#FF99FF"android:layout_gravity="center_horizontal|top"/> <ImageView android:layout_width="50dp" android:layout_height="50dp" android:id="@+id/imageView" android:layout_gravity="right|bottom" android:src="@drawable/ic_error" android:layout_margin="80dp"/></FrameLayout>
, 创建LoginActivity(续) 现在,我认为您可以通过使用所学的一切来为LoginActivity创建更好的UI,让我们开始吧!! 我将在下面展示我的布局(自己试试,不要复制) 隐藏,收缩,复制Code
<RelativeLayoutxmlns: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"tools:context="me.vable.android.viewandlayoutlessons.LoginActivity"> <ImageViewandroid:layout_width="match_parent"android:layout_height="200dp"android:id="@+id/imageview_app_logo"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:src="@drawable/ic_launcher"android:adjustViewBounds="true"android:padding="32dp"android:background="#2DABFF"android:layout_marginBottom="16dp"/> <EditTextandroid:id="@+id/edittext_username"android:layout_centerHorizontal="true"android:hint="Username"android:layout_width="250dp"android:layout_height="wrap_content"android:layout_below="@+id/imageview_app_logo"android:singleLine="true"android:maxLines="1"/> <EditTextandroid:id="@+id/edittext_password"android:layout_below="@+id/edittext_username"android:layout_alignRight="@+id/edittext_username"android:layout_alignLeft="@+id/edittext_username"android:hint="Password"android:layout_width="0dp"android:layout_height="wrap_content"android:inputType="textPassword"android:ems="10"android:singleLine="true"android:maxLines="1"/> <CheckBoxandroid:id="@+id/checkbox_remember_me"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="remember me"android:layout_below="@+id/edittext_password"android:layout_alignLeft="@+id/edittext_password"android:layout_marginLeft="8dp"android:layout_marginTop="16dp"/> <TextViewandroid:id="@+id/textview_forgot_password"android:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceSmall"android:text="forgot password?"android:layout_below="@+id/checkbox_remember_me"android:layout_centerHorizontal="true"android:layout_marginTop="16dp"android:textColor="#FF4040"/> <LinearLayoutandroid:orientation="horizontal"android:layout_width="fill_parent"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:layout_alignParentStart="true"android:weightSum="2"> <Buttonandroid:id="@+id/button_sign_up"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Sign up"android:layout_weight="1"/> <Buttonandroid:id="@+id/button_login"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Login"android:layout_weight="1"/> </LinearLayout></RelativeLayout>
, 受欢迎的活动 用户登录后会看到欢迎页面,该页面只显示个人资料图片和问候文字。只有一个选项菜单你还没学过,我们将在这个部分中了解它。 选项菜单 Android提供了一个标准的菜单组件。为了保持一致性,您应该使用标准菜单,而不是构建自己的菜单。在传统的Android版本中,有一个菜单硬件按钮用来打开选项菜单,但是在Android 3.0和上面的选项菜单是操作栏的一部分。谷歌提供了AppCompat库,用于创建遗留Android版本的操作栏,为所有设备带来相同的体验。 在Android 3.0+上,选项菜单分为两种类型,分别是动作菜单(在动作栏上以图标的形式显示)和弹出菜单(子菜单,直到你点击菜单才会崩溃的菜单)。 要创建options菜单,您需要在res/menu中创建一个菜单资源(当您使用空白活动模板时,该菜单资源将自动生成)。 现在,我已经用菜单资源名options_menu_example.xml创建了OptionsMenuExampleActivity。 这是一个XML代码 隐藏,复制Code
<menuxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"tools:context="me.vable.android.viewandlayoutlessons.OptionsMenuExampleActivity"> <itemandroid:id="@+id/action_settings"android:title="@string/action_settings"android:orderInCategory="100"app:showAsAction="never"/></menu>
默认情况下,空白活动模板将生成带有设置菜单的菜单资源。 这些是选项菜单的重要属性 id -这个菜单的id,没有id你就可以在Java代码中访问菜单。标题-你想要在这个菜单上显示的文本。orderInCategory——该菜单在其类别中的顺序。图标——此菜单的图标,当菜单为动作菜单时显示,并且总是显示在旧风格的菜单(遗留的android)上。app:showAsAction / android:showAsAction -这个菜单是动作菜单吗,你可以设置它总是显示为动作菜单,或取决于动作栏的空间,或永远不显示为动作菜单。 注意:如果你的Activity是从AppCompat库的ActionBarActivitiy扩展的,你需要导入一个app名称空间xmlns:app="http://schemas.android.com/apk/res-auto"并使用app名称空间中的showAsAction。或者你可以同时添加app: showasaction&android:showAsAction来确保动作菜单会显示出来。 我建议您将菜单的id命名为action_
<itemandroid:id="@+id/menu_about"android:title="About"android:orderInCategory="101"app:showAsAction="never"/>
我想显示关于菜单下的设置菜单,然后我设置它的顺序为101(大它低)。 接下来,我将创建refresh菜单作为操作菜单。 隐藏,复制Code
<itemandroid:id="@+id/action_refresh"android:title="Refresh"android:orderInCategory="1"app:showAsAction="always"/>
结果如下: 当你创建一个动作菜单时,你应该添加菜单图标。Android建议使用单色图像作为菜单图标,你必须创建的图像,简单,有明确的含义和众所周知的。 我决定使用这个图标来刷新菜单。Android Studio提供了图像资产导入向导,帮助开发者将图像转换为合适的大小和颜色。要使用向导,右键单击res文件夹,然后选择New >图像的资产。 您将看到向导窗口 有3种可绘制的资产类型,你可以使用这个向导来导入,有启动图标,操作栏和选项卡图标,以及通知图标。 我们将使用操作栏和标签图标选项来导入菜单图标。 这些是选项的描述。 资产类型-你想要创建前景的资产类型-你可以使用自己的图像,或使用剪贴画,或文本。 图像文件-如果你使用你自己的图像,向导会让你选择图像。剪纸艺术-如果你设置前景为剪纸艺术,向导将让你选择剪纸艺术。文本-如果你设置前台为文本,你可以在这里输入你的文本。字体-设置文本的字体。 修剪周围的空白空间-修剪前景元素周围的空间。附加填充—在前景元素周围添加空间。主题-你的应用的主题,如果你选择一个自定义选项,它会让你选择图标的颜色。资源名称——设置此资产的名称。 注意:资源名应该是ic_action_
<itemandroid:id="@+id/action_refresh"android:title="Refresh"android:orderInCategory="1"app:showAsAction="always"android:icon="@drawable/ic_action_refresh"/>
结果如下: 接下来,我们将用Java代码访问options菜单,并编写代码以响应选项菜单单击事件。 打开活动文件,您将看到onCreateOptionsMenu()和onOptionsItemSelected()方法(如果不存在就创建它) 隐藏,复制Code
@Overridepublic boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.options_menu_example, menu); return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item);}
onCreateOptionsMenu()方法用于膨胀选项菜单以在视图中显示。 onOptionsItemSelected()方法用于检测菜单上的单击事件。 现在,我们关注onOptionsItemSelected()方法,我将显示每个菜单的Toast消息。 隐藏,复制Code
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_settings) { //do something Toast.makeText(this,"Settings menu was clicked",Toast.LENGTH_SHORT).show(); return true; } else if (id == R.id.menu_about) { //do something Toast.makeText(this,"About menu was clicked",Toast.LENGTH_SHORT).show(); return true; } else if (id == R.id.action_refresh) { //do something Toast.makeText(this,"Refresh menu was clicked",Toast.LENGTH_SHORT).show(); return true; } return super.onOptionsItemSelected(item);}
运行应用程序!! , , 创建WelcomeActivity 现在,您已经了解了用于创建我们项目的WelcomeActivity的所有内容。现在创建它,并设置视图的id和菜单的id,如下图所示。 以下是我的代码: welcome.xml(菜单): 隐藏,收缩,复制Code
<RelativeLayoutxmlns: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:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:paddingBottom="@dimen/activity_vertical_margin"tools:context="me.vable.android.viewandlayoutlessons.WelcomeActivity"> <ImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:adjustViewBounds="true"android:id="@+id/imageview_profile"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:layout_marginTop="32dp"android:src="@drawable/ic_man"/> <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="Hello, John"android:id="@+id/textview_greeting"android:layout_below="@+id/imageview_profile"android:layout_centerHorizontal="true"android:layout_marginTop="16dp"/></RelativeLayout>
activity_welcome.xml(布局): 隐藏,收缩,复制Code
<menuxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"tools:context="me.vable.android.viewandlayoutlessons.WelcomeActivity"> <itemandroid:id="@+id/menu_user_list"android:title="User List"android:orderInCategory="1"app:showAsAction="never"/> <itemandroid:id="@+id/menu_profile"android:title="My Profile"android:orderInCategory="2"app:showAsAction="never"/> <itemandroid:id="@+id/menu_logout"android:title="Log Out"android:orderInCategory="3"app:showAsAction="never"/></menu>
, 报名活动 当用户打开应用程序,他们会发现LoginActivity,如果他们没有帐户,他们需要注册一个新的。还有一个RadioButton, RadioGroup,和Switch我们还没学过。现在,我们将学习创建一个注册活动。 RadioButton / RadioGroup RadioButton和RadioGroup一起用于创建一系列项,但是一次只能选择一个项。 RadioGroup是用来控制RadioButton的视图组,它只允许用户选择一个项目。 注意:在像线性布局这样的放射组中有方向属性。 几乎RadioButton的属性就像复选框的特性。我想你可以自己试一试。 例子:我想创建一个单一的选择问题,像上面的图片。以下是我的代码: 隐藏,收缩,复制Code
<LinearLayoutxmlns: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:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:paddingBottom="@dimen/activity_vertical_margin"tools:context="me.vable.android.viewandlayoutlessons.RadioButtonExampleActivity"android:orientation="vertical"> <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:text="what are you feeling right now?"android:id="@+id/textView"/> <RadioGroupandroid:id="@+id/radiogroup_feeling"android:layout_width="fill_parent"android:layout_height="wrap_content"> <RadioButtonandroid:id="@+id/radiobutton_felling_happy"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Happy"/> <RadioButtonandroid:id="@+id/radiobutton_felling_sad"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Sad"/> <RadioButtonandroid:id="@+id/radiobutton_felling_bored"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Bored"/> </RadioGroup></LinearLayout>
现在,我想检测什么按钮被选中,实现OnCheckedChangeListener的RadioGroup来检测选择变化。您将看到onCheckedChanged()方法,它将在所选项目发生更改时调用,它提供RadioButton的RadioGroup和id作为参数。 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.RadioGroup;import android.widget.Toast;public class RadioButtonExampleActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_radio_button_example); RadioGroup feelingRadioGroup = (RadioGroup) findViewById(R.id.radiogroup_feeling); feelingRadioGroup.setOnCheckedChangeListener(onCheckedChangeListener); } RadioGroup.OnCheckedChangeListener onCheckedChangeListener= new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup radioGroup, int i) { if(i == R.id.radiobutton_felling_happy) { Toast.makeText(RadioButtonExampleActivity.this,"You're happy!!",Toast.LENGTH_SHORT).show(); } else if(i == R.id.radiobutton_felling_sad) { Toast.makeText(RadioButtonExampleActivity.this,"You're sad",Toast.LENGTH_SHORT).show(); } else if(i == R.id.radiobutton_felling_bored) { Toast.makeText(RadioButtonExampleActivity.this,"You're bored",Toast.LENGTH_SHORT).show(); } } };}
, 开关 开关就像复选框一样工作,但它看起来像真实世界中的开关。你可以在上面设置开/关标签。需要切换Android 4.0或以上版本,如果您的设备运行的Android版本低于4.0,请使用复选框代替。 下面是一个例子: 隐藏,复制Code
<Switchandroid:id="@+id/switch_subscription"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Email subscriptions"android:textOn=""/>
您还可以通过使用textOn和textOff属性来设置on/off文本 隐藏,复制Code
<Switchandroid:id="@+id/switch_subscription"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Email subscriptions"android:textOn="Yes"android:textOff="No"/>
熟悉的视图:复选框,切换按钮。 , 创建SignUpActivity 现在就让我们创建注册活动吧!! 注意:请使用我在下面图片中提供的id。 以下是我的代码: activity_sign_up.xml 隐藏,收缩,复制Code
<RelativeLayoutxmlns: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:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"android:paddingBottom="@dimen/activity_vertical_margin"tools:context="me.vable.android.viewandlayoutlessons.SignupActivity"> <ImageViewandroid:layout_width="100dp" android:layout_height="100dp" android:adjustViewBounds="true"android:id="@+id/imageview_profile"android:layout_alignParentTop="true"android:layout_centerHorizontal="true"android:layout_marginTop="32dp"android:src="@drawable/ic_man"/> <EditTextandroid:id="@+id/edittext_username"android:layout_width="250dp"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:hint="Username"android:layout_below="@+id/imageview_profile"android:layout_centerHorizontal="true"android:layout_marginTop="16dp"/> <EditTextandroid:id="@+id/edittext_password"android:layout_width="250dp"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:hint="Password"android:password="true"android:layout_below="@+id/edittext_username"android:layout_centerHorizontal="true"/> <EditTextandroid:id="@+id/edittext_email"android:inputType="textEmailAddress"android:layout_width="250dp"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceMedium"android:hint="Username"android:layout_below="@+id/edittext_password"android:layout_centerHorizontal="true"/> <RadioGroupandroid:id="@+id/radiogroup_gender"android:layout_width="250dp"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_below="@+id/edittext_email"android:layout_centerHorizontal="true"> <RadioButtonandroid:id="@+id/radiobutton_male"android:text="male"android:layout_width="wrap_content"android:layout_height="wrap_content"/> <RadioButtonandroid:text="female"android:id="@+id/radiobutton_female"android:layout_width="wrap_content"android:layout_height="wrap_content"/> </RadioGroup> <Switchandroid:id="@+id/switch_subscription"android:layout_width="300dp"android:layout_height="wrap_content"android:text="Email subscriptions"android:layout_centerHorizontal="true"android:layout_marginTop="16dp"android:layout_below="@+id/radiogroup_gender"/> <Switchandroid:id="@+id/switch_allow_email"android:layout_width="300dp"android:layout_height="wrap_content"android:text="Allow email from other"android:layout_centerHorizontal="true"android:layout_marginTop="16dp"android:layout_below="@+id/switch_subscription"/></RelativeLayout>
sign_up.xml(选项菜单) 隐藏,复制Code
<menuxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"tools:context="me.vable.android.viewandlayoutlessons.SignUpActivity"> <itemandroid:id="@+id/action_submit"android:icon="@drawable/ic_action_check"android:title="Submit"app:showAsAction="always"/></menu>
然后,在设备上运行应用程序!! , 概要文件的活动 ProfileActivity将显示不带密码的用户信息。请自己创建它!! 完成后,在创建下一个活动之前,我们将向每个活动添加逻辑。 添加逻辑 在创建最后一个活动之前,我们将为每个活动添加逻辑代码,以使我们的应用程序工作。我已经在基础项目中提供了逻辑代码,你只需要实现它将你的活动。 用户类 User是用于存储用户信息的类。 以下是User类的属性: ,,私人字符串的用户名;,,私人密码字符串;,,私人字符串邮件;,,私人字符串profileImage;,,私人性别性别;,,私人布尔newsletterSubscribed;,,私人布尔allowedOtherEmail; Use可以通过访问器方法(get/set)设置或获取它。 这是性别枚举的结构 隐藏,复制Code
public enum Gender implements Serializable { MALE,FEMALE}
UserService类 UserService用于管理用户帐户,有创建新用户、登录、注销等功能,您将使用这个类与屏幕交互。 这些是这个类的方法: getInstance()—获取该类的当前实例。getCurrentUser() -获取当前登录用户。login()——使用用户名和密码对用户进行身份验证,您需要传递LoginListener以用于接收结果。登出()-从系统登出。register()—创建一个新的用户帐户,您需要传递RegisterListenerfor用于接收结果。getProfileImage() -返回用户配置文件图像的位图对象。getUserList()—获取用户帐户的列表,您需要传递用于接收结果的GetUserListListener。 这是你需要的界面t当使用某些方法时实现。 隐藏,复制Code
public interface LoginListener{ public void onResponce(boolean loggedin,String message, User user);}public interface RegisterListener{ public void onResponce(boolean registered, String message, User user);}public interface GetUserListListener{ public void onResponce(boolean success, String message, Listusers);}
每个接口将在第一个参数中返回结果,在第二个参数中返回消息,第三个参数是用户对象或用户列表对象。 LoginActivity 现在,开始使用LoginActivity。 首先,你需要获得视图的所有实例。 隐藏,复制Code
private EditText usernameEditText;private EditText passwordEduitText;private CheckBox rememberMeCheckBox;private TextView forgotPasswordTextView;private Button loginButton;private Button signUpButton;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); usernameEditText = (EditText) findViewById(R.id.edittext_username); passwordEduitText = (EditText) findViewById(R.id.edittext_password); rememberMeCheckBox = (CheckBox) findViewById(R.id.checkbox_remember_me); forgotPasswordTextView = (TextView) findViewById(R.id.textview_forgot_password); loginButton = (Button) findViewById(R.id.button_login); signUpButton = (Button) findViewById(R.id.button_sign_up);}
接下来,我们将创建login()方法。 隐藏,复制Code
private void login(String username,String password){ progressDialog.show(); UserService.getInstance(LoginActivity.this).login(username, password, loginListener);}
login()方法将调用UserService类的登录方法。 注意:您需要使用UserService. getinstance(上下文)来获得UserService类上的实例,不要自己创建它。 创建ProgressDialog,在执行长操作方法()时显示 隐藏,复制Code
private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { ... progressDialog = new ProgressDialog(LoginActivity.this); progressDialog.setIndeterminate(true); ... }
然后我们需要实现LoginListener来接收结果回调。 隐藏,收缩,复制Code
UserService.LoginListener loginListener = new UserService.LoginListener() { @Override public void onResponce(boolean loggedin, String message, User user) { progressDialog.dismiss(); Toast.makeText(LoginActivity.this,message,Toast.LENGTH_SHORT).show(); if(loggedin) { SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); if(rememberMeCheckBox.isChecked()) { editor.putBoolean("remembered", true); editor.putString("username", user.getUsername()); editor.putString("password", user.getPassword()); } else { editor.putBoolean("remembered",false); editor.remove("username"); editor.remove("password"); } editor.commit(); goToWelcomeActivity(); } }};
如果登录成功,我们需要检查“记住我”按钮状态。如果用户想要记住,我们需要将帐户数据保存到SharePreferences中。 Android提供了SharedPreferences来存储应用程序数据,比如设置。您可以从上下文类的getSharedPreferences()方法获得SharePreferences实例。您可以使用SharedPreferences保存或管理数据。编辑器类。 注意:每次使用添加、删除或编辑SharedPreferences数据时,您都需要使用edit .commit()方法提交数据。 当用户登录时,您需要使用WelcomeActivity。因此,我创建了goToWelcomeActivity()方法来完成这项工作。 隐藏,复制Code
private void goToWelcomeActivity(){ Intent intent = new Intent(this,WelcomeActivity.class); startActivity(intent); finish();}
intent对象就像你发送给安卓的消息,安卓收到意图后会找到那个意图的责任人。当你切换到另一个Activity时,你需要创建一个Intent并传递上下文和另一个Activity类,然后调用startActivity()方法。finish()方法用于结束活动,用户登录后我们将完成活动,因为我们不再需要它了。 接下来,我们将检测Login按钮的单击事件。 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... loginButton.setOnClickListener(onClickLoginButtonListener); ...}View.OnClickListener onClickLoginButtonListener = new View.OnClickListener() { @Override public void onClick(View view) { String username = usernameEditText.getText().toString(); String password = passwordEduitText.getText().toString(); login(username, password); }};
我们需要获取usernameEditText和passwordEditText的值,并将它们传递到login()方法中。 在此之后,我们必须实现注册按钮的单击事件。 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... signUpButton.setOnClickListener(onClickSignUpButtonListener); ...}View.OnClickListener onClickSignUpButtonListener = new View.OnClickListener() { @Override public void onClick(View view) { goToSignupActivity(); }};private void goToSignupActivity(){ Intent intent = new Intent(this,SignUpActivity.class); startActivity(intent);}
当用户点击注册按钮时,应用程序将导航到注册活动。 几乎完成,现在有忘记密码TextView,将用于更新密码,但我们现在没有那个功能。我们需要告诉用户这个函数没有实现。 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... forgotPasswordTextView.setOnClickListener(onClickForgotPasswordTextViewListener);}...View.OnClickListener onClickForgotPasswordTextViewListener = new View.OnClickListener() { @Override public void onClick(View view) { AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); builder.setTitle("Waraing"); builder.setIcon(R.drawable.ic_error); builder.setMessage("Not implement"); builder.setPositiveButton("OK",null); builder.show(); }};
我创建了AlertDialog来向用户显示这个函数没有实现。 接下来,我们需要检查用户进入该活动时的登录状态,如果用户已经登录,应用程序应该立即导航到WelcomeActivity。 隐藏,复制Code
@Override protected void onCreate(Bundle savedInstanceState) { ... if(UserService.getInstance(this).getCurrentUser()!=null) { goToWelcomeActivity(); return; } }
要检查statuc中的日志,您可以使用UserService的medthod getCurrentUser(),如果当前用户不是null,您需要切换到WelcomeActivity。 最后,如果我们已经从Remember Me函数存储了用户数据,则需要立即登录该用户。 隐藏,复制Code
@Override protected void onCreate(Bundle savedInstanceState) { ... SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); boolean remembered = sharedPreferences.getBoolean("remembered",false); if(remembered) { rememberMeCheckBox.setChecked(true); String username = sharedPreferences.getString("username", null); String password = sharedPreferences.getString("password", null); login(username,password); } }
这里是一个完整的源代码: 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.app.AlertDialog;import android.app.ProgressDialog;import android.content.Intent;import android.content.SharedPreferences;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.Button;import android.widget.CheckBox;import android.widget.EditText;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.service.UserService;public class LoginActivity extends ActionBarActivity { private EditText usernameEditText; private EditText passwordEduitText; private CheckBox rememberMeCheckBox; private TextView forgotPasswordTextView; private Button loginButton; private Button signUpButton; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); if(UserService.getInstance(this).getCurrentUser()!=null) { goToWelcomeActivity(); return; } progressDialog = new ProgressDialog(LoginActivity.this); progressDialog.setIndeterminate(true); usernameEditText = (EditText) findViewById(R.id.edittext_username); passwordEduitText = (EditText) findViewById(R.id.edittext_password); rememberMeCheckBox = (CheckBox) findViewById(R.id.checkbox_remember_me); forgotPasswordTextView = (TextView) findViewById(R.id.textview_forgot_password); loginButton = (Button) findViewById(R.id.button_login); signUpButton = (Button) findViewById(R.id.button_sign_up); loginButton.setOnClickListener(onClickLoginButtonListener); signUpButton.setOnClickListener(onClickSignUpButtonListener); forgotPasswordTextView.setOnClickListener(onClickForgotPasswordTextViewListener); SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); boolean remembered = sharedPreferences.getBoolean("remembered",false); if(remembered) { rememberMeCheckBox.setChecked(true); String username = sharedPreferences.getString("username", null); String password = sharedPreferences.getString("password", null); login(username,password); } } private void login(String username,String password) { progressDialog.show(); UserService.getInstance(LoginActivity.this).login(username, password, loginListener); } private void goToSignupActivity() { Intent intent = new Intent(this,SignUpActivity.class); startActivity(intent); } private void goToWelcomeActivity() { Intent intent = new Intent(this,WelcomeActivity.class); startActivity(intent); finish(); } View.OnClickListener onClickLoginButtonListener = new View.OnClickListener() { @Override public void onClick(View view) { String username = usernameEditText.getText().toString(); String password = passwordEduitText.getText().toString(); login(username, password); } }; View.OnClickListener onClickSignUpButtonListener = new View.OnClickListener() { @Override public void onClick(View view) { goToSignupActivity(); } }; View.OnClickListener onClickForgotPasswordTextViewListener = new View.OnClickListener() { @Override public void onClick(View view) { AlertDialog.Builder builder = new AlertDialog.Builder(LoginActivity.this); builder.setTitle("Waraing"); builder.setIcon(R.drawable.ic_error); builder.setMessage("Not implement"); builder.setPositiveButton("OK",null); builder.show(); } }; UserService.LoginListener loginListener = new UserService.LoginListener() { @Override public void onResponce(boolean loggedin, String message, User user) { progressDialog.dismiss(); Toast.makeText(LoginActivity.this,message,Toast.LENGTH_SHORT).show(); if(loggedin) { SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); if(rememberMeCheckBox.isChecked()) { editor.putBoolean("remembered", true); editor.putString("username", user.getUsername()); editor.putString("password", user.getPassword()); } else { editor.putBoolean("remembered",false); editor.remove("username"); editor.remove("password"); } editor.commit(); goToWelcomeActivity(); } } };}
SignUpActivity 要向SignupActivity添加逻辑,您需要首先获取所有视图实例。 隐藏,收缩,复制Code
private ImageView profileImageView;private EditText usernameEditText;private EditText passwordEditText;private EditText emailEditText;private RadioGroup genderRadioGroup;private RadioButton maleRadioButton;private RadioButton femaleRadioButton;private CompoundButton newsletterSubscriptionCompoundButton;private CompoundButton allowOtherEmailCompoundButton;private ProgressDialog progressDialog;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); progressDialog = new ProgressDialog(this); progressDialog.setIndeterminate(true); profileImageView = (ImageView) findViewById(R.id.imageview_profile); usernameEditText = (EditText) findViewById(R.id.edittext_username); passwordEditText = (EditText) findViewById(R.id.edittext_password); emailEditText = (EditText) findViewById(R.id.edittext_email); genderRadioGroup = (RadioGroup) findViewById(R.id.radiogroup_gender); maleRadioButton = (RadioButton) findViewById(R.id.radiobutton_male); femaleRadioButton = (RadioButton) findViewById(R.id.radiobutton_female); newsletterSubscriptionCompoundButton = (CompoundButton) findViewById(R.id.switch_subscription); if(newsletterSubscriptionCompoundButton == null) { newsletterSubscriptionCompoundButton = (CompoundButton) findViewById(R.id.checkbox_subscription); } allowOtherEmailCompoundButton = (CompoundButton) findViewById(R.id.switch_allow_email); if(allowOtherEmailCompoundButton == null) { allowOtherEmailCompoundButton = (CompoundButton) findViewById(R.id.checkbox_allow_email); }}
我使用CompoundButton而不是Switch或复选框,因为我需要同时支持它们。 通过将其中一个选项设置为默认选项,以确保选中了一个性别按钮 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... maleRadioButton.setChecked(true);}
当用户点击配置文件imageView时,我想允许他们选择他/她的设备上的图片。 隐藏,复制Code
private static final int SELECT_PICTURE = 1;@Overrideprotected void onCreate(Bundle savedInstanceState) { ... profileImageView.setOnClickListener(onClickProfileImageViewListener);}View.OnClickListener onClickProfileImageViewListener = new View.OnClickListener() { @Override public void onClick(View view) { chooseImage(); }};private void chooseImage(){ Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, SELECT_PICTURE);}
我使用Intent打开了另一个提供图像的应用程序。 当图像被接收时,我们将调整大小并设置在配置文件ImageView中显示它。 隐藏,收缩,复制Code
private Bitmap bitmap;@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SELECT_PICTURE && resultCode == Activity.RESULT_OK) try { // We need to recyle unused bitmaps if (bitmap != null) { bitmap.recycle(); } InputStream stream = getContentResolver().openInputStream(data.getData()); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize=2; bitmap = BitmapFactory.decodeStream(stream, null, options); int width = bitmap.getWidth(); int height = bitmap.getHeight(); double scale = 100.0/height; height = (int)(height*scale); width = (int)(width*scale); bitmap = Bitmap.createScaledBitmap(bitmap, width,height, false); stream.close(); profileImageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } super.onActivityResult(requestCode, resultCode, data);}
接下来,当用户单击Submit Action菜单时,数据将发送到UserService以创建帐户。 隐藏,收缩,复制Code
@Overridepublic boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.sign_up, menu); return true;}@Overridepublic boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_submit) { String username = usernameEditText.getText().toString(); String password = passwordEditText.getText().toString(); String email = emailEditText.getText().toString(); User.Gender gender; if(genderRadioGroup.getCheckedRadioButtonId() == R.id.radiobutton_male) { gender = User.Gender.MALE; } else { gender = User.Gender.FEMALE; } boolean newsletterSubscribed = newsletterSubscriptionCompoundButton.isChecked(); boolean allowedOtherEmail = allowOtherEmailCompoundButton.isChecked(); register(username,password,email,gender,newsletterSubscribed,allowedOtherEmail); return true; } return super.onOptionsItemSelected(item);}private void register(String username,String password, String email, User.Gender gender, boolean newsletterSubscribed, boolean allowedOtherEmail){ progressDialog.show(); UserService.getInstance(SignUpActivity.this).register(username,password,email,gender,newsletterSubscribed,allowedOtherEmail,registerListener,bitmap);}
实现用于接收注册结果的RegisterListener。 隐藏,复制Code
UserService.RegisterListener registerListener = new UserService.RegisterListener() { @Override public void onResponce(boolean registered, String message, User user) { progressDialog.dismiss(); Toast.makeText(SignUpActivity.this, message, Toast.LENGTH_SHORT).show(); if(registered) { goToWelcomeActivity(); } }};private void goToWelcomeActivity(){ Intent intent = new Intent(this,WelcomeActivity.class); startActivity(intent); finish();}
之后,您需要检查用户进入该活动时的登录状态。 隐藏,复制Code
protected void onCreate(Bundle savedInstanceState) { .... if(UserService.getInstance(this).getCurrentUser()!=null) { goToWelcomeActivity(); } ....}
这里是一个完整的源代码: 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.app.Activity;import android.app.ProgressDialog;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.CompoundButton;import android.widget.EditText;import android.widget.ImageView;import android.widget.RadioButton;import android.widget.RadioGroup;import android.widget.Toast;import java.io.FileNotFoundException;import java.io.IOException;import java.io.InputStream;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.service.UserService;public class SignUpActivity extends ActionBarActivity { private ImageView profileImageView; private EditText usernameEditText; private EditText passwordEditText; private EditText emailEditText; private RadioGroup genderRadioGroup; private RadioButton maleRadioButton; private RadioButton femaleRadioButton; private CompoundButton newsletterSubscriptionCompoundButton; private CompoundButton allowOtherEmailCompoundButton; private ProgressDialog progressDialog; private Bitmap bitmap; private static final int SELECT_PICTURE = 1; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_up); if(UserService.getInstance(this).getCurrentUser()!=null) { goToWelcomeActivity(); } progressDialog = new ProgressDialog(this); progressDialog.setIndeterminate(true); profileImageView = (ImageView) findViewById(R.id.imageview_profile); usernameEditText = (EditText) findViewById(R.id.edittext_username); passwordEditText = (EditText) findViewById(R.id.edittext_password); emailEditText = (EditText) findViewById(R.id.edittext_email); genderRadioGroup = (RadioGroup) findViewById(R.id.radiogroup_gender); maleRadioButton = (RadioButton) findViewById(R.id.radiobutton_male); femaleRadioButton = (RadioButton) findViewById(R.id.radiobutton_female); newsletterSubscriptionCompoundButton = (CompoundButton) findViewById(R.id.switch_subscription); if(newsletterSubscriptionCompoundButton == null) { newsletterSubscriptionCompoundButton = (CompoundButton) findViewById(R.id.checkbox_subscription); } allowOtherEmailCompoundButton = (CompoundButton) findViewById(R.id.switch_allow_email); if(allowOtherEmailCompoundButton == null) { allowOtherEmailCompoundButton = (CompoundButton) findViewById(R.id.checkbox_allow_email); } maleRadioButton.setChecked(true); profileImageView.setOnClickListener(onClickProfileImageViewListener); } View.OnClickListener onClickProfileImageViewListener = new View.OnClickListener() { @Override public void onClick(View view) { chooseImage(); } }; private void chooseImage() { Intent intent = new Intent(Intent.ACTION_PICK,android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI); startActivityForResult(intent, SELECT_PICTURE); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == SELECT_PICTURE && resultCode == Activity.RESULT_OK) try { // We need to recyle unused bitmaps if (bitmap != null) { bitmap.recycle(); } InputStream stream = getContentResolver().openInputStream(data.getData()); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize=2; bitmap = BitmapFactory.decodeStream(stream, null, options); int width = bitmap.getWidth(); int height = bitmap.getHeight(); double scale = 100.0/height; height = (int)(height*scale); width = (int)(width*scale); bitmap = Bitmap.createScaledBitmap(bitmap, width,height, false); stream.close(); profileImageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } super.onActivityResult(requestCode, resultCode, data); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.sign_up, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.action_submit) { String username = usernameEditText.getText().toString(); String password = passwordEditText.getText().toString(); String email = emailEditText.getText().toString(); User.Gender gender; if(genderRadioGroup.getCheckedRadioButtonId() == R.id.radiobutton_male) { gender = User.Gender.MALE; } else { gender = User.Gender.FEMALE; } boolean newsletterSubscribed = newsletterSubscriptionCompoundButton.isChecked(); boolean allowedOtherEmail = allowOtherEmailCompoundButton.isChecked(); register(username,password,email,gender,newsletterSubscribed,allowedOtherEmail); return true; } return super.onOptionsItemSelected(item); } private void register(String username,String password, String email, User.Gender gender, boolean newsletterSubscribed, boolean allowedOtherEmail) { progressDialog.show(); UserService.getInstance(SignUpActivity.this).register(username,password,email,gender,newsletterSubscribed,allowedOtherEmail,registerListener,bitmap); } UserService.RegisterListener registerListener = new UserService.RegisterListener() { @Override public void onResponce(boolean registered, String message, User user) { progressDialog.dismiss(); Toast.makeText(SignUpActivity.this, message, Toast.LENGTH_SHORT).show(); if(registered) { goToWelcomeActivity(); } } }; private void goToWelcomeActivity() { Intent intent = new Intent(this,WelcomeActivity.class); startActivity(intent); finish(); }}
受欢迎的活动 此活动将只显示使用配置文件图像和问候消息。 你需要获取视图上的instace并设置它们的值。 隐藏,复制Code
private ImageView profileImageView;private TextView greetingTextView;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_welcome); profileImageView = (ImageView) findViewById(R.id.imageview_profile); greetingTextView = (TextView) findViewById(R.id.textview_greeting); greetingTextView.setText(String.format("Hello, %s", user.getUsername())); profileImageView.setImageBitmap(UserService.getInstance(this).getProfileImage(user));}
检查用户实例。如果它不存在,您应该立即关闭此活动。 隐藏,复制Code
User user = UserService.getInstance(this).getCurrentUser();if(user==null) { finish(); return;}
然后,使用onOptionsItemSelected()方法检测选项菜单项单击事件,并为每个事件创建操作。 隐藏,收缩,复制Code
@Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.welcome, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.menu_user_list) { return true; }else if (id == R.id.menu_profile) { goToMenuProfilePage(); return true; }else if (id == R.id.menu_logout) { logout(); return true; } return super.onOptionsItemSelected(item); } private void goToMenuProfilePage() { Intent intent = new Intent(this,ProfileActivity.class); startActivity(intent); } private void logout() { UserService.getInstance(this).logout(); SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean("remembered",false); editor.remove("username"); editor.remove("password"); editor.commit(); finish(); }}
在goToMenuProfilePage()中,我有cr关闭意图并将额外的数据放入其中,因为我想要将User对象传递到ProfileActivity中。 这里是一个完整的源代码: 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.content.Intent;import android.content.SharedPreferences;import android.support.v7.app.ActionBarActivity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.widget.ImageView;import android.widget.TextView;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.service.UserService;public class WelcomeActivity extends ActionBarActivity { private ImageView profileImageView; private TextView greetingTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_welcome); profileImageView = (ImageView) findViewById(R.id.imageview_profile); greetingTextView = (TextView) findViewById(R.id.textview_greeting); User user = UserService.getInstance(this).getCurrentUser(); if(user==null) { finish(); return; } greetingTextView.setText(String.format("Hello, %s", user.getUsername())); profileImageView.setImageBitmap(UserService.getInstance(this).getProfileImage(user)); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.welcome, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.menu_user_list) { return true; }else if (id == R.id.menu_profile) { goToMenuProfilePage(); return true; }else if (id == R.id.menu_logout) { logout(); return true; } return super.onOptionsItemSelected(item); } private void goToMenuProfilePage() { Intent intent = new Intent(this,ProfileActivity.class); startActivity(intent); } private void logout() { UserService.getInstance(this).logout(); SharedPreferences sharedPreferences = getSharedPreferences("user_data",MODE_PRIVATE); SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putBoolean("remembered",false); editor.remove("username"); editor.remove("password"); editor.commit(); finish(); }}
概要文件的活动 ProfileActivity将从intent接收用户对象,并在屏幕上显示用户信息。首先,我们需要从intent接收User对象并获取所有视图实例。 隐藏,收缩,复制Code
private ImageView profileImageView;private TextView usernameTextView;private TextView emailTextVIew;private TextView genderTextView;private CompoundButton newsletterSubscriptionCompoundButton;private CompoundButton allowOtherEmailCompoundButton;@Overrideprotected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); User user = (User) getIntent().getExtras().getSerializable("user"); if(user==null) { finish(); return; } profileImageView = (ImageView) findViewById(R.id.imageview_profile); usernameTextView = (TextView) findViewById(R.id.textview_username); emailTextVIew = (TextView) findViewById(R.id.textview_email); genderTextView = (TextView) findViewById(R.id.textview_gender); newsletterSubscriptionCompoundButton = (Switch) findViewById(R.id.switch_subscription); if(newsletterSubscriptionCompoundButton==null) { newsletterSubscriptionCompoundButton = (CheckBox) findViewById(R.id.checkbox_subscription); } allowOtherEmailCompoundButton = (Switch) findViewById(R.id.switch_allow_email); if(allowOtherEmailCompoundButton==null) { allowOtherEmailCompoundButton = (CheckBox) findViewById(R.id.checkbox_allow_email); }}
接下来,将该值设置为视图 隐藏,复制Code
profileImageView.setImageBitmap(UserService.getInstance(this).getProfileImage(user));usernameTextView.setText(String.format("Username: %s",user.getUsername()));emailTextVIew.setText(String.format("Email: %s",user.getEmail()));genderTextView.setText(String.format("Gender: %s",user.getGender()== User.Gender.MALE?"Male":"Female"));newsletterSubscriptionCompoundButton.setChecked(user.isNewsletterSubscribed());allowOtherEmailCompoundButton.setChecked(user.isAllowedOtherEmail());
最后,如果allowOtherEmailCompoundButton没有被选中,我们需要隐藏电子邮件。 隐藏,复制Code
if(!allowOtherEmailCompoundButton.isChecked()){ emailTextVIew.setVisibility(View.GONE);}
这里是一个完整的源代码: 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.app.Activity;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.widget.CheckBox;import android.widget.CompoundButton;import android.widget.ImageView;import android.widget.Switch;import android.widget.TextView;import org.w3c.dom.Text;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.service.UserService;public class ProfileActivity extends ActionBarActivity { private ImageView profileImageView; private TextView usernameTextView; private TextView emailTextVIew; private TextView genderTextView; private CompoundButton newsletterSubscriptionCompoundButton; private CompoundButton allowOtherEmailCompoundButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); User user = (User) getIntent().getExtras().getSerializable("user"); if(user==null) { finish(); return; } profileImageView = (ImageView) findViewById(R.id.imageview_profile); usernameTextView = (TextView) findViewById(R.id.textview_username); emailTextVIew = (TextView) findViewById(R.id.textview_email); genderTextView = (TextView) findViewById(R.id.textview_gender); newsletterSubscriptionCompoundButton = (Switch) findViewById(R.id.switch_subscription); if(newsletterSubscriptionCompoundButton==null) { newsletterSubscriptionCompoundButton = (CheckBox) findViewById(R.id.checkbox_subscription); } allowOtherEmailCompoundButton = (Switch) findViewById(R.id.switch_allow_email); if(allowOtherEmailCompoundButton==null) { allowOtherEmailCompoundButton = (CheckBox) findViewById(R.id.checkbox_allow_email); } profileImageView.setImageBitmap(UserService.getInstance(this).getProfileImage(user)); usernameTextView.setText(String.format("Username: %s",user.getUsername())); emailTextVIew.setText(String.format("Email: %s",user.getEmail())); genderTextView.setText(String.format("Gender: %s",user.getGender()== User.Gender.MALE?"Male":"Female")); newsletterSubscriptionCompoundButton.setChecked(user.isNewsletterSubscribed()); allowOtherEmailCompoundButton.setChecked(user.isAllowedOtherEmail()); if(!allowOtherEmailCompoundButton.isChecked()) { emailTextVIew.setVisibility(View.GONE); } }}
用户列表活动,应用程序的最后一个活动 这是一篇关于视图和ViewGroup的文章,但是如果不编写代码,您将无法理解此活动中的ViewGroup。这就是我用这个活动结束这篇文章的原因,ViewGroup是ListView,每个应用程序的通用视图。 列表视图 大多数应用程序在Play Store都有一个ListView, ListView的基本思想是管理一系列的数据,当数据被用户动态创建时,你永远不会知道它的大小。ListView是最好的解决方案,您只为单个数据创建模板视图,适配器将应用每个数据项到视图并自动排列到列表中。 ListView是一个视图容器(ViewGroup),它不是一个布局,你不能把项目直接放在ListView上,但你需要创建一个适配器,就像一个中间件提供的视图项目到ListView。 上面的图片显示了ListView是如何工作的,适配器将使用数据并创建视图(列表项),然后将其提供给ListView。 的机制 当你添加适配器到ListView, ListView会要求数据源中的一些数据项,然后ListView会要求在特定位置需要显示在屏幕上的数据项的视图。每当数据源更改后,此过程将重新运行。 注意:ListView每次只存储n+1个项目,其中n是ListView在单个屏幕上不滚动就能显示的最大项目数。 基本项目的MainActivity就是一个很好的例子,看看MainActivity的布局,你只会看到一个ListView。 隐藏,复制Code
<ListViewxmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@android:id/list"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MainActivity"></ListView>
然后查看MainActivity Java代码,您将看到ActivityData实例的集合。 隐藏,收缩,复制Code
List<ActivityData> activityDataList = new ArrayList<ActivityData>();//List of the ActivityData instance, put you ActivityData hereactivityDataList.add(new ActivityData("Login",LoginActivity.class));activityDataList.add(new ActivityData("Welcome",WelcomeActivity.class));activityDataList.add(new ActivityData("Sign up Activity",SignUpActivity.class));activityDataList.add(new ActivityData("Profile Activity",ProfileActivity.class));activityDataList.add(new ActivityData(getString(R.string.title_activity_sample_inflate_view_from_xml),SampleInflateViewFromXmlActivity.class));//add the ActivityData to the ListactivityDataList.add(new ActivityData(getString(R.string.title_activity_sample_create_view_in_java_code),SampleCreateViewInJavaCodeActivity.class));activityDataList.add(new ActivityData("My Fist Activity",MyFirstActivity.class));activityDataList.add(new ActivityData("TextView Example",TextViewExampleActivity.class));activityDataList.add(new ActivityData("EditText Example",EditTextExampleActivity.class));activityDataList.add(new ActivityData("ImageView Example",ImageViewExampleActivity.class));activityDataList.add(new ActivityData("Button Example",ButtonExampleActivity.class));activityDataList.add(new ActivityData("CheckBox Example",CheckBoxExampleActivity.class));activityDataList.add(new ActivityData("LinearLayout Example",LinearLayoutExampleActivity.class));activityDataList.add(new ActivityData("RelativeLayout Example",RelativeLayoutExampleActivity.class));activityDataList.add(new ActivityData("Options Menu Example",OptionsMenuExampleActivity.class));activityDataList.add(new ActivityData("Radio Button Example",RadioButtonExampleActivity.class));activityDataList.add(new ActivityData("Switch Example",SwitchExampleActivity.class));
ActivityData成员: 将在ListView上显示的标题。ActivityClass——用于打开活动的activity类。 我想在ListView上显示这个集合,适配器是我需要的东西。要创建适配器,您需要创建BaseAdapter类。 这些是你需要重写的适配器方法: getCount()—数据源(或集合)中的项数。getItem()——返回特定位置的数据项。getItemId() -返回数据项在特定位置的id。getView() -返回数据项在特定位置的视图实例。 在ActivityDataListAdapter中,我创建了使用上下文和ActivityData集合作为参数的构造。 隐藏,复制Code
public class ActivityDataListAdapter extends BaseAdapter { private Context mContext; private List mItems; public ActivityDataListAdapter(Context context,List items) { mContext = context; mItems = items; } ...}
然后我创建了用于管理集合的方法。 隐藏,复制Code
public void add(ActivityData activityData){ mItems.add(activityData); notifyDataSetChanged();}public void addAll(List items){ mItems.addAll(items); notifyDataSetChanged();}public void remove(int index){ mItems.remove(index); notifyDataSetChanged();}public void remove(ActivityData activityData){ mItems.remove(activityData); notifyDataSetChanged();}
注意:notifyDataSetChanged()方法用于请求ListView重新设置。您需要在数据源中添加、删除、编辑项之后调用它。 getCount()方法将返回数据源大小。 隐藏,复制Code
@Overridepublic int getCount() { return mItems.size();}
getItem()方法将返回位于特定位置的数据项 隐藏,复制Code
@Overridepublic ActivityData getItem(int i) { return mItems.get(i);}
我们的数据没有id属性,在getItemId()方法中只返回一个0。 隐藏,复制Code
@Override public long getItemId(int i) { return 0; }
然后我需要创建在getView()方法中使用的视图。我已经创建了一个视图,包含2 TextView,第一个为标题和另一个活动类名。 listitem_activity_data.xml: 隐藏,收缩,复制Code
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"android:padding="8dp"> <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceLarge"android:text="@string/listitem_textview_default_activity_title"android:id="@+id/textview_title"android:padding="8dp"/> <TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textAppearance="?android:attr/textAppearanceSmall"android:text="@string/listitem_textview_activity_class_name"android:id="@+id/textview_class"android:padding="8dp"/></LinearLayout>
注意:列表项布局的名称应该以单词“listitem”开头。 然后,重写getView()方法 隐藏,收缩,复制Code
@Overridepublic View getView(int i, View view, ViewGroup viewGroup) { if(view == null) { view = LayoutInflater.from(mContext).inflate(R.layout.listitem_activity_data,null); } ActivityData activityData = getItem(i); String title = activityData.getTitle(); Class clazz = activityData.getActivityClass(); TextView titleTextView = (TextView)view.findViewById(R.id.textview_title); TextView classTextView = (TextView)view.findViewById(R.id.textview_class); if(title==null) titleTextView.setText(mContext.getString(R.string.listitem_textview_default_activity_title)); else titleTextView.setText(title); if(clazz==null) classTextView.setText(mContext.getString(R.string.listitem_textview_activity_class_name)); else classTextView.setText(clazz.getSimpleName()); return view;}
getView()方法中有整数、视图和ViewGroup参数,第一个参数是当前位置,第二个是当前项目的视图,第三个是ListView实例。首先,我检查一个视图实例是否不存在,膨胀一个新的,然后在特定位置获取项目,获取视图实例并设置数据。 回到MainActivity Java cocde,创建ActivityDataListAdapter的实例,并将其设置为ListView。 隐藏,复制Code
ActivityDataListAdapter activityDataListAdapter = new ActivityDataListAdapter(this,activityDataList);ListView listView = (ListView)findViewById(android.R.id.list);listView.setAdapter(activityDataListAdapter);
当你运行应用程序时,你会看到像这样的ActivityData列表。 现在,通过实现OnItemC,在用户单击列表项时添加操作lickListener。 隐藏,收缩,复制Code
AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { ActivityData activityData = (ActivityData)adapterView.getAdapter().getItem(i);//get the selected item from the Adapter if(activityData.getActivityClass()!=null) { try{ Intent intent = new Intent(MainActivity.this, activityData.getActivityClass());//create the intent for start the new Activity startActivity(intent);//start the new Activity } catch(ActivityNotFoundException e)//Activity not found or the class that you provide is not an Activity { AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);//Create alert dialog builder builder.setIcon(R.drawable.ic_error);//set dialog icon to drawable resource builder.setTitle(R.string.error_dialog_title);//set dialog title builder.setMessage( String.format( getString(R.string.error_dialog_activity_not_found_message), activityData.getActivityClass().getSimpleName() ) );//set dialog message builder.setPositiveButton(android.R.string.ok,null);//set positive button title and action builder.show();//show the dialog } } }};
这个OnItemClickListener实例将把用户带到他/她选择的活动,或者如果没有发现活动,将显示错误。 然后设置ListView在项目被点击时调用这个监听器。 隐藏,复制Code
@Override protected void onCreate(Bundle savedInstanceState) { ... listView.setOnItemClickListener(onItemClickListener); }
完成! ! 熟悉的视图:GridView, Spinner。 创建UserListActivity 现在,您已经了解了ListView和适配器。提示您创建UserListActivity,让我们现在开始吧!! 首先,您需要创建活动和布局。然后将ListView添加到布局文件中。 隐藏,复制Code
<ListViewxmlns: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"tools:context="me.vable.android.viewandlayoutlessons.UserListActivity"android:id="@android:id/list"></ListView>
其次,为用户项创建视图。 隐藏,收缩,复制Code
<?xmlversion="1.0"encoding="utf-8"?><LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:orientation="horizontal"android:layout_width="match_parent"android:layout_height="66dp"> <ImageViewandroid:id="@+id/imageview_profile"android:src="@drawable/ic_man"android:layout_width="50dp"android:layout_height="50dp"android:adjustViewBounds="true"android:layout_margin="8dp"/> <TextViewandroid:id="@+id/textview_username"android:layout_gravity="center_vertical"android:text="Username"android:textSize="18sp"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_margin="8dp"/></LinearLayout>
第三,创建使用用户列表中的数据的适配器名称UserListAdapter。 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons.data.adapter;import android.content.Context;import android.media.Image;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.TextView;import java.util.List;import me.vable.android.viewandlayoutlessons.R;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.service.UserService;/** * Created by Varavut on 8/23/2014. */public class UserListAdapter extends BaseAdapter { Context mContext; ListmItems; public UserListAdapter(Context context,List users) { mContext = context; mItems = users; } @Override public int getCount() { return mItems.size(); } @Override public User getItem(int i) { return mItems.get(i); } @Override public long getItemId(int i) { return 0; } @Override public View getView(int i, View view, ViewGroup viewGroup) { if(view == null) { view = LayoutInflater.from(mContext).inflate(R.layout.listitem_user,null); } User user = getItem(i); ImageView profileImageView = (ImageView)view.findViewById(R.id.imageview_profile); TextView usernameTextView = (TextView)view.findViewById(R.id.textview_username); profileImageView.setImageBitmap(UserService.getInstance(mContext).getProfileImage(user)); usernameTextView.setText(user.getUsername()); return view; }}
接下来,从UserService获取用户列表,在UserListActivity java代码中创建UseListAdapter的实例,并将其设置为ListView。 以下是我的代码: 隐藏,收缩,复制Code
package me.vable.android.viewandlayoutlessons;import android.app.Activity;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.view.Menu;import android.view.MenuItem;import android.widget.ListView;import java.util.ArrayList;import java.util.List;import me.vable.android.viewandlayoutlessons.data.User;import me.vable.android.viewandlayoutlessons.data.adapter.UserListAdapter;import me.vable.android.viewandlayoutlessons.data.service.UserService;public class UserListActivity extends ActionBarActivity { Listusers = new ArrayList (); UserListAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_user_list); adapter = new UserListAdapter(this, users); UserService.getInstance(this).getUserList(getUserListListener); ListView userListView = (ListView) findViewById(android.R.id.list); userListView.setAdapter(adapter); } UserService.GetUserListListener getUserListListener = new UserService.GetUserListListener() { @Override public void onResponce(boolean success, String message, List userList) { if(success) { users.clear(); adapter.notifyDataSetChanged(); users.addAll(userList); adapter.notifyDataSetChanged(); } } };}
当用户点击列表项时,应用程序将导航到UserProfileActivity。 隐藏,复制Code
@Overrideprotected void onCreate(Bundle savedInstanceState) { ... userListView.setOnItemClickListener(onItemClickListener);}AdapterView.OnItemClickListener onItemClickListener = new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { Intent intent = new Intent(UserListActivity.this,ProfileActivity.class); intent.putExtra("user",adapter.getItem(i)); startActivity(intent); }};
最后,回到WelcomeActivity,这里有一个没有操作的用户列表菜单。添加用于打开UserListActivity的操作。 隐藏,复制Code
@Overridepublic boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); if (id == R.id.menu_user_list) { goToUserListPage(); return true; }else if (id == R.id.menu_profile) { goToMenuProfilePage(); return true; }else if (id == R.id.menu_logout) { logout(); return true; } return super.onOptionsItemSelected(item);}private void goToUserListPage(){ Intent intent = new Intent(this,UserListActivity.class); startActivity(intent);}
运行应用程序并尝试使用每个函数!! 完整的项目存储库 ViewAndLayoutLessons GitHub上 的兴趣点 Android提供了许多基本视图和ViewGroup组件,而且你可以创建自己的自定义视图和复合视图。这篇文章只是Android视图系统的一小部分,还有更多的视图需要你学习。跳你enjou你的Android应用开发者生活!! 历史 24/08/2014初始提交。 24/08/2014添加熟悉的视图信息。 24/08/2014更正拼写错误的单词 25/08/2014更正设备信息 本文转载于:http://www.diyabc.com/frontweb/news30348.html
更多相关文章
- Android(安卓)软键盘使用总结
- Android解决CoordinatorLayout折叠布局RecyclerView最后一条数据
- 强烈推荐:Android完全自学从零开始
- 使用DrawerLayout实现侧滑栏
- android界面设计(一)侧边栏的两种实现方式
- 从任意位置加载XML布局
- android 动态修改菜单menu
- Android(安卓)API 中文 (53) —— BaseAdapter
- TextView设置中文粗体