您现在的位置是:网站首页> Android
界面相关技术收集
- Android
- 2024-12-18
- 1104人已阅读
界面相关技术收集
常用界面XML
splash.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</LinearLayout>
splash.java
public class splash extends Activity implements Runnable {
/** Called when the activity is first created. */
private Handler mHandler = new Handler(){
public void handleMessage(Message msg)
{
switch (msg.what)
{
default:
{
Intent iMain = new Intent(splash.this,login.class);
startActivity (iMain);
finish();
}
break;
}
};
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.splash);
Resources res = getResources();
Drawable drawable = res.getDrawable(R.drawable.splash);
this.getWindow().setBackgroundDrawable(drawable);
Thread m_Thread=new Thread(this);
m_Thread.start();
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Message message = new Message();
message.what = 1;
mHandler.sendMessage(message);
}
}
login.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bkcolor"
xmlns:android="http://schemas.android.com/apk/res/android">
<RelativeLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@color/bkcolor"
>
<ImageView android:id="@+id/dxlg" android:layout_width="fill_parent" android:layout_height="wrap_content"
android:src="@drawable/dxlg"
android:layout_marginTop="25.0dip"
/>
<EditText android:id="@+id/editUsername" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginLeft="15.0dip" android:layout_marginTop="25.0dip" android:layout_marginRight="15.0dip" android:hint="输入登录名" android:layout_alignParentLeft="true" android:layout_alignWithParentIfMissing="false" android:inputType="text" android:isScrollContainer="false" android:layout_below="@id/dxlg"/>
<EditText android:id="@+id/editPassword" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="9.0dip" android:hint="输入口令" android:layout_below="@id/editUsername" android:layout_alignLeft="@id/editUsername" android:layout_alignRight="@id/editUsername" android:inputType="textPassword" android:isScrollContainer="false" />
<CheckBox
android:id="@+id/checkRmPassword"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="15.0dip"
android:text="记住口令"
android:layout_below="@id/editPassword"
android:layout_alignLeft="@id/editPassword"
android:textColor="@color/forcolor"
/>
<Button android:textSize="16.0dip"
android:id="@+id/buttonLogin"
android:layout_width="90.0dip"
android:layout_height="45.0dip"
android:layout_marginTop="15.0dip"
android:text="登录"
android:layout_below="@id/checkRmPassword"
android:layout_alignLeft="@id/checkRmPassword" />
<Button android:textSize="16.0dip" android:id="@+id/buttonCancel"
android:layout_width="90.0dip" android:layout_height="45.0dip" android:text="取消" android:layout_toRightOf="@id/buttonLogin" android:layout_alignTop="@id/buttonLogin" />
<Button android:textSize="16.0dip" android:id="@+id/buttonUpdate" android:layout_width="90.0dip" android:layout_height="45.0dip" android:text="升级" android:layout_toRightOf="@id/buttonCancel" android:layout_alignTop="@id/buttonLogin"
/>
</RelativeLayout>
</ScrollView>
login.java
public class login extends BaseHttpActivity{
public android.view.View.OnClickListener handler=null;
public EditText m_userID=null,m_userPwd=null;
public CheckBox m_CheckBox=null;
private iniInfo m_iniInfo=new iniInfo();
private XNini m_XNini=new XNini();
wlbJson m_wlbJson=new wlbJson();
public boolean bPost=false;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg)
{
switch (msg.what)
{
default:
{
}
break;
}
};
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login);
m_XNini.m_ParentActivity=this;
m_XNini.ReadIni(m_iniInfo);
handler = new View.OnClickListener()
{
public void onClick(View v)
{
switch (v.getId())
{
case R.id.buttonLogin:
{
LG();
}
break;
case R.id.buttonCancel:
{
android.os.Process.killProcess(android.os.Process.myPid());
}
break;
case R.id.buttonUpdate:
TrySoft();
break;
}
}
};
findViewById(R.id.buttonLogin).setOnClickListener(handler);
findViewById(R.id.buttonCancel).setOnClickListener(handler);
findViewById(R.id.buttonUpdate).setOnClickListener(handler);
m_userID=(EditText)findViewById(R.id.editUsername);
m_userPwd=(EditText)findViewById(R.id.editPassword);
// m_iniInfo.sUserName="中文测试";
m_userID.setText(m_iniInfo.sUserName);
m_CheckBox=(CheckBox)findViewById(R.id.checkRmPassword);
if(m_iniInfo.bMark)
{
m_userPwd.setText(m_iniInfo.sUserPWD);
m_CheckBox.setChecked(true);
//LG();
}
else
{
}
/*
NetConnect m_NetConnect=new NetConnect();
m_NetConnect.act=this;
this.DisplayToast(m_NetConnect.GetNetType());
m_NetConnect=null;
*/
/*
findViewById(R.id.buttonLogin).setFocusable(true);
findViewById(R.id.buttonLogin).requestFocus(0);
*/
Button m_LGBT=(Button)findViewById(R.id.buttonLogin);
m_LGBT.setFocusable(true);
m_LGBT.setFocusableInTouchMode(true);
m_LGBT.requestFocus();
m_LGBT.requestFocusFromTouch();
}
public void LG()
{
String sName=m_userID.getText().toString();
String sPWD=m_userPwd.getText().toString();
if(sName.equals(""))
{
DisplayToast("请输入登录用户名");
this.m_userID.requestFocus();
return;
}
if(sPWD.equals(""))
{
DisplayToast("请输入登录口令");
this.m_userPwd.requestFocus();
return;
}
m_iniInfo.sUserName=sName;
m_iniInfo.sUserPWD=sPWD;
m_iniInfo.bMark=m_CheckBox.isChecked();
if(!m_iniInfo.bMark)
m_iniInfo.sUserPWD="";
m_XNini.WriteIni(m_iniInfo);
String sUrl=getString(R.string.url);
if(bPost)
{
String sData=m_wlbJson.PackLG(sName, sPWD);
PostHttp(sUrl+"wlb.aspx",sData,"正在登录请稍候...",new onOutAppData()
{
@Override
public void PutAppData(boolean bOK, JSONObject O) {
// TODO Auto-generated method stub
if(O!=null)
{
JSONObject m_userInfo=new JSONObject();
if(m_wlbJson.UnPackLG(O,m_userInfo))
{
try {
String sError=m_userInfo.getString("error");
DisplayToast(sError);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_OtherObject=m_userInfo;
Intent iMain = new Intent(login.this,xjwlb.class);
startActivity (iMain);
finish();
}
}
else
DisplayToast(O.toString());
}
else
{
DisplayToast("由于网络原因登陆失败");
}
}
});
}
else
{
sUrl=getString(R.string.neturl);
sUrl=m_wlbJson.PackLGUrl(sUrl,sName,sPWD);
GetHttp(sUrl,"正在登录请稍候...",new onOutAppData()
{
@Override
public void PutAppData(boolean bOK, JSONObject O) {
// TODO Auto-generated method stub
if(O!=null)
{
JSONObject m_userInfo=new JSONObject();
if(m_wlbJson.UnPackLG(O,m_userInfo))
{
m_OtherObject=m_userInfo;
String sError="";
try {
sError=m_userInfo.getString("error");
DisplayToast(sError);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
Intent iMain = new Intent(login.this,xjwlb.class);
startActivity (iMain);
finish();
}
}
else
DisplayToast(O.toString());
}
else
{
DisplayToast("由于网络原因登陆失败");
}
}
});
}
}
public void TrySoft()
{
UpdateSoft m_UpdateSoft=new UpdateSoft();
m_UpdateSoft.m_ParentActivty=this;
if(bPost)
m_UpdateSoft.PostVer();
else
m_UpdateSoft.GetVer(getString(R.string.updateurl));
}
}
UpdateSoft.java
public class UpdateSoft {
public Activity m_ParentActivty=null;
public ProgressDialog pBar;
private Handler handler = new Handler();
public String sUpdateUrl;
public boolean bShow=true;
public void PostVer()
{
if(m_ParentActivty==null)
return;
PackageManager manager = m_ParentActivty.getPackageManager();
try {
PackageInfo info = manager.getPackageInfo(m_ParentActivty.getPackageName(), 0);
String appVersion = info.versionName; // 版本名
final int nVer=info.versionCode;
final String sUrl=m_ParentActivty.getString(R.string.url)+"wlb.aspx";
new Thread(){
public void run()
{
RealPostVer(sUrl,nVer);
}
}.start();
}
catch (NameNotFoundException e)
{ // TODO Auto-generated catch block
e.printStackTrace();
}
}
public void InitUpdate(String FName)
{
final String TFName=FName;
final String sUrl=m_ParentActivty.getString(R.string.url);
Dialog dialog =
new AlertDialog.Builder(m_ParentActivty).setTitle("系统更新")
.setMessage("发现新版本,请更新!")// 设置内容
.setPositiveButton("确定",// 设置确定按钮
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
pBar =
new ProgressDialog(m_ParentActivty);
pBar.setTitle("正在下载");
pBar.setMessage("请稍候...");
pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
downFile(sUrl+TFName);
}
}).setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// 点击"取消"按钮之后退出程序
}
}).create();// 创建
// 显示对话框
dialog.show();
}
public void InitGetUpdate(String FName)
{
final String sUrl=FName;
Dialog dialog =
new AlertDialog.Builder(m_ParentActivty).setTitle("系统更新")
.setMessage("发现新版本,请更新!")// 设置内容
.setPositiveButton("确定",// 设置确定按钮
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
pBar =
new ProgressDialog(m_ParentActivty);
pBar.setTitle("正在下载");
pBar.setMessage("请稍候...");
pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
downFile(sUrl);
System.out.println(sUrl);
}
}).setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// 点击"取消"按钮之后退出程序
}
}).create();// 创建
// 显示对话框
dialog.show();
}
void downFile(final String url) {
pBar.show();
new Thread() {
public void run() {
HttpClient client = new DefaultHttpClient();
// params[0]代表连接的url
HttpGet get=new HttpGet(url);
HttpResponse response;
try {
response = client.execute(get);
HttpEntity entity = response.getEntity();
long length = entity.getContentLength();
InputStream is = entity.getContent();
FileOutputStream fileOutputStream = null;
if (is != null)
{
File file=new File(Environment.getExternalStorageDirectory(), "XJWLB.apk");
fileOutputStream =new FileOutputStream(file);
byte[] buf =new byte[1024];
int ch = -1;
int count = 0;
while ((ch = is.read(buf)) !=-1)
{
fileOutputStream.write(buf, 0, ch);
count += ch;
if (length >0)
{
}
}
}
fileOutputStream.flush();
if (fileOutputStream !=null)
{
fileOutputStream.close();
}
down();
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}.start();
}
void down() {
handler.post(new Runnable() {
public void run() {
pBar.cancel();
update();
}
});
}
void update()
{
Intent intent =
new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File("/sdcard/XJWLB.apk")),
"application/vnd.android.package-archive");
m_ParentActivty.startActivity(intent);
}
public String PackVer(int nVer)
{
// 先封装一个 JSON 对象
JSONObject Main=new JSONObject();
JSONObject param = new JSONObject();
try {
Main.put("fname","UpdateSoft");
param.put("ver", nVer);
Main.put("param",param);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Main.toString();
}
public boolean RealPostVer(String sUrl,int nVer)
{
HttpClient httpclient=null;
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
String sData=PackVer(nVer);
HttpPost httpPost=new HttpPost(sUrl);
StringEntity entity2;
try {
entity2 = new StringEntity(sData,HTTP.UTF_8);
httpPost.setEntity(entity2);
System.out.println("start开始Post");
HttpResponse httpResponse = httpclient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
System.out.println("end post");
if (entity != null)
{
String result = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
JSONObject O=null;
try {
O = new JSONObject( result);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
boolean bUpdate=false;
String FName;
try {
Object oo=O.get("bUpdate");
bUpdate =false;
if(oo!=null)
{
bUpdate=((Boolean)oo).booleanValue();
}
FName=(String)O.get("FileName");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
if(bUpdate)
HaveNewVer(true,FName);
else
HaveNewVer(false,"");
return true;
}
else
{
HaveNewVer(false,"");
return false;
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
}
public void HaveNewVer(boolean bHave,String FName)
{
final String TFName=FName;
if(bHave)
{
handler.post(new Runnable() {
public void run() {
InitGetUpdate(TFName);
}
});
}
else
{
handler.post(new Runnable() {
public void run() {
if(bShow)
Toast.makeText(m_ParentActivty, "未发现新版本", Toast.LENGTH_SHORT).show();
}
});
}
}
public void GetVer(String sUpUrl)
{
if(m_ParentActivty==null)
return;
PackageManager manager = m_ParentActivty.getPackageManager();
try {
PackageInfo info = manager.getPackageInfo(m_ParentActivty.getPackageName(), 0);
String appVersion = info.versionName; // 版本名
final int nVer=info.versionCode;
final String sUrl=sUpUrl;//m_ParentActivty.getString(R.string.url)+"wlb.aspx";
new Thread(){
public void run()
{
RealGetVer(sUrl,nVer);
}
}.start();
}
catch (NameNotFoundException e)
{ // TODO Auto-generated catch block
e.printStackTrace();
}
}
public boolean RealGetVer(String sUrl,int nVer)
{
HttpClient httpclient=null;
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
String sData=PackVer(nVer);
HttpGet httpget = new HttpGet(sUrl);
StringEntity entity2;
try {
System.out.println("start开始HTTP");
HttpResponse httpResponse = httpclient.execute(httpget);;
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
System.out.println("end post");
if (entity != null)
{
String result = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
JSONObject O=null;
try {
O = new JSONObject( result);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
boolean bUpdate=false;
String FName;
try {
int nTVer=O.getInt("version");
bUpdate =false;
if(nVer<nTVer)
{
bUpdate=true;
}
FName=(String)O.get("update_apk");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
if(bUpdate)
HaveNewVer(true,FName);
else
HaveNewVer(false,"");
return true;
}
else
{
HaveNewVer(false,"");
return false;
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
HaveNewVer(false,"");
return false;
}
}
}
BaseHttpActivity.java
public class BaseHttpActivity extends Activity {
private static XNWebApplication m_XNWebApplication=new XNWebApplication();
public static XYPack m_XYPack=new XYPack();
public static Object m_OtherObject=null;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what)
{
default:
{
ReturnData m_ReturnData=(ReturnData)msg.obj;
if(m_ReturnData!=null)
{
m_ReturnData.m_onOutAppData.PutAppData(m_ReturnData.bOK,m_ReturnData.m_JSONObject);
}
}
break;
}
};
};
public void GetHttp(String sUrl,String sTiShi,onOutAppData m_onOutAppData)
{
//String sUrl="http://192.168.20.215/Test.aspx";
final onOutAppData m_onOutAppData0=m_onOutAppData;
ProgressDialog pdg=null;
if(sTiShi.equals(""))
{
}
else
{
pdg=ShowWait("提示",sTiShi);
pdg.show();
}
final ProgressDialog pdialog=pdg;
//final ProgressDialog pdialog=ProgressDialog.show(this, "提示", "正在等待数据回馈...");
m_XNWebApplication.GetHttp(sUrl,new AppOutNetMsg()
{
@Override
public void PutInNetData(boolean bOK,JSONObject mJSONObject) {
Message message = new Message();
message.what = 1;
ReturnData m_ReturnData=new ReturnData();
m_ReturnData.bOK=bOK;
m_ReturnData.m_JSONObject=mJSONObject;
m_ReturnData.m_onOutAppData=m_onOutAppData0;
// message.obj=XYPack.UnPack(mJSONObject);
if(pdialog!=null)
pdialog.dismiss();
message.obj=m_ReturnData;
mHandler.sendMessage(message);
}
}
);
}
public void PostHttp(String sUrl,String sData,String sTiShi,onOutAppData m_onOutAppData)
{
//String sUrl="http://192.168.20.215/Test.aspx";
final onOutAppData m_onOutAppData0=m_onOutAppData;
final ProgressDialog pdialog=ShowWait("提示",sTiShi);
pdialog.show();
//final ProgressDialog pdialog=ProgressDialog.show(this, "提示", "正在等待数据回馈...");
m_XNWebApplication.PostHttp(sUrl,sData,new AppOutNetMsg()
{
@Override
public void PutInNetData(boolean bOK,JSONObject mJSONObject) {
Message message = new Message();
message.what = 1;
ReturnData m_ReturnData=new ReturnData();
m_ReturnData.bOK=bOK;
m_ReturnData.m_JSONObject=mJSONObject;
m_ReturnData.m_onOutAppData=m_onOutAppData0;
pdialog.dismiss();
message.obj=m_ReturnData;
mHandler.sendMessage(message);
}
}
);
}
public void DisplayToast(String Str)
{
Toast.makeText(this, Str, Toast.LENGTH_SHORT).show();
}
private ProgressDialog ShowWait(String sTitle,String sText)
{
ProgressDialog pdialog = new ProgressDialog(this);
pdialog.setTitle(sTitle);
pdialog.setMessage(sText);
//pdialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//pdialog.setIndeterminate(false);
//pdialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
return pdialog;
}
}
公有类
public interface AppOutNetMsg {
public void PutInNetData(boolean bOK,JSONObject m_JSONObject);
}
public interface HttpWebMsg
{
public void ReturnPostHttp(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData);
public void ReturnGetHttp(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData);
public void ReturnPostHttpData(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData);
}
public interface onOutAppData {
public void PutAppData(boolean bOK,JSONObject O);
}
public class HttpWeb {
public DefaultHttpClient httpclient = new DefaultHttpClient();//维持连接Cookie
public HttpWebMsg m_HttpWebMsg=null;
public HttpWeb()
{
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
public void TestGetNet() throws ClientProtocolException, IOException
{
//DefaultHttpClient httpclient = new DefaultHttpClient();
HttpGet httpget = new HttpGet("http://192.168.20.215/Test.aspx");
HttpResponse httpResponse = httpclient.execute(httpget);
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
if (entity != null)
{
/*
InputStream in=entity.getContent();
byte[] m_NetData=new byte[100];
in.read(m_NetData);
System.out.println("Data:"+new String(m_NetData));
m_NetData=null;
*/
String result = EntityUtils.toString(httpResponse.getEntity());
System.out.println("GET收到数据:"+result);
}
System.out.println("Initial set of cookies:");
Log.e("1","nitial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty())
{
System.out.println("None");
Log.e("1","None");
}
else {
for (int i = 0; i < cookies.size(); i++)
{ System.out.println("- " + cookies.get(i).toString());
Log.e("1",cookies.get(i).toString());
}
}
}
/*
也可以使用 HttpURLConnection直接通过stream发送,这要看服务端是如何接收的,代码如下:
URL url = new URL(url);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("POST");
httpURLConnection.setDoInput(true);
httpURLConnection.setDoOutput(true);
httpURLConnection.setUseCaches(false);
httpURLConnection.setRequestProperty("Charset", "UTF-8");
InputStream is = httpURLConnection.getInputStream();
OutputStream os = httpURLConnection.getOutputStream();
// 使用os发送xml数据,使用is接收服务端返回的数据
is.close();
os.close();
*/
public void TestPost(String sData) throws ClientProtocolException, IOException
{
HttpPost httpPost=new HttpPost("http://192.168.20.215/TestPost.aspx");
//List<NameValuePair> params = new ArrayList<NameValuePair>();
//params.add(new BasicNameValuePair("xml", sData));
//httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
StringEntity entity2 = new StringEntity(sData);
httpPost.setEntity(entity2);//new UrlEncodedFormEntity(params, HTTP.UTF_8));
HttpResponse httpResponse = httpclient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
if (entity != null)
{ //entity.consumeContent();
/*
InputStream in=entity.getContent();
byte[] m_NetData=new byte[100];
in.read(m_NetData);
System.out.println("Data:"+new String(m_NetData));
m_NetData=null;
*/
String result = EntityUtils.toString(httpResponse.getEntity());
System.out.println("POST收到数据:"+result);
}
System.out.println("Initial set of cookies:");
Log.e("1","nitial set of cookies:");
List<Cookie> cookies = httpclient.getCookieStore().getCookies();
if (cookies.isEmpty())
{
System.out.println("Cookies为空");
Log.e("1","None");
}
else {
for (int i = 0; i < cookies.size(); i++)
{
System.out.println("- " + cookies.get(i).toString());
Log.e("1",cookies.get(i).toString());
}
}
}
public boolean GetHttp(String sUrl,AppOutNetMsg m_AppOutNetMsg)
{
if(httpclient==null)
{
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
HttpGet httpget = new HttpGet(sUrl);//"http://192.168.20.215/Test.aspx");
System.out.println("start开始请求");
HttpResponse httpResponse;
try {
httpResponse = httpclient.execute(httpget);
System.out.println("end请求完毕");
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
if (entity != null)
{
String result = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnGetHttp(m_AppOutNetMsg,true,result);
}
return true;
}
else
{
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnGetHttp(m_AppOutNetMsg,false,"");
}
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnGetHttp(m_AppOutNetMsg,false,"");
}
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnGetHttp(m_AppOutNetMsg,false,"");
}
return false;
}
return false;
}
public boolean PostHttpData(String sUrl,String sData,AppOutNetMsg m_AppOutNetMsg)
{
if(httpclient==null)
{
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
HttpPost httpPost=new HttpPost(sUrl);
StringEntity entity2;
try {
entity2 = new StringEntity(sData,HTTP.UTF_8);
httpPost.setEntity(entity2);
System.out.println("start开始Post");
HttpResponse httpResponse = httpclient.execute(httpPost);
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
System.out.println("end post");
if (entity != null)
{
String result = EntityUtils.toString(httpResponse.getEntity(),"UTF-8");
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnPostHttpData(m_AppOutNetMsg,true,result);
}
return true;
}
else
m_HttpWebMsg.ReturnPostHttpData(m_AppOutNetMsg,false,"");
return false;
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttpData(m_AppOutNetMsg,false,"");
return false;
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttpData(m_AppOutNetMsg,false,"");
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttpData(m_AppOutNetMsg,false,"");
return false;
}
}
public boolean PostHttp(String sUrl,List<NameValuePair> params,AppOutNetMsg m_AppOutNetMsg)
{
if(httpclient==null)
{
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
HttpPost httpPost=new HttpPost(sUrl);
//List<NameValuePair> params = new ArrayList<NameValuePair>();
// params.add(new BasicNameValuePair("xml", sData));
try {
httpPost.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return false;
}
HttpResponse httpResponse=null;
try {
httpResponse = httpclient.execute(httpPost);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return false;
}
HttpEntity entity = httpResponse.getEntity();
System.out.println("Login form get: " + httpResponse.getStatusLine());
if (entity != null)
{
String result="";
try {
result = EntityUtils.toString(httpResponse.getEntity());
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return false;
}
//System.out.println("POST收到数据:"+result);
if(m_HttpWebMsg!=null)
{
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,true,result);
}
}
else
m_HttpWebMsg.ReturnPostHttp(m_AppOutNetMsg,false,"");
return true;
}
public void OpenWeb()
{
if(httpclient!=null)
return;
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
public void CloseWeb()
{
httpclient=null;
}
public void ReOpenWeb()
{
if(httpclient!=null)
httpclient=null;
httpclient=new DefaultHttpClient();
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
public void OpenWebProxy()
{
if(httpclient!=null)
return;
httpclient=new DefaultHttpClient();
HttpHost proxy = new HttpHost("10.0.0.172",80);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
public void ReOpenWebProxy()
{
if(httpclient!=null)
httpclient=null;
httpclient=new DefaultHttpClient();
HttpHost proxy = new HttpHost("10.0.0.172",80);
httpclient.getParams().setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
httpclient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 5000);
httpclient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, 5000);
}
}
HttpWork.java
public class HttpWork {
public boolean bWorking;
public String FName;
public AppOutNetMsg m_AppOutNetMsg;
public String sUrl;
public String sData;
}
public class ReturnData {
public onOutAppData m_onOutAppData;
public JSONObject m_JSONObject;
public boolean bOK;
}
XNWebApplication.java
public class XNWebApplication implements HttpWebMsg, Runnable
{
private HttpWeb m_HttpWeb=null;
private XYPack m_XYPack=null;
//private static final String sUrl = "视频监控Ver1.0";
private HttpWork m_HttpWork=new HttpWork();
public XNWebApplication()
{
m_HttpWeb=new HttpWeb();
m_HttpWeb.m_HttpWebMsg=this;
m_XYPack=new XYPack();
m_HttpWork.bWorking=false;
}
public boolean LGWlb(String sUrl,String sUser,String sPwd,AppOutNetMsg m_AppOutNetMsg)
{
if(m_HttpWork.bWorking)
return false;
String sData=m_XYPack.PackLG(sUser, sPwd);
m_HttpWork.bWorking=true;
m_HttpWork.FName="PostHttpData";
m_HttpWork.m_AppOutNetMsg=m_AppOutNetMsg;
m_HttpWork.sData=sData;
m_HttpWork.sUrl=sUrl;
Thread m_Thread=new Thread(this);
m_Thread.start();
return true;
/*
try {
m_HttpWeb.PostHttpData(sUrl, sData,m_AppOutNetMsg);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
*/
}
public boolean PostHttp(String sUrl,String sData,AppOutNetMsg m_AppOutNetMsg)
{
if(m_HttpWork.bWorking)
return false;
m_HttpWork.bWorking=true;
m_HttpWork.FName="PostHttpData";
m_HttpWork.m_AppOutNetMsg=m_AppOutNetMsg;
m_HttpWork.sData=sData;
m_HttpWork.sUrl=sUrl;
Thread m_Thread=new Thread(this);
m_Thread.start();
return true;
}
public boolean GetHttp(String sUrl,AppOutNetMsg m_AppOutNetMsg)
{
/*
try {
m_HttpWeb.GetHttp(sUrl,m_AppOutNetMsg);
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return false;
}
return true;
*/
if(m_HttpWork.bWorking)
return false;
m_HttpWork.bWorking=true;
m_HttpWork.FName="GetHttp";
m_HttpWork.m_AppOutNetMsg=m_AppOutNetMsg;
m_HttpWork.sData="";
m_HttpWork.sUrl=sUrl;
Thread m_Thread=new Thread(this);
m_Thread.start();
return true;
}
@Override
public void ReturnGetHttp(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData) {
// TODO Auto-generated method stub
if(m_AppOutNetMsg!=null)
{
JSONObject result;
try {
result = new JSONObject( sData);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
System.out.println(e.getMessage());
m_AppOutNetMsg.PutInNetData(false,null);
return;
}
m_AppOutNetMsg.PutInNetData(true,result);
}
}
@Override
public void ReturnPostHttp(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData) {
// TODO Auto-generated method stub
if(m_AppOutNetMsg!=null)
{
JSONObject result;
try {
result = new JSONObject( sData);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_AppOutNetMsg.PutInNetData(false,null);
return;
}
m_AppOutNetMsg.PutInNetData(true,result);
}
}
@Override
public void ReturnPostHttpData(AppOutNetMsg m_AppOutNetMsg,boolean bOK,String sData) {
// TODO Auto-generated method stub
if(m_AppOutNetMsg!=null)
{
JSONObject result;
try {
result = new JSONObject( sData);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
m_AppOutNetMsg.PutInNetData(false,null);
return;
}
m_AppOutNetMsg.PutInNetData(true,result);
}
}
@Override
public void run() {
// TODO Auto-generated method stub
if(m_HttpWork.FName=="PostHttpData")
{
m_HttpWeb.PostHttpData(m_HttpWork.sUrl, m_HttpWork.sData,m_HttpWork.m_AppOutNetMsg);
m_HttpWork.bWorking=false;
return ;
}
else
{
if(m_HttpWork.FName=="GetHttp")
{
m_HttpWeb.GetHttp(m_HttpWork.sUrl,m_HttpWork.m_AppOutNetMsg);
m_HttpWork.bWorking=false;
return;
}
}
}
}
XNPack.java
public class XYPack {
public String PackLG(String sUser,String sPWD)
{
// 先封装一个 JSON 对象
JSONObject param = new JSONObject();
try {
param.put("name", sUser);
param.put("password", sPWD);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return param.toString();
}
public boolean UnPackTest(String sResult)
{
JSONObject result;
try {
result = new JSONObject( sResult);
String token = (String)result.get("token");
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return true;
}
/*完美解。NET端Json
*
namespace SessionWeb
{
public class OneUser
{
public string Name;
public string Pic;
}
public class RetData
{
public bool bOK;
public string SessionNum;
public OneUser[] m_AllUser;
}
public partial class _Test : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if(Session["Hello"]==null)
{
Session["Hello"] = 1;
}
else
{
int A =Convert.ToInt32(Session["Hello"].ToString());
A += 1;
Session["Hello"] = A;
}
RetData m_RetData = new RetData();
m_RetData.bOK=true;
m_RetData.SessionNum=Session["Hello"].ToString();
m_RetData.m_AllUser = new OneUser[10];
for(int i=0;i<10;i++)
{
OneUser m_OneUser = new OneUser();
m_OneUser.Name = "xuneng"+i.ToString();
m_OneUser.Pic = i.ToString();
m_RetData.m_AllUser[i] = m_OneUser;
}
string jsonText = JsonConvert.SerializeObject(m_RetData);
Response.Write(jsonText);
//DataTableToJson();
//XmlToJson();
}
public void DataTableToJson()
{
string result = "";
DataTable dt = new DataTable();
dt.Columns.Add("name");//添加一列,想加几列再自己加
dt.Columns.Add("date");//添加一列,想加几列再自己加
DataRow dr;
for (int i = 0; i < 10; i++)//每列添多少行,条件自己加
{
dr = dt.NewRow();
dr["name"] = "1";
dr["date"] = DateTime.Now.ToString();
dt.Rows.Add(dr);//添加一行
}
result = JsonConvert.SerializeObject(dt, new DataTableConverter());
Response.Write(result);
}
public void XmlToJson()
{
string xml = "<?xml version=\"1.0\" standalone=\"no\"?>";
xml+="<root>";
xml += "<ret>true</ret>";
xml+="<person id=\"1\">";
xml+="<name>Alan</name>";
xml+="<url>http://www.google.com</url>";
xml+="</person>";
xml+="<person id=\"2\">";
xml+="<name>Louis</name>";
xml+="<url>http://www.yahoo.com</url>";
xml+="</person>";
xml+="Hello World";
xml+="</root>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(xml);
//XML to JSON
string jsonText = JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented);
Response.Write(jsonText);
}
}
}
*/
static public String UnPack(JSONObject result)
{
String Str="SessionNum=";
try {
Str+=result.get("SessionNum").toString()+"\n";
Str+="bOK="+result.get("bOK").toString()+"\n";
JSONArray array = result.getJSONArray("m_AllUser");
Str+="UserCount="+array.length()+"\n";
int i;
for(i=0;i<array.length();i++)
{
JSONObject m_OneUser=array.getJSONObject(i);
Str+="Name="+m_OneUser.get("Name").toString()+"\n";
Str+="Pic="+m_OneUser.get("Pic").toString()+"\n";
}
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return Str;
}
}
代码
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/bkcolor"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="240dip"
android:gravity="center_horizontal|top"
>
<ImageButton
android:id="@+id/shyButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/shy_bt"
android:layout_marginTop="100dip"
>
</ImageButton>
<ImageButton
android:id="@+id/fkcButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/fkc_bt"
android:layout_marginTop="100dip"
>
</ImageButton>
</LinearLayout>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
android:paddingBottom="4dip"
android:paddingLeft="12dip">
>
<ImageButton
android:id="@+id/szButton"
android:layout_width="81dip"
android:layout_height="60dip"
android:background="@drawable/person_bt"
android:layout_marginTop="100dip"
android:layout_alignParentLeft="true"
android:layout_marginLeft="10dip"
android:layout_weight="1"
>
</ImageButton>
<TextView android:id="@+id/kongLine"
android:layout_width="100dip"
android:layout_height="60px"
android:layout_marginTop="100dip"
android:layout_weight="6"
>
</TextView>
<ImageButton android:layout_marginLeft="12dip"
android:layout_height="60dip"
android:background="@drawable/exit_bt"
android:id="@+id/exitButton"
android:layout_marginTop="100dip"
android:layout_width="81dip"
android:layout_weight="1"
></ImageButton>
</LinearLayout>
</LinearLayout>
xjwlb.java
public class xjwlb extends BaseHttpActivity {
/** Called when the activity is first created. */
public android.view.View.OnClickListener handler=null;
boolean bPost=false;
private Handler mHandler = new Handler(){
public void handleMessage(Message msg)
{
switch (msg.what)
{
default:
{
}
break;
}
};
};
public LGUserInfo GetUserInfo()
{
LGUserInfo m_LGUserInfo=new LGUserInfo();
JSONObject m_userInfo=(JSONObject)m_OtherObject;
JSONObject O;
try {
O = (JSONObject)m_userInfo.get("userInfo");
m_LGUserInfo.yhid=O.getString("yhid");
m_LGUserInfo.lxsj=O.getString("lxsj");
m_LGUserInfo.cc=O.getDouble("cc");
m_LGUserInfo.cx=O.getString("cx");
m_LGUserInfo.dlbs=O.getString("dlbs");
m_LGUserInfo.dqcs=O.getString("dqcs");
m_LGUserInfo.dw=O.getDouble("dw");
m_LGUserInfo.dqsf=O.getString("dqsf");
m_LGUserInfo.yhnc=O.getString("yhnc");
m_LGUserInfo.qymc=O.getString("qymc");
}
catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
return m_LGUserInfo;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
handler = new View.OnClickListener()
{
public void onClick(View v)
{
switch (v.getId())
{
case R.id.szButton:
{
szPerson();
}
break;
case R.id.exitButton:
{
Exit();
}
break;
case R.id.shyButton:
{
shObject();
}
break;
case R.id.fkcButton:
{
fkc();
}
break;
}
}
};
findViewById(R.id.szButton).setOnClickListener(handler);
findViewById(R.id.exitButton).setOnClickListener(handler);
findViewById(R.id.shyButton).setOnClickListener(handler);
findViewById(R.id.fkcButton).setOnClickListener(handler);
LGUserInfo m_LGUserInfo=GetUserInfo();
PZConfig m_PZConfig=new PZConfig();
m_PZConfig.m_ParentActivity=this;
DriverInfo m_DriverInfo=new DriverInfo();
if(m_PZConfig.ReadDriver(m_DriverInfo,m_LGUserInfo.lxsj,m_LGUserInfo.cx,m_LGUserInfo.cc,m_LGUserInfo.dw))
{
if(m_DriverInfo._yhid.equals(m_LGUserInfo.yhid))
{
m_LGUserInfo.lxsj=m_DriverInfo._lxfs;
m_LGUserInfo.cx=m_DriverInfo._cx;
m_LGUserInfo.dw=m_DriverInfo._dw;
m_LGUserInfo.cc=m_DriverInfo._cc;
JSONObject m_userInfo=(JSONObject)m_OtherObject;
try {
JSONObject O = (JSONObject)m_userInfo.get("userInfo");
O.put("lxsj",m_DriverInfo._lxfs);
O.put("cx",m_DriverInfo._cx);
O.put("dw",m_DriverInfo._dw);
O.put("cc",m_DriverInfo._cc);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
TrySoft();
}
public void Exit()
{
new AlertDialog.Builder(this)
.setTitle("提示")
.setIcon(R.drawable.why)
.setMessage("确定退出系统吗?")
.setNegativeButton("取消",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int which) {
}
})
.setPositiveButton("确定",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
finish();
android.os.Process.killProcess(android.os.Process.myPid());
}
}).show();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
// 按下键盘上返回按钮
if (keyCode == KeyEvent.KEYCODE_BACK) {
Exit();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
// 或者下面这种方式
//System.exit(0);
//建议用这种
}
public void szPerson()
{
Intent iPerson = new Intent(xjwlb.this,PersonWindow.class);
startActivity (iPerson);
}
public void shObject()
{
Intent ishObject = new Intent(xjwlb.this,shobject.class);
startActivity (ishObject);
}
public void fkc()
{
Intent iFkc = new Intent(xjwlb.this,publishCar.class);
startActivity (iFkc);
}
public void TrySoft()
{
UpdateSoft m_UpdateSoft=new UpdateSoft();
m_UpdateSoft.m_ParentActivty=this;
m_UpdateSoft.bShow=false;
if(bPost)
m_UpdateSoft.PostVer();
else
m_UpdateSoft.GetVer(getString(R.string.updateurl));
}
}
XNDataSource.Java
public class XNDataSource extends BaseAdapter{
public ArrayList<HashMap<String, Object>> mylist = new ArrayList<HashMap<String, Object>>(); //这里的String表示对第二个字段的标题,后面的Object可以扩展为其他类对象
Activity activity=null;
onItemRender m_onOutItemRender=null;
int nItemRenderID;
public XNDataSource(Activity a,int nListItemResourceID,onItemRender m_onItemRender ){
activity = a;
m_onOutItemRender=m_onItemRender;
nItemRenderID=nListItemResourceID;
}
public int getCount() {
// TODO Auto-generated method stub
return mylist.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return mylist.get(position);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
LayoutInflater inflater =activity.getLayoutInflater();
final View view = inflater.inflate(nItemRenderID, null);
HashMap<String, Object>mOneRow=(HashMap<String, Object>)mylist.get(position);
if(m_onOutItemRender!=null)
{
m_onOutItemRender.RenderOneRow(this,view,position,mOneRow);
}
return view;
}
public void InitData()
{
for(int i=0;i<10;i++)
{
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("icon",R.drawable.icon);
map.put("ItemTitle", "标题字段"+i);
map.put("ItemText", "显示文字字段显示文字字段显示文字字段显示文字字段显示文字字段显示文字字段");
mylist.add(map);
}
}
public void AddOneRow(Object O)
{
HashMap<String, Object> map=(HashMap<String, Object>)O;
mylist.add(map);
XNDataSource.this.notifyDataSetChanged();
}
public void AddOneRow(HashMap<String, Object>m_OneRow)
{
mylist.add(m_OneRow);
XNDataSource.this.notifyDataSetChanged();
}
public void DelOneRow(int position)
{
mylist.remove(position);
XNDataSource.this.notifyDataSetChanged();
}
public void DelAllRow()
{
mylist.removeAll(mylist);
XNDataSource.this.notifyDataSetChanged();
}
}
onItemRender.java
public interface onItemRender {
//渲染每一项接口
public void RenderOneRow(Object BaseAdapter,View m_View,int nPostion,HashMap<String, Object>m_OneRow);
/*
例子
@Override
public void RenderOneRow(Object BaseAdapter,View mView, int nPostion,
HashMap<String, Object> mOneRow) {
// TODO Auto-generated method stub
final ImageView image=(ImageView)mView.findViewById(R.id.ItemImage);
final TextView textTitle = (TextView) mView.findViewById(R.id.ItemTitle);
final TextView textRong = (TextView) mView.findViewById(R.id.ItemText);
final Button button = (Button)mView.findViewById(R.id.buttonDelete);
final Button addbutton = (Button)mView.findViewById(R.id.buttonAdd);
image.setImageResource((Integer)mOneRow.get("icon"));
textTitle.setText(mOneRow.get("ItemTitle").toString());
textRong.setText(mOneRow.get("ItemText").toString());
button.setTag(nPostion);
final Object OO=BaseAdapter;
button.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
int position = Integer.parseInt(v.getTag().toString());
XNDataSource m_XNDataSource=(XNDataSource)OO;
m_XNDataSource.DelOneRow(position);
}});
addbutton.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
// TODO Auto-generated method stub
XNDataSource m_XNDataSource=(XNDataSource)OO;
HashMap<String,Object>map=new HashMap<String,Object>();
map.put("icon",R.drawable.icon);
map.put("ItemTitle", "标题字段"+200);
map.put("ItemText", "显示文字字段");
m_XNDataSource.AddOneRow(map);
}});
}
*/
}
Android——六大基本布局总结
基本理论:
Android六大基本布局分别是:
线性布局LinearLayout
表格布局TableLayout
相对布局RelativeLayout
层布局FrameLayout
绝对布局AbsoluteLayout
网格布局GridLayout。
其中,表格布局是线性布局的子类。网格布局是android 4.0后新增的布局。
在手机程序设计中,绝对布局基本上不用,用得相对较多的是线性布局和相对布局。
(一)线性布局LinearLayout
线性布局在开发中使用最多,具有垂直方向与水平方向的布局方式,通过设置属性“android:orientation”控制方向,属性值垂直(vertical)和水平(horizontal),默认水平方向。
android:gravity:内部控件对齐方式,常用属性值有center、center_vertical、center_horizontal、top、bottom、left、right等。
这个属性在布局组件RelativeLayout、TableLayout中也有使用,FrameLayout、AbsoluteLayout则没有这个属性。
center:居中显示,这里并不是表示显示在LinearLayout的中心,当LinearLayout线性方向为垂直方向时,center表示水平居中,但是并不能垂直居中,此时等同于center_horizontal的作用;同样当线性方向为水平方向时,center表示垂直居中,等同于center_vertical。
top、bottom、left、right顾名思义为内部控件居顶、低、左、右布局。
这里要与android:layout_gravity区分开,layout_gravity是用来设置自身相对于父元素的布局。
android:layout_weight:权重,用来分配当前控件在剩余空间的大小。
使用权重一般要把分配该权重方向的长度设置为零,比如在水平方向分配权重,就把width设置为零。
先来看一下效果:
下面来看看代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<EditText
android:id="@+id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<!--
第一线性布局
LinearLayout一定要设置方向
android:orientation 值:horizontal 元素水平摆放 | vertical 元素垂直摆放
android:gravity="right"设置对齐方式
-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center" >
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="确定"/>
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="取消" />
</LinearLayout>
<!-- 第二线性布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#ff0000"
android:text="红色"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#00ff00"
android:text="绿色"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_weight="1"
android:background="#0000ff"
android:text="蓝色"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="200dp"
android:layout_weight="2"
android:background="#00ffff"
android:text="青色"/>
</LinearLayout>
</LinearLayout>
(二)相对布局RelativeLayout
相对布局可以让子控件相对于兄弟控件或父控件进行布局,可以设置子控件相对于兄弟控件或父控件进行上下左右对齐。
RelativeLayout能替换一些嵌套视图,当我们用LinearLayout来实现一个简单的布局但又使用了过多的嵌套时,就可以考虑使用RelativeLayout重新布局。
相对布局就是一定要加Id才能管理。
RelativeLayout中子控件常用属性:
1、相对于父控件,例如:android:layout_alignParentTop=“true”
android:layout_alignParentTop 控件的顶部与父控件的顶部对齐;
android:layout_alignParentBottom 控件的底部与父控件的底部对齐;
android:layout_alignParentLeft 控件的左部与父控件的左部对齐;
android:layout_alignParentRight 控件的右部与父控件的右部对齐;
2、相对给定Id控件,例如:android:layout_above=“@id/**”
android:layout_above 控件的底部置于给定ID的控件之上;
android:layout_below 控件的底部置于给定ID的控件之下;
android:layout_toLeftOf 控件的右边缘与给定ID的控件左边缘对齐;
android:layout_toRightOf 控件的左边缘与给定ID的控件右边缘对齐;
android:layout_alignBaseline 控件的baseline与给定ID的baseline对齐;
android:layout_alignTop 控件的顶部边缘与给定ID的顶部边缘对齐;
android:layout_alignBottom 控件的底部边缘与给定ID的底部边缘对齐;
android:layout_alignLeft 控件的左边缘与给定ID的左边缘对齐;
android:layout_alignRight 控件的右边缘与给定ID的右边缘对齐;
3、居中,例如:android:layout_centerInParent=“true”
android:layout_centerHorizontal 水平居中;
android:layout_centerVertical 垂直居中;
android:layout_centerInParent 父控件的中央;
先来看一下效果:
版本低了,文本框可以在AndroidManifest.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:padding="10dp"
tools:context="${relativePackage}.${activityClass}" >
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/et1"
android:text="@string/username" />
<EditText
android:id="@+id/et1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/text1"
android:layout_marginTop="23dp"
android:inputType="text"
android:maxLines="12"
android:hint="用户名" />
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/et2"
android:text="@string/pwd" />
<EditText
android:id="@+id/et2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/et1"
android:layout_marginTop="23dp"
android:inputType="text"
android:maxLines="12"
android:layout_toRightOf="@id/text2"
android:hint="密码" />
<Button
android:id="@+id/button1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignBaseline="@+id/button2"
android:layout_alignBottom="@+id/button2"
android:layout_marginRight="14dp"
android:layout_toLeftOf="@+id/button2"
android:text="登录" />
<Button
android:id="@+id/button2"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_alignRight="@+id/et2"
android:layout_below="@+id/et2"
android:layout_marginTop="23dp"
android:text="退出" />
</RelativeLayout>
(三)层布局FrameLayout
帧布局或叫层布局,从屏幕左上角按照层次堆叠方式布局,后面的控件覆盖前面的控件。
该布局在开发中设计地图经常用到,因为是按层次方式布局,我们需要实现层面显示的样式时就可以
采用这种布局方式,比如我们要实现一个类似百度地图的布局,我们移动的标志是在一个图层的上面。
在普通功能的软件设计中用得也不多。层布局主要应用就是地图方面。
上面有三层颜色,点击下面的案列上面会出现对应的样式
activity_main.xml中代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="${relativePackage}.${activityClass}" >
<FrameLayout
android:id="@+id/frame"
android:layout_width="match_parent"
android:layout_margin="20dp"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/text1"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#0000ff" />
<TextView
android:id="@+id/text2"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#00ff00" />
<TextView
android:id="@+id/text3"
android:layout_width="match_parent"
android:layout_height="300dp"
android:background="#ff0000" />
</FrameLayout>
<LinearLayout
android:id="@+id/linear"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginLeft="20dp"
android:background="#0000ff"
android:text="颜色1"/>
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:background="#00ff00"
android:text="颜色2"/>
<Button
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#ff0000"
android:layout_marginRight="20dp"
android:text="颜色3"/>
</LinearLayout>
</LinearLayout>
MainActivity.java中代码:
public class MainActivity extends Activity {
private FrameLayout frame;
private TextView text1;
private TextView text2;
private TextView text3;
private Button button1;
private Button button2;
private Button button3;
private OnClickListener listener = new OnClickListener() {
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.button1:
//删除
frame.removeView(text1);
//创建
frame.addView(text1);
break;
case R.id.button2:
frame.removeViewInLayout(text2);
frame.addView(text2);
break;
case R.id.button3:
frame.removeViewInLayout(text3);
frame.addView(text3);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
frame = (FrameLayout) findViewById(R.id.frame);
text1 = (TextView) findViewById(R.id.text1);
text2 = (TextView) findViewById(R.id.text2);
text3 = (TextView) findViewById(R.id.text3);
button1 = (Button) findViewById(R.id.button1);
button2 = (Button) findViewById(R.id.button2);
button3 = (Button) findViewById(R.id.button3);
button1.setOnClickListener(listener);
button2.setOnClickListener(listener);
button3.setOnClickListener(listener);
}
}
(四)绝对布局AbsoluteLayout
绝对布局中将所有的子元素通过设置android:layout_x 和 android:layout_y属性,将子元素的坐标位置固定下来,即坐标(android:layout_x, android:layout_y) ,layout_x用来表示横坐标,layout_y用来表示纵坐标。屏幕左上角为坐标(0,0),横向往右为正方,纵向往下为正方。实际应用中,这种布局用的比较少,因为Android终端一般机型比较多,各自的屏幕大小。分辨率等可能都不一样,如果用绝对布局,可能导致在有的终端上显示不全等。所有基本不会使用,这里就不多介绍了。
(五)表格布局TableLayout
表格布局,适用于多行多列的布局格式,每个TableLayout是由多个TableRow组成,一个TableRow就表示TableLayout中的每一行,这一行可以由多个子元素组成。实际上TableLayout和TableRow都是LineLayout线性布局的子类。但是TableRow的参数android:orientation属性值固定为horizontal,且android:layout_width=MATCH_PARENT,android:layout_height=WRAP_CONTENT。所以TableRow实际是一个横向的线性布局,且所以子元素宽度和高度一致。
注意:在TableLayout中,单元格可以为空,但是不能跨列,意思是只能不能有相邻的单元格为空。
TableLayout常用属性:
android:shrinkColumns:设置可收缩的列,内容过多就收缩显示到第二行
android:stretchColumns:设置可伸展的列,将空白区域填充满整个列
android:collapseColumns:设置要隐藏的列
列的索引从0开始,shrinkColumns和stretchColumns可以同时设置。
子控件常用属性:
android:layout_column:第几列
android:layout_span:占据列数
效果图是一个计数器页面:
代码(这里这是页面,数据处理部分,完整功能计算器请访问:https://blog.csdn.net/qq_40205116/article/details/88550843):
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/TableLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:stretchColumns="*" >
<TextView
android:id="@+id/text"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="@android:color/holo_blue_bright"
android:textSize="30dp"
android:gravity="center|right"
android:text="" />
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:id="@+id/btn01"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="C" />
<Button
android:id="@+id/btn02"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="←" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="%" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="÷" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="7" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="8" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="9" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="x" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="4" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="5" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="6" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="-" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="1" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="2" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="3" />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="+" />
</TableRow>
<TableRow
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" >
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="." />
<Button
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="0" />
<Button
android:id="@+id/btn19"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_span="2"
android:text="=" />
</TableRow>
</TableLayout>
(六)网格布局GridLayout
作为android 4.0 后新增的一个布局,与前面介绍过的TableLayout(表格布局)其实有点大同小异;
不过新增了一些东东
①跟LinearLayout(线性布局)一样,他可以设置容器中组件的对齐方式
②容器中的组件可以跨多行也可以跨多列(相比TableLayout直接放组件,占一行相比较)
因为是android 4.0新增的,API Level 14,在这个版本以前的sdk都需要导入项目。这里不解释。
常用属性:
排列对齐:
①设置组件的排列方式: android:orientation="" vertical(竖直,默认)或者horizontal(水平)
②设置组件的对齐方式: android:layout_gravity="" center,left,right,buttom
设置布局为几行几列:
①设置有多少行: android:rowCount="4" //设置网格布局有4行
②设置有多少列: android:columnCount="4" //设置网格布局有4列
设置某个组件位于几行几列
注:都是从0开始算的哦!
①组件在第几行: android:layout_row = "1" //设置组件位于第二行
②组件在第几列: android:layout_column = "2" //设置该组件位于第三列
设置某个组件横跨几行几列(合并):
横跨几行: android:layout_rowSpan = "2" //纵向横跨2行
横跨几列: android:layout_columnSpan = "3" //横向横跨2列
android:layout_gravity="fill"填充
效果图:
这里只简单的设置了一下按钮演示,大家也可以用gridLayout来做一个计数器页面(这里我就不写了,因为和上面那个表格布局差不多)。
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/GridLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnCount="4"
android:rowCount="3"
android:orientation="horizontal"
tools:context="${relativePackage}.${activityClass}" >
<!--
columnCount列
rowCount行
orientation排列方式,horizontal水平,vertical垂直
-->
<!--
layout_columnSpan合并列单元格
layout_rowSpan合并行单元格
layout_gravity="fill"填充
-->
<Button
android:id="@+id/button1"
android:layout_columnSpan="2"
android:layout_gravity="fill"
android:text="bun11" />
<Button
android:id="@+id/button2"
android:text="bun12" />
<Button
android:id="@+id/button3"
android:layout_rowSpan="2"
android:layout_gravity="fill"
android:text="bun13" />
<Button
android:id="@+id/button5"
android:text="bun21" />
<Button
android:id="@+id/button6"
android:text="bun22" />
<Button
android:id="@+id/button7"
android:text="bun23" />
</GridLayout>
除上面讲过之外常用的几个布局的属性:
(1)layout_margin
用于设置控件边缘相对于父控件的边距
android:layout_marginLeft
android:layout_marginRight
android:layout_marginTop
android:layout_marginBottom
(2) layout_padding
用于设置控件内容相对于控件边缘的边距
android:layout_paddingLeft
android:layout_paddingRight
android:layout_paddingTop
android:layout_paddingBottom
(3) layout_width/height
用于设置控件的高度和宽度
wrap_content 内容包裹,表示这个控件的里面文字大小填充
fill_parent 跟随父窗口
match_parent
(4) gravity
用于设置View组件里面内容的对齐方式
top bottom left right center等
自定义View的三种实现方式及自定义属性使用介绍
尽管Android系统提供了不少控件,但是有很多酷炫效果仍然是系统原生控件无法实现的。好在Android允许自定义控件,来弥补原生控件的不足。但是在很多初学者看来,自定义View似乎很难掌握。其中有很大一部分原因是我们平时看到的自定义View使用中,有多种形式,有的寥寥数笔,有的逻辑很复杂,有的直接继承View或ViewGroup,有的却直接继承系统的原生控件,有的可以直接使用系统定义的属性,而有的却自定义了自己的属性......所以不明白使用规则的开发者,很容易被这只“纸老虎”吓到。
实际上实现自定义View的方式,从整体上看,只分为三种:组合控件,继承控件,自绘控件。然后就是根据需要来添加自定义的属性,就这么简单。本文将会针对这4个方面进行详细的讲解。主要内容如下:
一、组合控件
组合控件,顾名思义,就是将系统原有的控件进行组合,构成一个新的控件。这种方式下,不需要开发者自己去绘制图上显示的内容,也不需要开发者重写onMeasure,onLayout,onDraw方法来实现测量、布局以及draw流程。所以,在实现自定义view的三种方式中,这一种相对比较简单。
实际开发中,标题栏就是一个比较常见的例子。因为在一个app的各个界面中,标题栏基本上是大同小异,复用率很高。所以经常会将标题栏单独做成一个自定义view,在不同的界面直接引入即可,而不用每次都把标题栏布局一遍。本节就自定义一个标题栏,包含标题和返回按钮两个控件,来介绍这种组合控件的实现方式。
1、定义标题栏布局文件
定义标题栏的布局文件custom_title_view.xml,将返回按钮和标题文本进行组合。这一步用于确定标题栏的样子,代码如下所示:
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/holo_orange_light">
<Button
android:id="@+id/btn_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:text="Back"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textColor="@android:color/white"
android:textSize="20sp" />
</RelativeLayout>
复制代码
这个布局很简单,就不多说了。
2、根据给定布局实现自定义View
复制代码
public class CustomTitleView extends FrameLayout implements View.OnClickListener {
private View.OnClickListener mLeftOnClickListener;
private Button mBackBtn;
private TextView mTittleView;
public CustomTitleView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater.from(context).inflate(R.layout.custom_title_view, this);
mBackBtn = findViewById(R.id.btn_left);
mBackBtn.setOnClickListener(this);
mTittleView = findViewById(R.id.title_tv);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btn_left:
if (mLeftOnClickListener != null) {
mLeftOnClickListener.onClick(v);
}
break;
}
}
public void setLeftOnClickListener(View.OnClickListener leftOnClickListener) {
mLeftOnClickListener = leftOnClickListener;
}
public void setTittle(String title){
mTittleView.setText(title);
}
}
复制代码
为了编译理解和记忆,这里对该部分做一点说明:
(1)代码中对外提供了两个接口,一是动态设置标题,二是使用者可以自定义返回按钮的点击事件。
(2)CustomTitleView的构造函数,要选择两个参数的,选择其它参数的构造函数会报错。这一点是笔者开发机测试的结果,暂时不清楚是不是所有手机上都是这样。
(3)这里是继承的FrameLayout,但是继承LinearLayout,RelativeLayout等系统布局控件都可以。之所以要继承这些系统现成的ViewGroup,是因为这样可以不用再重写onMeasure,onLayout等,这样省事很多。由于这里是一个布局控件,要用LayoutInflater来填充,所以需要继承ViewGroup,如果继承View的直接子类,编译会不通过。所以,CustomTitleView自己就是一个容器,完全可以当成容器使用,此时CustomTitleView自身的内容会和其作为父布局添加的子控件,效果会叠加,具体的叠加效果是根据继承的容器特性决定的。
3、在Activity的布局文件中添加CustomTitleView
在Activity的布局文件activity_custom_view_compose_demo.xml中,像使用系统控件一样使用CustomTitleView即可。前说了,CustomTitleView自己就是继承的现成的系统布局,所以它们拥有的属性特性,CustomTitleView一样拥有。
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.CustomTitleView
android:id="@+id/customview_title"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</com.example.demos.customviewdemo.CustomTitleView>
</RelativeLayout>
复制代码
4、在Activity中操作CustomTitleView
复制代码
public class CustomViewComposeDemoActivity extends AppCompatActivity {
private CustomTitleView mCustomTitleView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_custom_view_compose_demo);
mCustomTitleView = findViewById(R.id.customview_title);
mCustomTitleView.setTittle("This is Title");
mCustomTitleView.setLeftOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
}
复制代码
在第8行中,获取到CustomTitleView实例,第9行设置标题文字,第10行自定义“Back”按钮点击事件。
5、效果图
按照如上的4步,就通过组合控件完成了一个比较简单的自定义标题栏。可见,这种方式是非常简单的。
二、继承控件
通过继承系统控件(View子类控件或ViewGroup子类控件)来完成自定义View,一般是希望在原有系统控件基础上做一些修饰性的修改,而不会做大幅度的改动,如在TextView的文字下方添加下划线,在LinearLayout布局中加一个蒙板等。这种方式往往都会复用系统控件的onMeasure和onLayout方法,而只需要重写onDraw方法,在其中绘制一些需要的内容。下面会分别继承View类控件和ViewGroup类控件来举例说明。
1、继承View类系统控件
如下示例为在TextView文字下方显示红色下划线,其基本步骤如下:
(1)继承View控件,并重写onDraw方法
复制代码
@SuppressLint("AppCompatCustomView")
public class UnderlineTextView extends TextView{
public UnderlineTextView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(5);
int width = getWidth();
int height = getBaseline();
canvas.drawLine(0,height,width,height,paint);
}
}
复制代码
(2)在布局文件中调用
就像使用一个普通TextView一样使用UnderlineTextView。
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.UnderlineTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="50dp"
android:layout_centerInParent="true"
android:text="Hello World!"/>
</RelativeLayout>
复制代码
(3)效果图
2、继承ViewGroup类系统控件
如下示例演示,在layout布局上添加一个浅红色的半透明蒙板,这种需求在工作中也是非常常见的。
(1)继承ViewGroup类系统控件
复制代码
public class ForegroundLinearLayout extends LinearLayout{
public ForegroundLinearLayout(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
canvas.drawColor(Color.parseColor("#50FF0000"));
}
}
复制代码
(2)在布局文件中调用
对ForegroundLinearLayout的使用,就和使用其父类LinearLayout一样。
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.ForegroundLinearLayout
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_centerInParent="true"
android:gravity="center">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Hello World!"
android:textColor="@android:color/black"
android:textSize="50dp" />
</com.example.demos.customviewdemo.ForegroundLinearLayout>
</RelativeLayout>
复制代码
(3)效果图
在宽为全屏宽度,高为200dp的布局范围内,绘制完子其子控件TextView后,在上面覆盖了一层浅红色的半透明蒙板。
从上面两个例子可见,继承系统原有的控件来实现自定义View,步骤非常简单,比组合控件简单多了。但是这一节需要对Canvas,paint等绘制方面的知识有一定的了解,且还需要对ViewGroup的中内容的绘制顺序有一定的了解,才能在原生控件的基础上做出想要的效果来。
三、自绘控件
这三种方法中,自绘控件是最复杂的,因为所有的绘制逻辑和流程都需要自己完成。采用自绘控件这种方式时,如果自定义View为最终的叶子控件,那么需要直接继承View;而不过自定义View为容器类控件,则需要直接继承ViewGroup。这里依然针对直接继承View和ViewGroup分别举例进行说明。
1、自绘叶子View控件
这里通过画一个直方图来展示自绘View控件的实现。
(1)直接继承View类
自绘叶子View控件时,最主要工作就是绘制出丰富的内容,这一过程是在重写的onDraw方法中实现的。由于是叶子view,它没有子控件了,所以重写onLayout没有意义。onMeasure的方法可以根据自己的需要来决定是否需要重写,很多情况下,不重写该方法并不影响正常的绘制。
复制代码
public class HistogramView extends View{
private Paint mPaint;
private Path mPath;
public HistogramView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPath = new Path();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制坐标轴
mPaint.reset();
mPath.reset();
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(100,100);
mPath.rLineTo(0,402);
mPath.rLineTo(800,0);
canvas.drawPath(mPath,mPaint);
//绘制文字
mPaint.reset();
mPaint.setTextSize(30);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText("Froyo",160,540,mPaint);
canvas.drawText("CB",280,540,mPaint);
canvas.drawText("ICS",380,540,mPaint);
canvas.drawText("J",480,540,mPaint);
canvas.drawText("KitKat",560,540,mPaint);
canvas.drawText("L",690,540,mPaint);
canvas.drawText("M",790,540,mPaint);
//绘制直方图,柱形图是用较粗的直线来实现的
mPaint.reset();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(80);
float[] lines3={
200,500,200,495,
300,500,300,480,
400,500,400,480,
500,500,500,300,
600,500,600,200,
700,500,700,150,
800,500,800,350,
};
canvas.drawLines(lines3,mPaint);
}
}
复制代码
(2)在Activity界面的布局文件中引入
和其它自定义控件一样,直接在布局文件中引入即可。
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.HistogramView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
复制代码
(3)效果图
2、自绘ViewGroup控件
这里通过自定义一个父布局控件,并添加一个子view来作为例子讲解该方法的实现。
(1)直接继承ViewGroup类
自绘ViewGroup控件,需要直接继承ViewGroup,在该系列第一篇文章中将绘制流程的时候就讲过,onLayout是ViewGroup中的抽象方法,其直接继承者必须实现该方法。所以这里,onLayout方法必须要实现的,如果这里面的方法体为空,那该控件的子view就无法显示了。要想准确测量,onMeasure方法也是要重写的。下面例子中,只演示了第一个子view的测量和布局,onLayout方法中的child.layout,就完成了对子view的布局。
复制代码
public class CustomLayout extends ViewGroup {
public CustomLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (getChildCount() > 0) {
//只测量第一个child
View child = getChildAt(0);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (getChildCount() > 0) {
//只布局第一个child
View child = getChildAt(0);
child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
}
}
}
复制代码
(2)在布局文件中和普通父布局一样被引入
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.CustomLayout
android:layout_width="match_parent"
android:layout_centerInParent="true"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
android:textSize="50dp"/>
</com.example.demos.customviewdemo.CustomLayout>
</RelativeLayout>
复制代码
(3)效果图
上述代码中第8行没有起效,从布局上看TextView应该是处于屏幕的正中央,但是实际结果却还是在左上方显示。这是因为CustomLayout控件,并没有实现“android:layout_centerInParent”这个属性,所以是无效的。关于属性的问题,正是下一节要介绍的内容。
四、在自定义View中使用自定义属性
我们在使用Android原生控件的时候,经常可以看到在布局文件中可以设置很多的属性值,如
复制代码
<TextView
android:id="@+id/title_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Title"
android:textColor="@android:color/white"
android:textSize="20sp" />
复制代码
这里可以根据需要随时设置TextView要显示的文字,文字颜色,文字大小等各种属性,给使用者带来了极大的方便。我们在使用自定义View的时候,也非常希望能够像TextView等系统原生控件一样通过设置属性值来个性化自定义View。本节咱们在上一节自定义直方图的基础上,来介绍自定义属性的基本使用流程。
1、在values中编写需要的属性
在res/values/下新建资源文件,这里咱们命名为attrs.xml,在其中编写所需要的属性
复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="HistogramView">
<attr name="textColor" format="color"/>
<attr name="histogramColor" format="color"/>
</declare-styleable>
</resources>
复制代码
这里<declare-styleable>中的name是自行命名的,可以理解为这个自定义属性集合的名称。代码中包含了两个自定义属性,名称分别为“textColor”和“histogramColor”,这里用来设置直方图中文字的颜色和直方图的颜色。format表示的是属性的格式,这里均设置为“color”,表示对应的属性是用来设置颜色值的。对于“format”,后面还会详细讲到。其它的就是固定的格式了,直接套用就行。
2、在自定义View中引入属性
复制代码
public class HistogramView extends View{
private Paint mPaint;
private Path mPath;
private int mTextColor,mHistogramColor;
public HistogramView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPath = new Path();
initAttrs(context,attrs);
}
private void initAttrs(Context context, AttributeSet attrs){
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HistogramView);
mTextColor = typedArray.getColor(R.styleable.HistogramView_textColor,Color.BLACK);
mHistogramColor = typedArray.getColor(R.styleable.HistogramView_histogramColor,Color.GREEN);
typedArray.recycle();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制坐标轴
mPaint.reset();
mPath.reset();
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPath.moveTo(100,100);
mPath.rLineTo(0,402);
mPath.rLineTo(800,0);
canvas.drawPath(mPath,mPaint);
//绘制文字
mPaint.reset();
mPaint.setTextSize(30);
mPaint.setColor(mTextColor);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawText("Froyo",160,540,mPaint);
canvas.drawText("CB",280,540,mPaint);
canvas.drawText("ICS",380,540,mPaint);
canvas.drawText("J",480,540,mPaint);
canvas.drawText("KitKat",560,540,mPaint);
canvas.drawText("L",690,540,mPaint);
canvas.drawText("M",790,540,mPaint);
//绘制直方图,柱形图是用较粗的直线来实现的
mPaint.reset();
mPaint.setColor(mHistogramColor);
mPaint.setStrokeWidth(80);
float[] lines3={
200,500,200,495,
300,500,300,480,
400,500,400,480,
500,500,500,300,
600,500,600,200,
700,500,700,150,
800,500,800,350,
};
canvas.drawLines(lines3,mPaint);
}
}
复制代码
将上述代码和前面第三节中自绘直方图代码对比,红色部分是修改或新增的代码。第15~20行代码就是初始化属性的地方,这个过程需要在构造函数中完成。其中,第16行是和自定义属性集建立联系,第17和18行是获取开发者在布局文件中使用时设置的相应属性值,如果没有设置,则会使用默认设置的颜色,分别为Color.BLACK和Color.GREEN。这里注意第19行,用完后一定要回收资源。这样就初始化了文字颜色mTextColor值和mHistogramColor值,在后面onDraw中就使用该值来绘制对应的部分。
3、在布局文件中设置属性值
复制代码
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.demos.customviewdemo.HistogramView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:textColor="@android:color/holo_red_light"
app:histogramColor="@android:color/holo_blue_bright"/>
</RelativeLayout>
复制代码
这段代码中,第3,10,11行和以往的布局文件有些不一样,这是使用自定义属性时的固定格式。第3行中,如果布局文件中没有这一句,一定要加上,这句是声明命名空间,只有声明了命名空间才能使用自定义属性。“app”是该命名空间的名称,这里是自行命名的,不一定非要用“app”。第10行和11行,“app:attrName”表示用的是自定义的属性,固定用法,前面mTextColor和mHistogramColor值就是从这里获取的。
还记得上一节结尾处说“android:layout_centerInParent”没有起效吗?现在我们知道,这里设置的属性,是在自定义View代码中获取该值,根据该值来确定显示效果的。“android:layout_centerInParent”的值在View的源码中没有被使用,所以设置后也就无效了。“android:layout_width”和“android:layout_height”属性是必须要有的,所有的View的实现都要用到这两个属性来确定宽高。现在,咱们应该明白,设置控件属性值是如何起作用的了吧。
4、效果图
五、自定义属性格式汇总
在上面一节中,仅仅只是对文字颜色和直方图颜色的属性值做了设置,是为了演示自定义属性的使用步骤。在实际开发中,完全可以定义更多类型的属性,如显示文字的内容,文字的大小,直方图的宽度等。format也不只限定于“color”,还有“String”,“Integer”等,多种多样。本节就汇总一下平时比较常用的一些属性format。
本节主要参考了如下文章:【Android自定义View全解】
1、常用的11种format类型
复制代码
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="SelfAttr">
<!--1.reference:参考某一资源ID-->
<attr name="background" format="reference" />
<!--2. color:颜色值-->
<attr name = "textColor" format = "color" />
<!--3.boolean:布尔值-->
<attr name = "focusable" format = "boolean" />
<!--4.dimension:尺寸值-->
<attr name = "layout_width" format = "dimension" />
<!--5. float:浮点值-->
<attr name = "fromAlpha" format = "float" />
<!--6.integer:整型值-->
<attr name = "lines" format="integer" />
<!--7.string:字符串-->
<attr name = "text" format = "string" />
<!--8.fraction:百分数-->
<attr name = "pivotX" format = "fraction" />
<!--9.enum:枚举值。属性值只能选择枚举值中的一个-->
<attr name="orientation">
<enum name="horizontal" value="0" />
<enum name="vertical" value="1" />
</attr>
<!--10.flag:位或运算。属性值可以选择其中多个值-->
<attr name="gravity">
<flag name="top" value="0x01" />
<flag name="bottom" value="0x02" />
<flag name="left" value="0x04" />
<flag name="right" value="0x08" />
<flag name="center_vertical" value="0x16" />
...
</attr>
<!--11.混合类型:属性定义时可以指定多种类型值-->
<attr name = "background_2" format = "reference|color" />
</declare-styleable>
</resources>
复制代码
如上列出了平时工作中在常见的11种类型的格式,说是11种,但最后一种是前面10种的组合而已。看到上述的属性名称应该很熟悉吧,都是系统原生控件的属性名称。
2、使用举例
如下对上述属性的使用一一举例演示,可以对照着来理解,都是平时常用的系统控件。
复制代码
<!--1.reference:参考某一资源ID-->
<ImageView android:background = "@drawable/图片ID"/>
<!--2. color:颜色值-->
<TextView android:textColor = "#00FF00"/>
<!--3.boolean:布尔值-->
<Button android:focusable = "true"/>
<!--4.dimension:尺寸值-->
<Button android:layout_width = "42dp"/>
<!--5. float:浮点值-->
<alpha android:fromAlpha = "1.0"/>
<!--6.integer:整型值-->
<TextView android:lines="1"/>
<!--7.string:字符串-->
<TextView android:text = "我是文本"/>
<!--8.fraction:百分数-->
<rotate android:pivotX = "200%"/>
<!--9.enum:枚举值-->
<LinearLayout
android:orientation = "vertical">
</LinearLayout>
<!--10.flag:位或运算-->
<TextView android:gravity="bottom|left"/>
<!--11.混合类型:属性定义时可以指定多种类型值-->
<ImageView android:background = "@drawable/图片ID" />
<!--或者-->
<ImageView android:background = "#00FF00" />
复制代码
结语
关于自定义View的3中实现方式以及自定义属性的使用,这里就讲完了。读完后,是不是发现基本的实现流程其实非常简单呢?当然,本文为了说明实现流程,所以举的例子都比较简单,但不是说绘制内容也一样简单。就好像办理入学手续很简单,但读书这件事却不那么容易一样。要完成一些酷炫的自定义View,还需要好好地掌握Canvas,Paint,Path等工具的使用,以及View的绘制流程原理。当然,本文肯定有很多描述不妥或不准确的地方,欢迎来拍砖。
android:exported 属性详解
android:exported 是Android中的四大组件 Activity,Service,Provider,Receiver 四大组件中都会有的一个属性。
总体来说它的主要作用是:是否支持其它应用调用当前组件。
默认值:如果包含有intent-filter 默认值为true; 没有intent-filter默认值为false。
1、先来看:Activity中的:
<activity
……
android:exported=["true" | "false"]
……
/>
意思如下:
在Activity中该属性用来标示:当前Activity是否可以被另一个Application的组件启动:true允许被启动;false不允许被启动。
如果被设置为了false,那么这个Activity将只会被当前Application或者拥有同样user ID的Application的组件调用。
exported 的默认值根据Activity中是否有intent filter 来定。没有任何的filter意味着这个Activity只有在详细的描述了他的class name后才能被唤醒 .这意味着这个Activity只能在应用内部使用,因为其它application并不知道这个class的存在。所以在这种情况下,它的默认值是false。从另一方面讲,如果Activity里面至少有一个filter的话,意味着这个Activity可以被其它应用从外部唤起,这个时候它的默认值是true。
其实,不只有这个属性可以指定Activity是否暴露给其它应用,也可以使用permission来限制外部实体唤醒当前Activity(详情见permission属性)
2、Service中的:
<service android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:isolatedProcess=["true" | "false"]
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</service>
意思如下:
该属性用来标示,其它应用的组件是否可以唤醒service或者和这个service进行交互:true可以,false不可以。如果为false,只有同一个应用的组件或者有着同样user ID的应用可以启动这个service或者绑定这个service。
默认值根据当前service是否有intent filter来定。如果没有任何filter意味着当前service只有在被详细的描述class name后才会被唤醒。这意味这当前service只能在应用内部使用(因为其它应用不知道这个class name).所以在这种情况下它的默认值为 false.从另一方面讲,如果至少有一个filter的话那么就意味着这个service可以被外部应用使用,这种情况下默认值为true。
其实,不只有这个属性可以指定service是否暴露给其它应用。你也可以使用permission来限制外部实体唤醒当前service(详情见permission属性)
3、Provider中的:
<provider android:authorities="list"
android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:grantUriPermissions=["true" | "false"]
android:icon="drawable resource"
android:initOrder="integer"
android:label="string resource"
android:multiprocess=["true" | "false"]
android:name="string"
android:permission="string"
android:writePermission="string" >
. . .
</provider>
意思如下:
当前内容提供者是否会被其它应用使用:
true: 当前提供者可以被其它应用使用。任何应用可以使用Provider通过URI 来获得它,也可以通过相应的权限来使用Provider。
false:当前提供者不能被其它应用使用。设置Android:exported=“false”来限制其它应用获得你应用的Provider。只有拥有同样的user ID 的应用可以获得当前应用的Provider。
当Android sdk 的最小版本为16或者更低时他的默认值是true。如果是17和以上的版本默认值是false。
可以通过Android:exported=“fasle” 和 permission来限制当前应用Provider是否会被其它应用获取。
4、receiver中的:
<receiver android:enabled=["true" | "false"]
android:exported=["true" | "false"]
android:icon="drawable resource"
android:label="string resource"
android:name="string"
android:permission="string"
android:process="string" >
. . .
</receiver>
意思如下:
当前broadcast Receiver 是否可以从当前应用外部获取Receiver message 。true,可以;false 不可以。如果为false ,当前broadcast Receiver 只能收到同一个应用或者拥有同一 user ID 应用发出广播。
默认值根据当前 broadcast Receiver 是否包含intent filter来定。如果没有任何的filter的话意味着只有在被详细的描述了class name的情况下才会被唤起。这意味着当前Receiver只能在应用内部被使用(因为其它应用不知道这个类的存在。)在这种情况下,默认值是false。如果至少包含一个filter意味着当前broadcast Receiver 将会收到来自系统或者其它应用的广播,所以这个时候默认值是true。
不只有这个属性可以指定broadcast Receiver 是否暴露给其它应用。你也可以使用permission来限制外部应用给他发送消息。
不带layout一般是指容器特有属性
不带layout一般是指容器特有属性
如:
android:gravity center center_horizontal bottom top left right
android:orientation
...
其他基本指非容器的自身特性
如layout_gravity指做自己为位置排列
android @id和@+id的区别
其实@+id就是在R.java文件里新增一个id名称,如果之前已经存在相同的id名称,那么会覆盖之前的名称。而@id则是直接引用R.java文件的存在的id资源,如果不存在,会编译报错
遍历view中的子view
private List<View> getAllChildViews(View view) {
List<View> allchildren = new ArrayList<View>();
if (view instanceof ViewGroup) {
ViewGroup vp = (ViewGroup) view;
for (int i = 0; i < vp.getChildCount(); i++) {
View viewchild = vp.getChildAt(i);
allchildren.add(viewchild);
//再次 调用本身(递归)
allchildren.addAll(getAllChildViews(viewchild));
}
}
return allchildren;
}
Android中setTag的使用
什么是setTag
Tag 从本质上来讲是就是相关联的 view 的额外信息。它们经常用来存储一些 view 的数据,这样做非常方便而不用存入另外单独的结构
ListView 中的使用
setTag()使用的最多的场景基本就是 ListView,GridView,RecycleView,ViewPage,Gallery等类似用于展示大量重复的 View 的控件上
这一些控件基本都会对视图判断是否在可视的范围,从而决定回不回收资源。**那么,问题就来了,当被回收的 view 再一次出现在世人的眼前的时候,机器是不是需要重新绑定数据,重新加载资源,重新绘制view?**问题的答案是肯定的。那么明明已经使用过的 view 再来一次也要重新开始绘制,那样不是一直在重复同样的动作?同样的事,重复的做,那就是在无谓的消耗机器性能了
通过观察,我们可以发现,其实无论是 ListView,GridView,RecycleView,ViewPage,还是Gallery,它们的使用都是离不开 adapter,每一个子 item 的创建也是在 adapter 中的 getView()中完成的,因此,我们要开刀的就是 adapter 的 getView()
在 很早之前的一篇博客 达内课程-音乐播放器3.0(上) 中,我们展示了音乐列表,现在我们分析 MusicAdapter 中的代码,优化前:
public class MusicAdapter extends BaseAdapter<Music> {
public MusicAdapter(Context context, List data) {
super(context, data);
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
Music music = getData().get(i);
if(view == null){
view = getInflater().inflate(R.layout.item_music,null);
}
TextView title = view.findViewById(R.id.tv_music_title);
TextView path = view.findViewById(R.id.tv_music_path);
title.setText(music.getTitle());
path.setText(music.getPath());
return view;
}
}
优化后:
public class MusicAdapter extends BaseAdapter<Music> {
public MusicAdapter(Context context, List data) {
super(context, data);
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
Music music = getData().get(i);
ViewHolder holder;
if(view == null){
view = getInflater().inflate(R.layout.item_music,null);
holder = new ViewHolder();
holder.title = view.findViewById(R.id.tv_music_title);
holder.path = view.findViewById(R.id.tv_music_path);
view.setTag(holder);
}else{
holder = (ViewHolder) view.getTag();
}
holder.title.setText(music.getTitle());
holder.path.setText(music.getPath());
return view;
}
class ViewHolder{
TextView title;
TextView path;
}
}
其中以下代码,我们反复的声明变量是没有意义的
TextView title = view.findViewById(R.id.tv_music_title);
TextView path = view.findViewById(R.id.tv_music_path);
所以我们增加了一个 ViewHolder 来存储这些信息,把它通过setTag()存到itemView 中,再第二次使用的时候就可以通过getTag()把 holder 取出来直接使用
区分 view
可以给多个 Button 添加一个监听器,每个 Button 都设置不同的setTag。这个监听器就通过getTag来分辨是哪个 Button 被按下
Button button1 = findViewById(R.id.button1);
Button button2 = findViewById(R.id.button2);
MyListener listener = new MyListener();
button1.setTag(1);
button1.setOnClickListener(listener);
button2.setTag(2);
button2.setOnClickListener(listener);
public class MyListener implements View.OnClickListener {
@Override
public void onClick(View v) {
int tag = (Integer) v.getTag();
switch (tag) {
case 1:
Log.d("TTT", "button1 click");
break;
case 2:
Log.d("TTT", "button2 click");
break;
}
}
}
setTag(key,object)
还可以存储不同的信息,这就用到了 setTag(key,object),不过这个 key 需要写成资源类型
Button button1 = findViewById(R.id.button1);
MyListener listener = new MyListener();
button1.setTag(R.id.tag_cao, "A Dream in Red Mansions");
button1.setTag(R.id.tag_wu, "Journey to the West");
button1.setOnClickListener(listener);
public class MyListener implements View.OnClickListener {
@Override
public void onClick(View v) {
Log.d("TTT", "曹雪芹写了" + v.getTag(R.id.tag_cao));
Log.d("TTT", "吴承恩写了" + v.getTag(R.id.tag_wu));
}
}