Android开发系列(十一) QQ登陆界面——Android控件使用实例
這是手機(jī)QQ2013官方版的登錄界面:
?
這個(gè)是我自己做出來(lái)的 QQ登錄界面:
?
當(dāng)然與官方版相比還是有很大的差距,不過對(duì)于學(xué)習(xí)安卓控件的使用已經(jīng)足夠了。
為實(shí)現(xiàn)上述界面,需要有幾個(gè)關(guān)鍵的知識(shí)點(diǎn)需要學(xué)習(xí):
一、實(shí)現(xiàn)圓角的效果——學(xué)會(huì)使用描述背景的drawable/中的 xml文件
需要在drawable文件夾中創(chuàng)建xml文件,文件的父控件類型為shape,在shape父控件中,有<solid/> ?<corners/> <stroke/> <padding/> 等屬性,分別處理背景的填充顏色、邊角的曲率、邊框線的寬度和顏色、上下左右內(nèi)邊框(即背景超出使用改背景的空間的寬度)
?????例如,若想實(shí)現(xiàn)一個(gè)圓角的ImageButton,可以創(chuàng)建一個(gè) fillet_shape.xml文件
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" ><solid android:color="#ffffff"/><corners android:radius="10px"/><padding android:left="3dip" android:top="3dip" android:right="3dip" android:bottom="3dip"/></shape> 然后在Activity類中用ImageButton的實(shí)例設(shè)置setBackgroundResource(); 或者在xml布局文件中在配置控件屬性使用? android:background="@drawable/fillet_shape"
注意這里在配置好背景之后,在為ImageView設(shè)置顯示的圖片時(shí),只能使用setImageResource()而不能使用setBackgroundResource();
學(xué)會(huì)這點(diǎn)很重要,后面就可以舉一反三,本例中使用該方法為 EditText設(shè)置了邊框,為L(zhǎng)istView的每一個(gè)Item設(shè)置了邊框,為按鈕設(shè)置了圓角背景。就不再特殊說(shuō)明
?
二、RelativeLayout中控件的布局問題
不同控件之間是可以覆蓋的,注意在布局文件中后配置的空間可以覆蓋掉之前配置的空間,所以本例在布局文件中讓ListView控件放在了最后,另外如果想要一個(gè)控件暫時(shí)消失
可以使用setVisibility(View.GONE);的方法,這樣改控件消失以后被覆蓋的空間就可以正常使用了。另外本例在EditText中添加按鈕并沒有自定義EditText,而是直接通過布局文件的描述將聯(lián)系人游標(biāo)(小箭頭)嵌在了Edittext中。注意這里一般不使用View.INVISIBLE,這樣控件并未消失
?
三、notifyDataSetChanged方法是BaseAdapter的方法,所以可以在構(gòu)造的適配器內(nèi)部或者創(chuàng)建的適配器對(duì)象使用。
?
四、并不是只有Button可以設(shè)置OnClickListener? 實(shí)際上很多常見的空間都可以使用,如EditText或者TextView ,這個(gè)應(yīng)該是屬于View的抽象方法
?
五、ListView如何調(diào)整每一個(gè)Item邊框的寬度并且避免Item之間的分割線顏色太深?
????? 方法就是上面介紹的自定義drawable/ 中xml文件,來(lái)配置邊和背景屬性,另外在配置ListView控件的屬性時(shí) 設(shè)置android:divider="#aaaaaa" android:dividerHeight="0px"? 這樣可以是ListItem的邊框做出上圖所示的效果。
?
六、怎樣解決ListView中添加Button之后就不響應(yīng)單擊事件的問題?
原因是Button搶奪了焦點(diǎn),最簡(jiǎn)單的解決辦法是:在自定義的每一個(gè)ListItem的布局文件中在根標(biāo)簽的屬性中添加上 android:descendantFocusability="blocksDescendants" 即拒絕ListItem中的子控件獲得焦點(diǎn)
?
七、怎樣實(shí)現(xiàn)在點(diǎn)擊某個(gè)控件以外的屏幕區(qū)域就使該控件消失的效果?本例中實(shí)現(xiàn)在點(diǎn)擊ListView以外的區(qū)域就會(huì)使ListView消失的效果。
方法是覆寫MainActivity的onTouchEvent()方法,根據(jù)點(diǎn)擊的坐標(biāo)(x,y)與目標(biāo)控件通過getLocation獲得的控件左上角坐標(biāo),再結(jié)合目標(biāo)控件的寬和高,判斷點(diǎn)擊的點(diǎn)是否在控件內(nèi),進(jìn)而決定對(duì)該控件執(zhí)行怎樣的操作。
例子:
@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubif(event.getAction()==MotionEvent.ACTION_DOWN && isVisible){int[] location=new int[2];//調(diào)用getLocationInWindow方法獲得某一控件在窗口中左上角的橫縱坐標(biāo) loginList.getLocationInWindow(location);//獲得在屏幕上點(diǎn)擊的點(diǎn)的坐標(biāo)int x=(int)event.getX(); int y=(int)event.getY();if(x<location[0]|| x>location[0]+loginList.getWidth() ||y<location[1]||y>location[1]+loginList.getHeight()){isIndicatorUp=false;isVisible=false;listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);loginList.setVisibility(View.GONE); //讓ListView列表消失,并且讓游標(biāo)向下指! }}return super.onTouchEvent(event);}
以上就是我在寫程序的過程中遇到的一些難題,天有些晚了,直接上所有的代碼吧。。
?
首先布局文件activity_main.xml
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context=".MainActivity"android:background="#dde1ee" ><ImageView android:id="@+id/myImage"android:layout_width="70dip"android:layout_height="70dip"android:layout_marginTop="65dip"android:layout_centerHorizontal="true"android:background="@drawable/fillet_shape"/><EditText android:id="@+id/qqNum"android:layout_width="match_parent"android:layout_height="40dip"android:layout_marginLeft="30dip"android:layout_marginRight="30dip"android:layout_marginTop="15dip"android:paddingLeft="50dip"android:layout_below="@id/myImage"android:inputType="number"android:background="@drawable/qqnum_edit"/><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="賬號(hào)"android:textSize="8pt"android:textColor="@android:color/darker_gray"android:layout_alignLeft="@id/qqNum"android:layout_alignTop="@id/qqNum"android:layout_marginTop="9dip"android:layout_marginLeft="3dip"/><EditText android:id="@+id/qqPassword"android:layout_width="match_parent"android:layout_height="40dip"android:paddingLeft="50dip"android:layout_marginLeft="30dip"android:layout_marginRight="30dip"android:layout_below="@id/qqNum"android:background="@drawable/qqnum_edit"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="密碼"android:textSize="8pt"android:textColor="@android:color/darker_gray"android:layout_alignLeft="@id/qqPassword"android:layout_alignTop="@id/qqPassword"android:layout_marginTop="9dip"android:layout_marginLeft="3dip"/><ImageButtonandroid:id="@+id/qqListIndicator"android:layout_width="22dip"android:layout_height="20dip"android:layout_marginBottom="8dip"android:layout_marginRight="3dip"android:layout_alignBottom="@+id/qqNum"android:layout_alignRight="@+id/qqNum"android:background="@drawable/indicator_down" /><ImageButton android:id="@+id/delete_button_edit"android:layout_width="18dip"android:layout_height="18dip"android:layout_marginBottom="8dip"android:layout_marginRight="3dip"android:layout_alignBottom="@+id/qqNum"android:layout_toLeftOf="@id/qqListIndicator"android:background="@drawable/delete_button_edit"android:visibility="gone"/><Button android:id="@+id/qqLoginButton"android:layout_width="match_parent"android:layout_height="35dip"android:layout_below="@id/qqPassword"android:layout_alignLeft="@id/qqNum"android:layout_alignRight="@id/qqNum"android:layout_marginTop="20dip"android:background="@drawable/login_button_back"android:text="登錄"android:textColor="@android:color/white"/><TextView android:id="@+id/fetchPassword"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentBottom="true"android:layout_alignParentLeft="true"android:layout_below="@id/qqLoginButton"android:layout_marginLeft="45dip"android:text="找回密碼"android:textSize="7pt"android:textColor="#333355"android:gravity="bottom"/><TextView android:id="@+id/registQQ"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/qqLoginButton"android:layout_alignParentBottom="true"android:layout_alignParentRight="true"android:layout_marginRight="45dip"android:layout_marginTop="5dip"android:text="注冊(cè)賬號(hào)"android:textSize="7pt"android:textColor="#333355"android:gravity="bottom"/><TextView android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_below="@id/qqLoginButton"android:text="|"android:textSize="7pt"android:layout_alignParentBottom="true"android:layout_centerHorizontal="true"android:gravity="bottom"/><ListViewandroid:id="@+id/loginQQList"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_above="@id/registQQ"android:layout_alignLeft="@id/qqNum"android:layout_alignRight="@id/qqNum"android:layout_below="@id/qqNum"android:focusable="true"android:focusableInTouchMode="true"android:visibility="gone"android:divider="#aaaaaa"android:dividerHeight="0px"/></RelativeLayout>
listItem的布局文件:
至于實(shí)現(xiàn)圓角等邊框效果的xml布局文件就不再添加,上面第一條已經(jīng)給出例子,可以根據(jù)需要的效果進(jìn)行推廣。
?
然后就是MainActivity文件,這里為了適配器類等夠?qū)ctivity界面進(jìn)行更改,將適配器類寫成了MainActivity類的內(nèi)部類,代碼中有說(shuō)明。另外相當(dāng)一部分代碼是為了實(shí)現(xiàn)一些細(xì)節(jié)性的東西,如EditText中游標(biāo)的的方向變化,圖片圖案的變化,使用了一些常量。
package com.example.android_qq_login;import java.util.ArrayList; import java.util.HashMap; import com.qqlist.contactor.UserInfo;import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.view.LayoutInflater; import android.view.Menu; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.View.OnClickListener; import android.widget.*; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemSelectedListener;public class MainActivity extends Activity {TextView textFetchPassWord=null,textRegister=null;Button loginButton=null;ImageButton listIndicatorButton=null, deleteButtonOfEdit=null;ImageView currentUserImage=null;ListView loginList=null;EditText qqEdit=null, passwordEdit=null;private static boolean isVisible=false; //ListView是否可見private static boolean isIndicatorUp=false; //指示器的方向public static int currentSelectedPosition=-1; //用于記錄當(dāng)前選擇的ListView中的QQ聯(lián)系人條目的ID,如果是-1表示沒有選擇任何QQ賬戶,注意在向//List中添加條目或者刪除條目時(shí)都要實(shí)時(shí)更新該currentSelectedPosition String[] from={"userPhoto","userQQ","deletButton"};int[] to={R.id.login_userPhoto,R.id.login_userQQ,R.id.login_deleteButton};ArrayList<HashMap<String,Object>> list=null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textFetchPassWord=(TextView)findViewById(R.id.fetchPassword);textRegister=(TextView)findViewById(R.id.registQQ);loginButton=(Button)findViewById(R.id.qqLoginButton);listIndicatorButton=(ImageButton)findViewById(R.id.qqListIndicator);loginList=(ListView)findViewById(R.id.loginQQList);list=new ArrayList<HashMap<String,Object>>();currentUserImage=(ImageView)findViewById(R.id.myImage);qqEdit=(EditText)findViewById(R.id.qqNum);passwordEdit=(EditText)findViewById(R.id.qqPassword);deleteButtonOfEdit=(ImageButton)findViewById(R.id.delete_button_edit);qqEdit.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(qqEdit.getText().toString().equals("")==false){deleteButtonOfEdit.setVisibility(View.VISIBLE);}}});deleteButtonOfEdit.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// TODO Auto-generated method stub currentUserImage.setImageResource(R.drawable.qqmain);qqEdit.setText("");currentSelectedPosition=-1;deleteButtonOfEdit.setVisibility(View.GONE);}});UserInfo user1=new UserInfo(R.drawable.contact_0,"1234567",R.drawable.deletebutton);UserInfo user2=new UserInfo(R.drawable.contact_1,"10023455",R.drawable.deletebutton);addUser(user1);addUser(user2);//設(shè)置當(dāng)前顯示的被選中的賬戶的頭像if(currentSelectedPosition==-1){currentUserImage.setImageResource(R.drawable.qqmain);qqEdit.setText("");}else{currentUserImage.setImageResource((Integer)list.get(currentSelectedPosition).get(from[0]));qqEdit.setText((String)list.get(currentSelectedPosition).get(from[1]));}MyLoginListAdapter adapter=new MyLoginListAdapter(this, list, R.layout.layout_list_item, from, to);loginList.setAdapter(adapter);loginList.setOnItemClickListener(new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> arg0, View arg1, int arg2,long arg3) {// TODO Auto-generated method stubcurrentUserImage.setImageResource((Integer)list.get(arg2).get(from[0]));qqEdit.setText((String)list.get(arg2).get(from[1]));currentSelectedPosition=arg2;//相應(yīng)完點(diǎn)擊后List就消失,指示箭頭反向! loginList.setVisibility(View.GONE);listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);System.out.println("---------Selected!!");}});listIndicatorButton.setOnClickListener(new OnClickListener(){@Overridepublic void onClick(View v) {// TODO Auto-generated method stubif(isIndicatorUp){isIndicatorUp=false;isVisible=false;listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);loginList.setVisibility(View.GONE); //讓ListView列表消失 }else{isIndicatorUp=true;isVisible=true;listIndicatorButton.setBackgroundResource(R.drawable.indicator_up);loginList.setVisibility(View.VISIBLE);}}});}//繼承onTouchEvent方法,用于實(shí)現(xiàn)點(diǎn)擊控件之外的部分使控件消失的功能private void addUser(UserInfo user){HashMap<String,Object> map=new HashMap<String,Object>();map.put(from[0], user.userPhoto);map.put(from[1], user.userQQ);map.put(from[2], user.deleteButtonRes);list.add(map);}@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubif(event.getAction()==MotionEvent.ACTION_DOWN && isVisible){int[] location=new int[2];//調(diào)用getLocationInWindow方法獲得某一控件在窗口中左上角的橫縱坐標(biāo) loginList.getLocationInWindow(location);//獲得在屏幕上點(diǎn)擊的點(diǎn)的坐標(biāo)int x=(int)event.getX(); int y=(int)event.getY();if(x<location[0]|| x>location[0]+loginList.getWidth() ||y<location[1]||y>location[1]+loginList.getHeight()){isIndicatorUp=false;isVisible=false;listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);loginList.setVisibility(View.GONE); //讓ListView列表消失,并且讓游標(biāo)向下指! }}return super.onTouchEvent(event);}/*** 為了便于在適配器中修改登錄界面的Activity,這里把適配器作為* MainActivity的內(nèi)部類,避免了使用Handler,簡(jiǎn)化代碼* @author DragonGN**/public class MyLoginListAdapter extends BaseAdapter{protected Context context;protected ArrayList<HashMap<String,Object>> list;protected int itemLayout;protected String[] from;protected int[] to;public MyLoginListAdapter(Context context,ArrayList<HashMap<String, Object>> list, int itemLayout,String[] from, int[] to) {super();this.context = context;this.list = list;this.itemLayout = itemLayout;this.from = from;this.to = to;}@Overridepublic int getCount() {// TODO Auto-generated method stubreturn list.size();}@Overridepublic Object getItem(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getItemId(int position) {// TODO Auto-generated method stubreturn position;}class ViewHolder{public ImageView userPhoto;public TextView userQQ;public ImageButton deleteButton;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// TODO Auto-generated method stubViewHolder holder=null;/*currentPosition=position; 不能使用currentPosition,因?yàn)槊坷L制完一個(gè)Item就會(huì)更新currentPosition這樣得到的currentPosition將始終是最后一個(gè)Item的position */if(convertView==null){convertView=LayoutInflater.from(context).inflate(itemLayout, null);holder=new ViewHolder();holder.userPhoto=(ImageView)convertView.findViewById(to[0]);holder.userQQ=(TextView)convertView.findViewById(to[1]);holder.deleteButton=(ImageButton)convertView.findViewById(to[2]);convertView.setTag(holder);}else{holder=(ViewHolder)convertView.getTag();}holder.userPhoto.setBackgroundResource((Integer)list.get(position).get(from[0]));holder.userQQ.setText((String)list.get(position).get(from[1]));holder.deleteButton.setBackgroundResource((Integer)list.get(position).get(from[2]));holder.deleteButton.setOnClickListener(new ListOnClickListener(position));return convertView;}class ListOnClickListener implements OnClickListener{private int position;public ListOnClickListener(int position) {super();this.position = position;}@Overridepublic void onClick(View arg0) {// TODO Auto-generated method stub list.remove(position);//如果刪除的就是當(dāng)前顯示的賬號(hào),那么將主界面當(dāng)前顯示的頭像設(shè)置回初始頭像if(position==currentSelectedPosition){currentUserImage.setImageResource(R.drawable.qqmain);qqEdit.setText("");currentSelectedPosition=-1;}else if(position<currentSelectedPosition){currentSelectedPosition--; //這里小于當(dāng)前選擇的position時(shí)需要進(jìn)行減1操作 }listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);loginList.setVisibility(View.GONE); //讓ListView列表消失,并且讓游標(biāo)向下指! MyLoginListAdapter.this.notifyDataSetChanged(); }}}}?
另外再多附幾張效果圖:
??
轉(zhuǎn)載地址:http://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_11.html?utm_source=tuicool&utm_medium=referral
總結(jié)
以上是生活随笔為你收集整理的Android开发系列(十一) QQ登陆界面——Android控件使用实例的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Exception:must imple
- 下一篇: Android应用开发-MP3音乐播放器