Android开发系列(十一) QQ登陆界面——Android控件使用实例
這是手機QQ2013官方版的登錄界面:
?
這個是我自己做出來的 QQ登錄界面:
?
當然與官方版相比還是有很大的差距,不過對于學習安卓控件的使用已經足夠了。
為實現上述界面,需要有幾個關鍵的知識點需要學習:
一、實現圓角的效果——學會使用描述背景的drawable/中的 xml文件
需要在drawable文件夾中創建xml文件,文件的父控件類型為shape,在shape父控件中,有<solid/> ?<corners/> <stroke/> <padding/> 等屬性,分別處理背景的填充顏色、邊角的曲率、邊框線的寬度和顏色、上下左右內邊框(即背景超出使用改背景的空間的寬度)
?????例如,若想實現一個圓角的ImageButton,可以創建一個 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的實例設置setBackgroundResource(); 或者在xml布局文件中在配置控件屬性使用? android:background="@drawable/fillet_shape"
注意這里在配置好背景之后,在為ImageView設置顯示的圖片時,只能使用setImageResource()而不能使用setBackgroundResource();
學會這點很重要,后面就可以舉一反三,本例中使用該方法為 EditText設置了邊框,為ListView的每一個Item設置了邊框,為按鈕設置了圓角背景。就不再特殊說明
?
二、RelativeLayout中控件的布局問題
不同控件之間是可以覆蓋的,注意在布局文件中后配置的空間可以覆蓋掉之前配置的空間,所以本例在布局文件中讓ListView控件放在了最后,另外如果想要一個控件暫時消失
可以使用setVisibility(View.GONE);的方法,這樣改控件消失以后被覆蓋的空間就可以正常使用了。另外本例在EditText中添加按鈕并沒有自定義EditText,而是直接通過布局文件的描述將聯系人游標(小箭頭)嵌在了Edittext中。注意這里一般不使用View.INVISIBLE,這樣控件并未消失
?
三、notifyDataSetChanged方法是BaseAdapter的方法,所以可以在構造的適配器內部或者創建的適配器對象使用。
?
四、并不是只有Button可以設置OnClickListener? 實際上很多常見的空間都可以使用,如EditText或者TextView ,這個應該是屬于View的抽象方法
?
五、ListView如何調整每一個Item邊框的寬度并且避免Item之間的分割線顏色太深?
????? 方法就是上面介紹的自定義drawable/ 中xml文件,來配置邊和背景屬性,另外在配置ListView控件的屬性時 設置android:divider="#aaaaaa" android:dividerHeight="0px"? 這樣可以是ListItem的邊框做出上圖所示的效果。
?
六、怎樣解決ListView中添加Button之后就不響應單擊事件的問題?
原因是Button搶奪了焦點,最簡單的解決辦法是:在自定義的每一個ListItem的布局文件中在根標簽的屬性中添加上 android:descendantFocusability="blocksDescendants" 即拒絕ListItem中的子控件獲得焦點
?
七、怎樣實現在點擊某個控件以外的屏幕區域就使該控件消失的效果?本例中實現在點擊ListView以外的區域就會使ListView消失的效果。
方法是覆寫MainActivity的onTouchEvent()方法,根據點擊的坐標(x,y)與目標控件通過getLocation獲得的控件左上角坐標,再結合目標控件的寬和高,判斷點擊的點是否在控件內,進而決定對該控件執行怎樣的操作。
例子:
@Overridepublic boolean onTouchEvent(MotionEvent event) {// TODO Auto-generated method stubif(event.getAction()==MotionEvent.ACTION_DOWN && isVisible){int[] location=new int[2];//調用getLocationInWindow方法獲得某一控件在窗口中左上角的橫縱坐標 loginList.getLocationInWindow(location);//獲得在屏幕上點擊的點的坐標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列表消失,并且讓游標向下指! }}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="賬號"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="注冊賬號"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的布局文件:
至于實現圓角等邊框效果的xml布局文件就不再添加,上面第一條已經給出例子,可以根據需要的效果進行推廣。
?
然后就是MainActivity文件,這里為了適配器類等夠對Activity界面進行更改,將適配器類寫成了MainActivity類的內部類,代碼中有說明。另外相當一部分代碼是為了實現一些細節性的東西,如EditText中游標的的方向變化,圖片圖案的變化,使用了一些常量。
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; //用于記錄當前選擇的ListView中的QQ聯系人條目的ID,如果是-1表示沒有選擇任何QQ賬戶,注意在向//List中添加條目或者刪除條目時都要實時更新該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);//設置當前顯示的被選中的賬戶的頭像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;//相應完點擊后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方法,用于實現點擊控件之外的部分使控件消失的功能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];//調用getLocationInWindow方法獲得某一控件在窗口中左上角的橫縱坐標 loginList.getLocationInWindow(location);//獲得在屏幕上點擊的點的坐標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列表消失,并且讓游標向下指! }}return super.onTouchEvent(event);}/*** 為了便于在適配器中修改登錄界面的Activity,這里把適配器作為* MainActivity的內部類,避免了使用Handler,簡化代碼* @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,因為每繪制完一個Item就會更新currentPosition這樣得到的currentPosition將始終是最后一個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);//如果刪除的就是當前顯示的賬號,那么將主界面當前顯示的頭像設置回初始頭像if(position==currentSelectedPosition){currentUserImage.setImageResource(R.drawable.qqmain);qqEdit.setText("");currentSelectedPosition=-1;}else if(position<currentSelectedPosition){currentSelectedPosition--; //這里小于當前選擇的position時需要進行減1操作 }listIndicatorButton.setBackgroundResource(R.drawable.indicator_down);loginList.setVisibility(View.GONE); //讓ListView列表消失,并且讓游標向下指! MyLoginListAdapter.this.notifyDataSetChanged(); }}}}?
另外再多附幾張效果圖:
??
轉載地址:http://www.cnblogs.com/carlos-vic/p/Carlos_V_Android_11.html?utm_source=tuicool&utm_medium=referral
總結
以上是生活随笔為你收集整理的Android开发系列(十一) QQ登陆界面——Android控件使用实例的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Exception:must imple
- 下一篇: 播放器代码大全