提交文件

This commit is contained in:
llliupeiwen
2022-11-04 11:56:24 +08:00
commit 560b70fff7
134 changed files with 6126 additions and 0 deletions

15
.gitignore vendored Normal file
View File

@@ -0,0 +1,15 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
.cxx
local.properties

3
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,3 @@
# Default ignored files
/shelf/
/workspace.xml

6
.idea/compiler.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<bytecodeTargetLevel target="11" />
</component>
</project>

28
.idea/deploymentTargetDropDown.xml generated Normal file
View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="deploymentTargetDropDown">
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="D:\Android Virtual Device\.android\avd\Pixel_5_API_33.avd" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<targetSelectedWithDropDown>
<Target>
<type value="QUICK_BOOT_TARGET" />
<deviceKey>
<Key>
<type value="VIRTUAL_DEVICE_PATH" />
<value value="D:\Android Virtual Device\.android\avd\Pixel_5_API_33.avd" />
</Key>
</deviceKey>
</Target>
</targetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2022-11-04T03:04:29.775838Z" />
</component>
</project>

19
.idea/gradle.xml generated Normal file
View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="testRunner" value="GRADLE" />
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>

10
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_11" default="true" project-jdk-name="Android Studio default JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>

1
app/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

41
app/build.gradle Normal file
View File

@@ -0,0 +1,41 @@
plugins {
id 'com.android.application'
}
android {
namespace 'com.example.teambag'
compileSdk 32
defaultConfig {
applicationId "com.example.teambag"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
implementation files('libs\\BASE64.jar')
implementation files('libs\\pinyin4j-2.5.0.jar')
implementation files('libs\\sun.misc.BASE64Decoder.jar')
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
}

BIN
app/libs/BASE64.jar Normal file

Binary file not shown.

BIN
app/libs/pinyin4j-2.5.0.jar Normal file

Binary file not shown.

Binary file not shown.

21
app/proguard-rules.pro vendored Normal file
View File

@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile

View File

@@ -0,0 +1,26 @@
package com.example.teambag;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
/**
* Instrumented test, which will execute on an Android device.
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.teambag", appContext.getPackageName());
}
}

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TeamBag"
tools:targetApi="31"
android:usesCleartextTraffic="true">
<activity android:name=".AppStart"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<activity android:name=".Welcome"/>
<activity android:name=".Register"/>
<activity android:name=".LoginUser"/>
<activity android:name=".LoginPhone"/>
<activity android:name=".Main"/>
<activity android:name=".ChatRoom"
android:exported="true">
</activity>
<activity android:name=".Search"/>
<activity android:name=".MainTopRightDialog" android:theme="@style/MyDialogStyleTop"/>
<activity
android:name=".Loading"
android:theme="@style/MyDialogStyle" />
</application>
</manifest>

View File

@@ -0,0 +1,27 @@
package com.example.teambag;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
public class AppStart extends Activity{
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//设置布局
setContentView(R.layout.app_start);
//延迟跳转,显示欢迎图片背景
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
//页面跳转到启动界面
Intent intent = new Intent(com.example.teambag.AppStart.this,com.example.teambag.Welcome.class);
startActivity(intent);
//结束当前activity
com.example.teambag.AppStart.this.finish();
}
},1000);
}
}

View File

@@ -0,0 +1,193 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ListView;
import androidx.annotation.Nullable;
import com.example.teambag.adapter.ImageAdapter;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressLint("ValidFragment")
public class ChatFragment extends Fragment {
//账号,以用于查找消息列表
private String number;
//声明组件
private ListView listView;
// 创建集合用于存储服务器发来的显示微信消息列表的一些信息
private List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
//自定义的一个Hander消息机制
private MyHander myhander = new MyHander();
@SuppressLint("ValidFragment")
ChatFragment(String number) {
this.number = number;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// 开一个线程完成网络请求操作
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
httpUrlConnPost(String.valueOf(number));
}
});
thread1.start();
/*等待网络请求线程完成*/
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
View view = inflater.inflate(R.layout.chat_fragment, container, false);
//初始化组件
listView = view.findViewById(R.id.listView);
//创建自定义的适配器,用于把数据显示在组件上
BaseAdapter adapter = new ImageAdapter(getActivity().getApplicationContext(), list);
//设置适配器
listView.setAdapter(adapter);
return view;
}
// 1.编写一个发送请求的方法
// 发送请求的主要方法
public void httpUrlConnPost(String number) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/ChatInformation");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
//json.put("title", URLEncoder.encode(title, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("number", URLEncoder.encode(number, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode() + "");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
System.out.println("测试:" + str);
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
for(int j = 0; j<rjson.getJSONArray("json").length();j++){
String str1 = rjson.getJSONArray("json").getJSONObject(j).get("titleimg").toString();
String[] pic = str1.split("\r\n");
String str2 = rjson.getJSONArray("json").getJSONObject(j).get("title").toString();
String[] title = str2.split("\r\n");
String str3 = rjson.getJSONArray("json").getJSONObject(j).get("content").toString();
String[] content = str3.split("\r\n");
String str4 = rjson.getJSONArray("json").getJSONObject(j).get("time").toString();
String[] time = str4.split("\r\n");
String str5 = rjson.getJSONArray("json").getJSONObject(j).get("showcode").toString();
String[] pic2 = str5.split("\r\n");
for (int i = 0; i < pic.length; i++) {
Map<String, Object> map = new HashMap<String, Object>();
map.put("pic", pic[i]);
System.out.println("网址:" + pic[i]);
map.put("title", title[i]);
System.out.println("网址:" + title[i]);
map.put("content", content[i]);
map.put("time", time[i]);
map.put("code", pic2[i]);
list.add(map);//将map放到list集合中
}
}
boolean result = rjson.getBoolean("j1");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明跳转微信页成功跳转微信页失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
myhander.sendEmptyMessage(1);
Log.i("用户:", "跳转微信页成功");
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用户:", "跳转微信页失败");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明跳转微信页成功如果是2说明跳转微信页失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "");
break;
case 2:
Log.i("aa", msg.what + "");
}
}
}
}

View File

@@ -0,0 +1,243 @@
package com.example.teambag;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import com.example.teambag.adapter.MsgAdapter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
public class ChatRoom extends AppCompatActivity implements View.OnClickListener{
private List<Msg> msgList = new ArrayList<>();
private MsgAdapter adapter;
private Button back; //退回键
private RecyclerView recyclerView; //对话显示框
private EditText input_text; //输入框
private String imageId ; //获取自己的头像
private String his_imageId; //获取对方发头像
private String time; //获取时间
private Button send; //发送按钮
private String name; //从主活动获取的名字
private String hisName; //对方昵称从自定义的receive线程中获取便于和自己的昵称区分
private String content; //获取对话内容
private String ip; //获取ip
private String port; //获取端口号
private Socket socketSend; //套接字用于绑定ip号和端口号便于计算机之间的传输消息
private DataInputStream dis; //码头
private DataOutputStream dos; //集装箱
private String recMsg;
boolean isRunning = false; //判断线程是否运行
boolean isSend = false; //判断是否发送
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.chat_room);
//启动活动,并获取传递过来的信息
Intent intent = getIntent();
name=Main.userName;
/*
//传入键值得到数据
ip = intent.getStringExtra("ip");
port = intent.getStringExtra("port");
//取出int要指定key还要设置默认值当intent中没有该key对应的value时返回设置的默认值
imageId = intent.getIntExtra("imageId",0);
*/
//测试数据
hisName = intent.getStringExtra("his_name");
//System.out.println("his_name: "+hisName);
ip = "192.168.31.102";
port = "6666";
imageId = Main.img;
System.out.println("img: "+imageId);
his_imageId = intent.getStringExtra("his_img");
//获取实例
input_text = (EditText) findViewById(R.id.input_text);
back = (Button) findViewById(R.id.back);
send = (Button) findViewById(R.id.send);
//注册监听器
back.setOnClickListener(this);
send.setOnClickListener(this);
//将RecyclerView和list建立联系(建立与适配器关系)
LinearLayoutManager layoutManager = new LinearLayoutManager(ChatRoom.this);
recyclerView = (RecyclerView) findViewById(R.id.msg_recycler_view);
recyclerView.setLayoutManager(layoutManager);
adapter = new MsgAdapter(msgList);
recyclerView.setAdapter(adapter);
//如果要连网的话就不能在主线程上操作,所以要另外开启一条线程
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println("号码");
socketSend = new Socket(ip, Integer.parseInt(port));
isRunning = true;
dis = new DataInputStream(socketSend.getInputStream());
dos = new DataOutputStream(socketSend.getOutputStream());
System.out.println("打开dos");
System.out.println("发送定位数据");
dos.writeUTF(name);
//开一条线程接收服务器传来的信息
new Thread(new receive(), "接收线程").start();
System.out.println("打开线程");
} catch (Exception e) {
Log.e("TAG",e.toString());
e.printStackTrace();
//为当前线程准备消息队列
Looper.prepare();
//Toast只有在主线程中能显示出来
Toast.makeText(ChatRoom.this, "连接服务器失败", Toast.LENGTH_SHORT).show();
//开启循环取消息
Looper.loop();
finish();
}
}
}).start();
}
//获取当前时间
public String getCurrentTime(){
Date d = new Date();
//设置显示的时间格式
SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日HH:mm:ss");
//以这种格式显示
return sdf.format(d);
}
@Override
public void onClick(View view) {
switch(view.getId()){
case R.id.back:
finish();
break;
case R.id.send:
//显示时间
time = getCurrentTime();
String content = input_text.getText().toString();
//显示信息
StringBuilder sb = new StringBuilder();
sb.append(content);
if(!"".equals(content)){ //发送信息不为空
isSend = true;
new Thread(new Runnable() {
@Override
public void run() {
String content = input_text.getText().toString();
Log.d("ttw","发了一条消息");
System.out.println("content = "+content);
System.out.println("传入发送信息");
if(!"".equals(content) && isSend){
String date = getCurrentTime();
try {
if(!"".equals(date) && !"".equals(name)){
dos.writeUTF(date);
dos.writeUTF(content);
dos.writeUTF(name);
dos.writeUTF(String.valueOf(imageId));
dos.writeUTF(hisName);
System.out.println("发送完了");
}
} catch (IOException e) {
e.printStackTrace();
}
isSend = false;
}
}
}).start();
Msg msg = new Msg(content,Msg.TYPE_SENT,time,name,imageId); //发送消息
System.out.println("imageId = "+imageId);
msgList.add(msg);
//当有新消息时刷新ListView中的消息
adapter.notifyItemInserted(msgList.size()-1);
//将LestView定位到最后一行
recyclerView.scrollToPosition(msgList.size()-1);
input_text.setText("");
}else{
Toast.makeText(ChatRoom.this, "不可发送空信息!", Toast.LENGTH_SHORT).show();
}
sb.delete(0,sb.length());
break;
default:
break;
}
}
//子线程与主线程通过Handler来进行通信。子线程可以通过Handler来通知主线程进行UI更新。
//Handler有两个主要的用途:(1)安排消息和可运行对象在将来的某个时间点执行;(2)将一个要在不同的线程上执行的动作编入队列。
private Handler handler = new Handler(Looper.myLooper()){
@Override
public void handleMessage(@NonNull Message msg) {
if(!recMsg.isEmpty()){
System.out.println("更新消息");
addNewMessage(content,Msg.TYPE_RECEIVED,time,hisName,his_imageId); //刷新接收的消息
}
}
};
public void addNewMessage(String msg,int type,String time,String name,String his_imageId){
Msg message = new Msg(msg,type,time,name,his_imageId);
msgList.add(message);
//当有消息时通知列表有新的数据插入刷新recyclerview中消息
adapter.notifyItemInserted(msgList.size()-1);
//将消息一直放在显示屏的底部不随意跑上去
recyclerView.scrollToPosition(msgList.size()-1);
}
//接收线程
class receive implements Runnable{
@Override
public void run() {
recMsg = "";
while(isRunning){
System.out.println("开始接收线程receive");
Msg msg = null;
try {
time = dis.readUTF();
content = dis.readUTF();
hisName = dis.readUTF();
his_imageId = dis.readUTF();
System.out.println("接收信息 = "+content);
recMsg = hisName + time + content;
msg = new Msg(content,Msg.TYPE_RECEIVED,time,hisName,his_imageId);
} catch (Exception e) {
System.out.println("接受失败");
e.printStackTrace();
}
//判断是否为空字符串
if(!TextUtils.isEmpty(recMsg)){
System.out.println("查看名字"+msg.getName());
Message message = new Message();
message.obj = msg;
handler.sendMessage(message);
}
}
}
}
}

View File

@@ -0,0 +1,246 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.Fragment;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import com.example.teambag.adapter.SortAdapter;
import com.example.teambag.tools.SideBar;
import com.example.teambag.tools.User;
import org.json.JSONObject;
import org.w3c.dom.Text;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressLint("ValidFragment")
public class ContactListFragment extends Fragment {
String[] imgUrl;
String[] name;
private String number; //微信号,通过微信号去查找通讯录
/* 声明组件*/
private ListView listView;
private SideBar sideBar;
/*声明或创建集合,用于处理数据*/
private ArrayList<User> list;
private ArrayList<Integer> list2;
private List<Map<String, String>> data = new ArrayList<Map<String, String>>();
//自定义的一个Hander消息机制
private MyHander myhander = new MyHander();
@SuppressLint("ValidFragment")
ContactListFragment(String number) {
this.number = number;
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*开启一个线程,用微信号向服务器请求通讯录数据*/
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
httpUrlConnPost(String.valueOf(number));
}
});
thread1.start();
/*等待线性处理完成*/
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取fragment布局
View view = inflater.inflate(R.layout.contactlist_fragment, container, false);
/*初始化组件*/
listView = (ListView) view.findViewById(R.id.listView);
sideBar = (SideBar) view.findViewById(R.id.side_bar);
//初始化数据
initData();
sideBar.setOnStrSelectCallBack(new SideBar.ISideBarSelectCallBack() {
@Override
public void onSelectStr(int index, String selectStr) {
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getName() == "新的朋友" || list.get(i).getName() == "群聊" ||
list.get(i).getName() == "标签" || list.get(i).getName() == "公众号" )
continue;
if (selectStr.equalsIgnoreCase(list.get(i).getFirstLetter())) {
listView.setSelection(i); // 选择到首字母出现的位置
return;
}
}
}
});
return view;
}
private void initData() {
//把从服务器获取解析的数据添加到map中方便处理
Map<String, String> map = new HashMap<String, String>();
for (int i = 0; i < imgUrl.length; i ++) {
map.put(name[i], imgUrl[i]);
}
data.add(map);
//名字要提取出来在添加到list中因为要进行字母排序
list = new ArrayList<>();
for (int i = 0; i < imgUrl.length; i++) {
//System.out.println("i= "+i);
list.add(new User(name[i]));
}
Collections.sort(list); // 对list进行排序需要让User实现Comparable接口重写compareTo方法
//四个标签排序后再进行添加,好进行条件判断分离出来
list.add(0,new User("新的朋友"));
list.add(1,new User("群聊"));
list.add(2,new User("标签"));
list.add(3,new User("公众号"));
//四个标签图片不需要再服务器获取,直接移动端实现即可
list2 = new ArrayList<>();
list2.add(R.drawable.newfriend);
list2.add(R.drawable.groupchat);
list2.add(R.drawable.sign);
list2.add(R.drawable.publicnum);
/*创建自定义适配器并设置给listview*/
SortAdapter adapter = new SortAdapter(getActivity().getApplicationContext(), list, list2, data);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
String his_name=list.get(i).getName();
Intent intent = new Intent(getActivity(),ChatRoom.class);
for(int k =0;k<data.size();k++) {
if (data.get(k).get(his_name) != null) {
intent.putExtra("his_img", data.get(k).get(his_name));
break;
}
}
intent.putExtra("img",Main.img);
intent.putExtra("his_name",his_name);
//页面跳转到登录界面
startActivity(intent);
}
});
}
// 1.编写一个发送请求的方法
// 发送请求的主要方法
public void httpUrlConnPost(String number) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/Contact");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
//json.put("title", URLEncoder.encode(title, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("number", URLEncoder.encode(number, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode()+"");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
System.out.println("测试:" + str);
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
String str1=new String();
String str2=new String();
for(int i=0;i<rjson.getJSONArray("json").length();i++){
str1 += rjson.getJSONArray("json").getJSONObject(i).get("img").toString();
str1 += "\r\n";
str2 += rjson.getJSONArray("json").getJSONObject(i).get("name").toString();
str2 += "\r\n";
}
imgUrl = str1.split("\r\n");
name = str2.split("\r\n");
boolean result = rjson.getBoolean("j1");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明注册成功否则注册失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
myhander.sendEmptyMessage(1);
Log.i("用户:", "登录成功");
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用户:", "登录失败");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明注册成功如果是2说明注册失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "");
break;
case 2:
Log.i("aa", msg.what + "");
}
}
}
}

View File

@@ -0,0 +1,62 @@
package com.example.teambag;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ListView;
import com.example.teambag.R;
import com.example.teambag.adapter.findSortAdapter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class FindFragment extends Fragment {
/* 声明组件*/
private ListView listView;
//定义一个map集合存放数据
private List<Map<String,String>> list = new ArrayList<>();
//准备图片
private int[] pic = new int[]{
R.drawable.friend_img,R.drawable.video_img,
R.drawable.scan_img,R.drawable.shark_img,
R.drawable.look_img,R.drawable.search_img,
R.drawable.direct_seeding_img,R.drawable.shopping_img,
R.drawable.game_img,R.drawable.small_routine_img,
};
//准备文字
private String data[] =new String[]
{"朋友圈 ","视频号 " ,"扫一扫 ",
"摇一摇 ","看一看 " ,"搜一搜 ",
"直播和附近","购物 ","游戏 ","小程序 "};
//准备图片
private int[] pic1 = new int[]{
R.drawable.tab_img,R.drawable.tab_img,R.drawable.tab_img,R.drawable.tab_img,
R.drawable.tab_img,R.drawable.tab_img,R.drawable.tab_img,R.drawable.tab_img,
R.drawable.tab_img,R.drawable.tab_img
};
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.find_fragment, container, false);
/*初始化组件*/
listView = (ListView) view.findViewById(R.id.listView);
//初始化数据
initData();
/*创建自定义适配器并设置给listview*/
findSortAdapter adapter = new findSortAdapter(getActivity().getApplicationContext(), list);
listView.setAdapter(adapter);
return view;
}
private void initData() {
for(int i=0;i<data.length;i++){
Map<String,String> map = new HashMap<>();
map.put("pic",String.valueOf(pic[i]));
map.put("title",data[i]);
map.put("pic1",String.valueOf(pic1[i]));
list.add(map);//将map放到list集合中
}
}
}

View File

@@ -0,0 +1,23 @@
package com.example.teambag;
import android.app.Activity;
import android.app.Dialog;
import android.os.Bundle;
import android.os.Handler;
public class Loading extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.loading); //设置布局
//一秒后结束当前activity
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
Loading.this.finish();
}
}, 1000);
}
}

View File

@@ -0,0 +1,286 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import com.example.teambag.tools.IEditTextChangeListener;
import com.example.teambag.tools.WorksSizeCheckUtil;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class LoginPhone extends AppCompatActivity {
private String number;
private String name;
private String img;
//声明组件变量
private EditText phone;
private EditText password;
private TextView user_login;
private Button button;
//自定义的一个Hander消息机制
private LoginPhone.MyHander myhander = new LoginPhone.MyHander();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_phone); //设置布局
/* 隐藏自带标题*/
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //全屏显示
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //因为背景为浅色所以将状态栏字体设置为黑色
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
initViews(); // 初始化布局元素
// 设置注册按钮是否可点击
if (phone.getText() + "" == "" || password.getText() + "" == "") {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
inputFocus(); //监听EditView变色
buttonChangeColor(); //登录按钮变色
//设置通过微信号登录的监听器
user_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到用微信号登录的activity
Intent intent = new Intent(LoginPhone.this, LoginUser.class);
startActivity(intent);
}
});
//button的点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建一个进度条的activity,通过AndroidMainfest.xml文件声明为对胡框这样activity就不会覆盖当前的activity
Intent intent = new Intent();
intent.setClass(LoginPhone.this, Loading.class);
startActivity(intent);
// 开一个线程完成网络请求操作
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
httpUrlConnPost(LoginPhone.this.phone.getText() + "",
password.getText() + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
@SuppressLint("NewApi")
public void initViews() {
// 得到所有的组件
phone = (EditText) this.findViewById(R.id.log_phone);
password = (EditText) this.findViewById(R.id.log_passwd);
user_login = (TextView) this.findViewById(R.id.user_log);
button = (Button) this.findViewById(R.id.log_button);
}
public void inputFocus() {
phone.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver1);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver1);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver2);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver2);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
}
public void buttonChangeColor() {
//创建工具类对象 把要改变颜色的Button先传过去
WorksSizeCheckUtil.textChangeListener textChangeListener = new WorksSizeCheckUtil.textChangeListener(button);
textChangeListener.addAllEditText(phone, password);//把所有要监听的EditText都添加进去
//接口回调 在这里拿到boolean变量 根据isHasContent的值决定 Button应该设置什么颜色
WorksSizeCheckUtil.setChangeListener(new IEditTextChangeListener() {
@Override
public void textChange(boolean isHasContent) {
if (isHasContent) {
button.setBackgroundResource(R.drawable.login_button_focus);
button.setTextColor(getResources().getColor(R.color.loginButtonTextFouse));
} else {
button.setBackgroundResource(R.drawable.login_button_shape);
button.setTextColor(getResources().getColor(R.color.loginButtonText));
}
}
});
}
// 发送请求的主要方法
public void httpUrlConnPost(String phone, String password) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/Login");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
json.put("number", URLEncoder.encode(phone, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("password", URLEncoder.encode(password, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode() + "");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
Log.i("aa", "rjson=" + rjson);// rjson={"json":true}
boolean result = rjson.getBoolean("json");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明登录成功否则登录失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
number=rjson.getString("number");
name=rjson.getString("name");
img=rjson.getString("img");
myhander.sendEmptyMessage(1);
Log.i("用户:", "登录成功,number = "+ number);
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用户:", "登录失败");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明登录成功如果是2说明登录失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "111111");
//System.out.println("number"+number);
Toast.makeText(getApplicationContext(), "登录成功",
Toast.LENGTH_SHORT).show();
Intent intent = new Intent (com.example.teambag.LoginPhone.this, com.example.teambag.Main.class);
intent.putExtra("chat_number",number);
intent.putExtra("name",name);
intent.putExtra("img",img);
startActivity(intent);
com.example.teambag.LoginPhone.this.finish();
break;
case 2:
Log.i("aa", msg.what + "");
new AlertDialog.Builder(com.example.teambag.LoginPhone.this)
.setTitle(" 登录失败")
.setMessage(" 手机号或密码错误,请重新填写")
.setPositiveButton("确定", null)
.show();
}
}
}
//返回按钮处理事件
public void login_activity_back(View v) {
/*跳转到微信启动页*/
Intent intent = new Intent();
intent.setClass(com.example.teambag.LoginPhone.this, Welcome.class);
startActivity(intent);
com.example.teambag.LoginPhone.this.finish(); //结束当前activity
}
}

View File

@@ -0,0 +1,294 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Intent;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import com.example.teambag.tools.IEditTextChangeListener;
import com.example.teambag.tools.WorksSizeCheckUtil;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
public class LoginUser extends AppCompatActivity {
private String number;
private String name;
private String img;
//声明组件变量
private EditText userNumber;
private EditText password;
private TextView phone_login;
private Button button;
//自定义的一个Hander消息机制
private MyHander myhander = new MyHander();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_user); //设置布局
/* 隐藏自带标题*/
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //全屏显示
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //因为背景为浅色所以将状态栏字体设置为黑色
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
initViews(); // 初始化布局元素
/*获取注册activity传过来的微信号*/
Intent intent = getIntent();
String number = intent.getStringExtra("chat_number");
//把传过来的值显示在登录布局上
userNumber.setText(number);
// 设置注册按钮是否可点击
if (userNumber.getText() + "" == "" || password.getText() + "" == "") {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
inputFocus(); //监听EditView变色
buttonChangeColor(); //登录按钮变色
// 设置手机号登录的监听器
phone_login.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//跳转到手机号登录的activity
Intent intent=new Intent(LoginUser.this,LoginPhone.class);
startActivity(intent);
}
});
//button的点击事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//创建一个进度条的activity,通过AndroidMainfest.xml文件声明为对话框这样activity就不会覆盖当前的activity
Intent intent = new Intent();
intent.setClass(LoginUser.this, Loading.class);
startActivity(intent);
// 开一个线程完成网络请求操作
new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(1000);
httpUrlConnPost(LoginUser.this.userNumber.getText() + "",
password.getText() + "");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
});
}
@SuppressLint("NewApi")
public void initViews() {
// 得到所有的组件
userNumber = (EditText) this.findViewById(R.id.log_user_number);
password = (EditText) this.findViewById(R.id.log_passwd);
phone_login = (TextView) this.findViewById(R.id.phone_log);
button = (Button) this.findViewById(R.id.log_button);
}
public void inputFocus() {
userNumber.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver1);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver1);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver2);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.login_diver2);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
}
public void buttonChangeColor() {
//创建工具类对象 把要改变颜色的Button先传过去
WorksSizeCheckUtil.textChangeListener textChangeListener = new WorksSizeCheckUtil.textChangeListener(button);
textChangeListener.addAllEditText(userNumber, password);//把所有要监听的EditText都添加进去
//接口回调 在这里拿到boolean变量 根据isHasContent的值决定 Button应该设置什么颜色
WorksSizeCheckUtil.setChangeListener(new IEditTextChangeListener() {
@Override
public void textChange(boolean isHasContent) {
if (isHasContent) {
button.setBackgroundResource(R.drawable.login_button_focus);
button.setTextColor(getResources().getColor(R.color.loginButtonTextFouse));
} else {
button.setBackgroundResource(R.drawable.login_button_shape);
button.setTextColor(getResources().getColor(R.color.loginButtonText));
}
}
});
}
// 发送请求的主要方法
public void httpUrlConnPost(String number, String password) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/Login");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
json.put("number", URLEncoder.encode(number, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("password", URLEncoder.encode(password, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode() + "");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
Log.i("aa", "rjson=" + rjson);// rjson={"json":true}
boolean result = rjson.getBoolean("json");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明登录成功否则登录失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
this.number = rjson.getString("number");
this.name = rjson.getString("name");
this.img = rjson.getString("img");
myhander.sendEmptyMessage(1);
Log.i("用户:", "登录成功");
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用户:", "登录失败");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明登录成功如果是2说明登录失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "");
//提示
Toast.makeText(getApplicationContext(), "登录成功",
Toast.LENGTH_SHORT).show();
//通过Intent跳转到微信首页把微信号传过去
Intent intent = new Intent();
intent.setClass(com.example.teambag.LoginUser.this,
com.example.teambag.Main.class);
intent.putExtra("chat_number", number);
intent.putExtra("name",name);
intent.putExtra("img",img);
startActivity(intent);
com.example.teambag.LoginUser.this.finish();//结束当前activity
break;
case 2:
Log.i("aa", msg.what + "");
//对话框
new AlertDialog.Builder(com.example.teambag.LoginUser.this)
.setTitle(" 登录失败")
.setMessage(" 用户名或密码错误,请重新填写")
.setPositiveButton("确定", null)
.show();
break;
}
}
}
//返回按钮处理事件
public void login_activity_back(View v) {
/*跳转到微信启动页*/
Intent intent = new Intent();
intent.setClass(com.example.teambag.LoginUser.this, Welcome.class);
startActivity(intent);
com.example.teambag.LoginUser.this.finish(); //结束当前activity
}
}

View File

@@ -0,0 +1,437 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
import com.example.teambag.tools.User;
import org.json.JSONObject;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Main extends FragmentActivity implements View.OnClickListener {
private ChatFragment firstFragment = null;// 用于显示聊天界面
private ContactListFragment secondFragment = null;// 用于显示通讯录界面
private FindFragment thirdFragment = null;// 用于显示发现界面
private SelfFragment fourthFragment = null;// 用于显示我界面
private View firstLayout = null;// 微信显示布局
private View secondLayout = null;// 通讯录显示布局
private View thirdLayout = null;// 发现显示布局
private View fourthLayout = null;// 我显示布局
/*声明组件变量*/
private ImageView chatImg = null;
private ImageView contactImg = null;
private ImageView findImg = null;
private ImageView selfImg = null;
private TextView chatText = null;
private TextView contactText = null;
private TextView findText = null;
private TextView selfText = null;
String[] imgUrl;
String[] name;
/*声明或创建集合,用于处理数据*/
public static ArrayList<User> list;
public static ArrayList<Integer> list2;
public static List<Map<String, String>> data = new ArrayList<Map<String, String>>();
//自定义的一个Hander消息机制
private MyHander myhander = new MyHander();
//用于查找微信消息列表
public static String number;
public static String userName;
public static String img;
private FragmentManager fragmentManager = null;// 用于对Fragment进行管理
@Override
protected void onCreate(Bundle savedInstanceState) {
/*获取登录activity传过来的微信号*/
Intent intent = getIntent();
number = intent.getStringExtra("chat_number");
userName = intent.getStringExtra("name");
img = intent.getStringExtra("img");
System.out.println("img: "+img);
/*开启一个线程,向服务器请求通讯录数据*/
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
httpUrlConnPost(String.valueOf(number));
}
});
thread1.start();
/*等待线性处理完成*/
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
initData(); //初始化数据
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);//要求窗口没有title
super.setContentView(R.layout.main);
// 初始化布局元素
initViews();
fragmentManager = getFragmentManager();//用于对Fragment进行管理
// 设置默认的显示界面
setTabSelection(0);
}
/**
* 在这里面获取到每个需要用到的控件的实例,并给它们设置好必要的点击事件
*/
@SuppressLint("NewApi")
public void initViews() {
fragmentManager = getFragmentManager();
firstLayout = findViewById(R.id.chat_layout);
secondLayout = findViewById(R.id.contacts_layout);
thirdLayout = findViewById(R.id.find_layout);
fourthLayout = findViewById(R.id.self_layout);
chatImg = (ImageView) findViewById(R.id.chat_img);
contactImg = (ImageView) findViewById(R.id.contact_img);
findImg = (ImageView) findViewById(R.id.find_img);
selfImg = (ImageView) findViewById(R.id.self_img);
chatText = (TextView) findViewById(R.id.chat_text);
contactText = (TextView) findViewById(R.id.contact_text);
findText = (TextView) findViewById(R.id.find_text);
selfText = (TextView) findViewById(R.id.self_text);
//处理点击事件
firstLayout.setOnClickListener(this);
secondLayout.setOnClickListener(this);
thirdLayout.setOnClickListener(this);
fourthLayout.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.chat_layout:
setTabSelection(0);// 当点击了微信时选中第1个tab
break;
case R.id.contacts_layout:
setTabSelection(1);// 当点击了通讯录时选中第2个tab
break;
case R.id.find_layout:
setTabSelection(2);// 当点击了发现时选中第3个tab
break;
case R.id.self_layout:
setTabSelection(3);// 当点击了我时选中第4个tab
break;
default:
break;
}
}
/**
* 根据传入的index参数来设置选中的tab页 每个tab页对应的下标。0表示微信1表示通讯录2表示发现3表示我
*/
@SuppressLint("NewApi")
private void setTabSelection(int index) {
clearSelection();// 每次选中之前先清除掉上次的选中状态
FragmentTransaction transaction = fragmentManager.beginTransaction();// 开启一个Fragment事务
hideFragments(transaction);// 先隐藏掉所有的Fragment以防止有多个Fragment显示在界面上的情况
switch (index) {
case 0:
// 当点击了我的微信tab时改变控件的图片和文字颜色
chatImg.setImageResource(R.drawable.tab_chat_pressed);//修改布局中的图片
chatText.setTextColor(Color.parseColor("#0090ff"));//修改字体颜色
if (firstFragment == null) {
/*获取登录activity传过来的微信号*/
Intent intent = getIntent();
String number = intent.getStringExtra("chat_number");
// 如果FirstFragment为空则创建一个并添加到界面上
firstFragment = new ChatFragment(number);
transaction.add(R.id.fragment, firstFragment);
} else {
// 如果FirstFragment不为空则直接将它显示出来
transaction.show(firstFragment);//显示的动作
}
break;
// 以下和firstFragment类同
case 1:
contactImg.setImageResource(R.drawable.tab_address_pressed);
contactText.setTextColor(Color.parseColor("#0090ff"));
if (secondFragment == null) {
/*获取登录activity传过来的微信号*/
Intent intent = getIntent();
String number = intent.getStringExtra("chat_number");
secondFragment = new ContactListFragment(number);
transaction.add(R.id.fragment, secondFragment);
} else {
transaction.show(secondFragment);
}
break;
case 2:
findImg.setImageResource(R.drawable.tab_find_frd_pressed);
findText.setTextColor(Color.parseColor("#0090ff"));
if (thirdFragment == null) {
thirdFragment = new FindFragment();
transaction.add(R.id.fragment, thirdFragment);
} else {
transaction.show(thirdFragment);
}
break;
case 3:
selfImg.setImageResource(R.drawable.tab_settings_pressed);
selfText.setTextColor(Color.parseColor("#0090ff"));
if (fourthFragment == null) {
fourthFragment = new SelfFragment();
transaction.add(R.id.fragment, fourthFragment);
} else {
transaction.show(fourthFragment);
}
break;
}
transaction.commit();
}
/**
* 清除掉所有的选中状态
*/
private void clearSelection() {
chatImg.setImageResource(R.drawable.tab_chat_normal);
chatText.setTextColor(Color.parseColor("#82858b"));
contactImg.setImageResource(R.drawable.tab_address_normal);
contactText.setTextColor(Color.parseColor("#82858b"));
findImg.setImageResource(R.drawable.tab_find_frd_normal);
findText.setTextColor(Color.parseColor("#82858b"));
selfImg.setImageResource(R.drawable.tab_settings_normal);
selfText.setTextColor(Color.parseColor("#82858b"));
}
/**
* 将所有的Fragment都设置为隐藏状态 用于对Fragment执行操作的事务
*/
@SuppressLint("NewApi")
private void hideFragments(FragmentTransaction transaction) {
if (firstFragment != null) {
transaction.hide(firstFragment);
}
if (secondFragment != null) {
transaction.hide(secondFragment);
}
if (thirdFragment != null) {
transaction.hide(thirdFragment);
}
if (fourthFragment != null) {
transaction.hide(fourthFragment);
}
}
//搜索按钮处理事件
public void search(View v) {
//跳转到微信启动页
Intent intent = new Intent();
intent.setClass(com.example.teambag.Main.this,
com.example.teambag.Search.class);
startActivity(intent);
}
//加号点击事件处理方法
public void buttonTopRight(View v) {
Intent intent = new Intent(com.example.teambag.Main.this,
com.example.teambag.MainTopRightDialog.class);
startActivity(intent);
}
private void initData() {
//把从服务器获取解析的数据添加到map中方便处理
Map<String, String> map = new HashMap<String, String>();
for (int i = 1; i < imgUrl.length; i ++) {
map.put(name[i], imgUrl[i]);
}
data.add(map);
//名字要提取出来在添加到list中因为要进行字母排序
list = new ArrayList<>();
if (imgUrl.length != 1) {
for (int i = 0; i < imgUrl.length; i++) {
list.add(new User(name[i]));
}
Collections.sort(list); // 对list进行排序需要让User实现Comparable接口重写compareTo方法
//四个标签排序后再进行添加,好进行条件判断分离出来
list.add(0,new User("新的朋友"));
list.add(1,new User("群聊"));
list.add(2,new User("标签"));
list.add(3,new User("公众号"));
//四个标签图片不需要再服务器获取,直接移动端实现即可
list2 = new ArrayList<>();
list2.add(R.drawable.newfriend);
list2.add(R.drawable.groupchat);
list2.add(R.drawable.sign);
list2.add(R.drawable.publicnum);
}
}
// 1.编写一个发送请求的方法
// 发送请求的主要方法
public void httpUrlConnPost(String number) {
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/Contact");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
//json.put("title", URLEncoder.encode(title, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("number", URLEncoder.encode(number, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode()+"");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
System.out.println("测试:" + str);
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
String str1=new String();
String str2=new String();
for(int i=0;i<rjson.getJSONArray("json").length();i++){
str1 += rjson.getJSONArray("json").getJSONObject(i).get("img").toString();
str1 += "\r\n";
str2 += rjson.getJSONArray("json").getJSONObject(i).get("name").toString();
str2 += "\r\n";
}
imgUrl = str1.split("\r\n");
name = str2.split("\r\n");
boolean result = rjson.getBoolean("j1");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明注册成功否则注册失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
myhander.sendEmptyMessage(1);
Log.i("用户:", "登录成功");
} else {
myhander.sendEmptyMessage(2);
System.out.println("222222222222222");
Log.i("用户:", "登录失败");
}
} else {
myhander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
System.out.println("11111111111111111");
myhander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明注册成功如果是2说明注册失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "");
break;
case 2:
Log.i("aa", msg.what + "");
}
}
}
}
/*
//封装一个AlertDialog
private void exitDialog() {
Dialog dialog = new AlertDialog.Builder(this)
.setTitle("温馨提示")
.setMessage("您确定要退出程序吗?")
.setPositiveButton("退出", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
finish();
}
})
.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface arg0, int arg1) {
}
}).create();
dialog.show();
}
//返回菜单键监听事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {//如果是返回按钮
exitDialog();
}
return super.onKeyDown(keyCode, event);
}
*/

View File

@@ -0,0 +1,61 @@
package com.example.teambag;
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.widget.LinearLayout;
public class MainTopRightDialog extends Activity {
private LinearLayout layout;
private Animation animation1;
private Animation animation2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_top_right_dialog);
//设置对话框activity的宽度等于屏幕宽度一定要设置不然对话框会显示不全
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);//需要添加的语句
layout=(LinearLayout)findViewById(R.id.main_dialog_layout);
animation1=AnimationUtils.loadAnimation(this,R.anim.push_top_in2);
//layout.startAnimation(animation1);
layout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event){
animation2=AnimationUtils.loadAnimation(this,R.anim.push_top_out2);
animation2.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
finish();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
layout.startAnimation(animation2);
return true;
}
@Override
public void finish(){
super.finish();
}
}

View File

@@ -0,0 +1,40 @@
package com.example.teambag;
public class Msg {
public static final int TYPE_RECEIVED = 0; //标记用于判断是输出消息还是接收消息
public static final int TYPE_SENT = 1;
private String content; //存储消息信息
private int type; //存储判断信息
private String time;
private String name;
private String imageId;
public Msg(String content, int type, String time,String name,String imageId) {
this.content = content;
this.type = type;
this.time = time;
this.name = name;
this.imageId = imageId;
}
public String getContent() {
return content;
}
public int getType() {
return type;
}
public String getTime(){
return time;
}
public String getName(){
return name;
}
public String getImageId(){
return imageId;
}
}

View File

@@ -0,0 +1,293 @@
package com.example.teambag;
import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.os.Handler;
import android.widget.ImageView;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import com.example.teambag.tools.IEditTextChangeListener;
import com.example.teambag.tools.RandomUserName;
import com.example.teambag.tools.WorksSizeCheckUtil;
import org.json.JSONObject;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Register extends AppCompatActivity {
//声明组件
private EditText username;
private EditText phone;
private EditText password;
private Button button;
//随机微信
private String randomNumber;
//自定义一个UI修改机制
private MyHander myHander = new MyHander();
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//设置布局
setContentView(R.layout.register);
//隐藏自带标题
ActionBar actionBar = getSupportActionBar();
if(actionBar != null){
actionBar.hide();
}
if(Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //全屏显示
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //因为背景为浅色所以将状态栏字体设置为黑色
}
// 初始化布局元素
initViews();
// 设置注册按钮是否可点击
if (username.getText() + "" == "" || phone.getText() + "" == "" || password.getText() + "" == "") {
button.setEnabled(false);
} else {
button.setEnabled(true);
}
//监听EditView变色
inputFocus();
//监听登录按钮变色
buttonChangeColor();
//button的点击事件事件
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/*判断输入的手机号格式对不对,对的话开一个线程完成网络请求操作*/
Pattern pattern = Pattern
.compile("^(13[0-9]|15[0-9]|153|15[6-9]|180|18[23]|18[5-9])\\d{8}$");
Matcher matcher = pattern.matcher(phone.getText());
if (matcher.matches()) {
// 开一个线程完成网络请求操作
new Thread(new Runnable() {
@Override
public void run() {
httpUrlConnPost(Register.this.username.getText() + "",
phone.getText() + "", password.getText() + "");
}
}).start();
} else {
Toast.makeText(getApplicationContext(), "手机格式错误", Toast.LENGTH_LONG).show();
}
}
});
}
/*在这里面获取到每个需要用到的控件的实例*/
@SuppressLint("NewApi")
public void initViews() {
// 得到所有的组件
username = (EditText) this.findViewById(R.id.reg_name);
phone = (EditText) this.findViewById(R.id.reg_phone);
password = (EditText) this.findViewById(R.id.reg_passwd);
button = (Button) this.findViewById(R.id.reg_button);
}
/*监听EditView变色*/
public void inputFocus() {
username.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver1);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver1);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
phone.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver2);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver2);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
password.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// 此处为得到焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver3);
imageView.setBackgroundResource(R.color.input_dvier_focus);
} else {
// 此处为失去焦点时的处理内容
ImageView imageView = (ImageView) findViewById(R.id.reg_diver3);
imageView.setBackgroundResource(R.color.input_dvier);
}
}
});
}
/*监听登录按钮变色*/
public void buttonChangeColor() {
//创建工具类对象 把要改变颜色的Button先传过去
WorksSizeCheckUtil.textChangeListener textChangeListener = new WorksSizeCheckUtil.textChangeListener(button);
textChangeListener.addAllEditText(username, phone, password);//把所有要监听的EditText都添加进去
//接口回调 在这里拿到boolean变量 根据isHasContent的值决定 Button应该设置什么颜色
WorksSizeCheckUtil.setChangeListener(new IEditTextChangeListener() {
@Override
public void textChange(boolean isHasContent) {
if (isHasContent) {
button.setBackgroundResource(R.drawable.login_button_focus);
button.setTextColor(getResources().getColor(R.color.loginButtonTextFouse));
} else {
button.setBackgroundResource(R.drawable.login_button_shape);
button.setTextColor(getResources().getColor(R.color.loginButtonText));
}
}
});
}
/*发送请求的主要方法*/
public void httpUrlConnPost(String name, String phone, String password) {
/*使用工具类生成随机的微信号*/
RandomUserName ran = new RandomUserName();
randomNumber = ran.generate();
HttpURLConnection urlConnection = null;
URL url;
try {
// 请求的URL地地址
url = new URL(
"http://192.168.31.102:8808/AndroidServer_war_exploded/Reigister");
urlConnection = (HttpURLConnection) url.openConnection();// 打开http连接
urlConnection.setConnectTimeout(3000);// 连接的超时时间
urlConnection.setUseCaches(false);// 不使用缓存
// urlConnection.setFollowRedirects(false);是static函数作用于所有的URLConnection对象。
urlConnection.setInstanceFollowRedirects(true);// 是成员函数,仅作用于当前函数,设置这个连接是否可以被重定向
urlConnection.setReadTimeout(3000);// 响应的超时时间
urlConnection.setDoInput(true);// 设置这个连接是否可以写入数据
urlConnection.setDoOutput(true);// 设置这个连接是否可以输出数据
urlConnection.setRequestMethod("POST");// 设置请求的方式
urlConnection.setRequestProperty("Content-Type",
"application/json;charset=UTF-8");// 设置消息的类型
urlConnection.connect();// 连接从上述至此的配置必须要在connect之前完成实际上它只是建立了一个与服务器的TCP连接
JSONObject json = new JSONObject();// 创建json对象
json.put("number", URLEncoder.encode(randomNumber, "UTF-8"));// 使用URLEncoder.encode对特殊和不可见字符进行编码
json.put("name", URLEncoder.encode(name, "UTF-8"));
json.put("phone", URLEncoder.encode(phone, "UTF-8"));
json.put("password", URLEncoder.encode(password, "UTF-8"));// 把数据put进json对象中
String jsonstr = json.toString();// 把JSON对象按JSON的编码格式转换为字符串
// ------------字符流写入数据------------
OutputStream out = urlConnection.getOutputStream();// 输出流用来发送请求http请求实际上直到这个函数里面才正式发送出去
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out));// 创建字符流对象并用高效缓冲流包装它,便获得最高的效率,发送的是字符串推荐用字符流,其它数据就用字节流
bw.write(jsonstr);// 把json字符串写入缓冲区中
bw.flush();// 刷新缓冲区,把数据发送出去,这步很重要
out.close();
bw.close();// 使用完关闭
Log.i("aa", urlConnection.getResponseCode() + "");
//以下判斷是否訪問成功如果返回的状态码是200则说明访问成功
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {// 得到服务端的返回码是否连接成功
// ------------字符流读取服务端返回的数据------------
InputStream in = urlConnection.getInputStream();
BufferedReader br = new BufferedReader(
new InputStreamReader(in));
String str = null;
StringBuffer buffer = new StringBuffer();
while ((str = br.readLine()) != null) {// BufferedReader特有功能一次读取一行数据
buffer.append(str);
}
in.close();
br.close();
JSONObject rjson = new JSONObject(buffer.toString());
Log.i("aa", "rjson=" + rjson);// rjson={"json":true}
boolean result = rjson.getBoolean("json");// 从rjson对象中得到key值为"json"的数据这里服务端返回的是一个boolean类型的数据
System.out.println("json:===" + result);
//如果服务器端返回的是true则说明注册成功否则注册失败
if (result) {// 判断结果是否正确
//在Android中http请求必须放到线程中去作请求但是在线程中不可以直接修改UI只能通过hander机制来完成对UI的操作
myHander.sendEmptyMessage(1);
Log.i("用户:", "注册成功");
} else {
myHander.sendEmptyMessage(2);
Log.i("用户:", "手机号已被注册");
}
} else {
myHander.sendEmptyMessage(2);
}
} catch (Exception e) {
e.printStackTrace();
Log.i("aa", e.toString());
myHander.sendEmptyMessage(2);
} finally {
urlConnection.disconnect();// 使用完关闭TCP连接释放资源
}
}
// 在Android中不可以在线程中直接修改UI只能借助Handler机制来完成对UI的操作
class MyHander extends Handler {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//判断hander的内容是什么如果是1则说明注册成功如果是2说明注册失败
switch (msg.what) {
case 1:
Log.i("aa", msg.what + "!");
Toast.makeText(getApplicationContext(), "注册成功",
Toast.LENGTH_SHORT).show();
/*跳转到登录页面并把微信号也传过去*/
Intent intent = new Intent();
intent.putExtra("chat_number", randomNumber);
intent.setClass(com.example.teambag.Register.this, LoginUser.class);
startActivity(intent);
com.example.teambag.Register.this.finish(); //结束当前activity
break;
case 2:
Log.i("aa", msg.what + "");
//這是一個提示消息
Toast.makeText(getApplicationContext(), "手机号已被注册", Toast.LENGTH_LONG).show();
}
}
}
//返回按钮处理事件
public void rigister_activity_back(View v) {
/*跳转到微信启动页*/
Intent intent = new Intent();
intent.setClass(com.example.teambag.Register.this, Welcome.class);
startActivity(intent);
com.example.teambag.Register.this.finish(); //结束当前activity
}
}

View File

@@ -0,0 +1,113 @@
package com.example.teambag;
import android.graphics.Color;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.BaseAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.SearchView;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import com.example.teambag.adapter.SearchSortAdapter;
import com.example.teambag.tools.User;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Search extends AppCompatActivity {
//声明组件
private SearchView mSearchView;
private ListView mListView;
private LinearLayout label;
private LinearLayout top;
//创建集合用户处理搜索功能
private List<User> list = Main.list;
private List<User> list1 = null;
public static List<Map<String, String>> data = Main.data;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.search);
/* 隐藏自带标题*/
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.hide();
}
if (Build.VERSION.SDK_INT >= 21) {
View decorView = getWindow().getDecorView();
int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN //全屏显示
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; //因为背景为浅色所以将状态栏字体设置为黑色
decorView.setSystemUiVisibility(option);
getWindow().setStatusBarColor(Color.TRANSPARENT);
}
//初始化组件
mListView = (ListView) findViewById(R.id.listView);
label = (LinearLayout) findViewById(R.id.label);
top = (LinearLayout) findViewById(R.id.top);
mSearchView = (SearchView) findViewById(R.id.searview);
//设置searchview适配器
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return true;
}
//获取输入内容
@Override
public boolean onQueryTextChange(String newText) {
//如果newText是长度为0的字符串则显示下面的指定搜索内容不显示listview和联系人
if (TextUtils.isEmpty(newText)){
label.setVisibility(View.VISIBLE);
mListView.setVisibility(View.GONE);
top.setVisibility(View.GONE);
}else { //否则显示listview显示结果其他都隐藏掉
label.setVisibility(View.GONE);
mListView.setVisibility(View.VISIBLE);
System.out.println("+++++" + newText);
list1 = new ArrayList<>();//创建集合,存储检索到的数据
/*检索数据*/
for (int i = 0; i < list.size(); i ++) {
char[] inputText = newText.toCharArray();
char[] chars = list.get(i).getName().toCharArray();
for (int j = 0; j < inputText.length; j++) {
if (j < chars.length) {
if (inputText[j] == chars[j] ||
newText.equalsIgnoreCase(list.get(i).getFirstLetter())) {
if (j == (inputText.length - 1)) {
top.setVisibility(View.VISIBLE);
list1.add(new User(list.get(i).getName()));
}
}else {
break;
}
}
}
}
if (list1.size() != 0) {
//创建自定义的适配器,用于把数据显示在组件上
BaseAdapter adapter = new SearchSortAdapter(getApplicationContext(), data,
list1, newText, mListView);
//设置适配器
mListView.setAdapter(adapter);
} else {
mListView.setVisibility(View.GONE);
}
}
return false;
}
});
}
//取消返回
public void back(View v) {
this.finish();
}
}

View File

@@ -0,0 +1,14 @@
package com.example.teambag;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class SelfFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.self_fragment, container, false);
return view;
}
}

View File

@@ -0,0 +1,36 @@
package com.example.teambag;
import android.app.Activity;
import android.app.Dialog;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
public class Welcome extends Activity {
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
//设置布局
setContentView(R.layout.welcome);
}
//登录按钮点击事件处理
public void welcome_login(View view){
Intent intent = new Intent();
//页面跳转到登录界面
intent.setClass(com.example.teambag.Welcome.this,com.example.teambag.LoginUser.class);
startActivity(intent);
//结束当前activity
this.finish();
}
//注册按钮点击事件处理
public void welcome_register(View view){
Intent intent = new Intent();
//页面跳转到注册界面
intent.setClass(com.example.teambag.Welcome.this,com.example.teambag.Register.class);
startActivity(intent);
//结束当前activity
this.finish();
}
}

View File

@@ -0,0 +1,107 @@
package com.example.teambag.adapter;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.teambag.tools.GetImageByUrl;
import com.example.teambag.R;
import java.util.List;
import java.util.Map;
public class ImageAdapter extends BaseAdapter {
// 要显示的数据的集合
private List<Map<String, Object>> data;
// 接受上下文
private Context context;
// 声明内部类对象
private ViewHolder viewHolder;
public ImageAdapter(Context context, List<Map<String, Object>> data) {
this.context = context;
this.data = data;
}
// 返回的总个数
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}
// 返回每个条目对应的数据
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}
// 返回的id
@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
// 返回这个条目对应的控件对象
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// 判断当前条目是否为null
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = View.inflate(context, R.layout.chat_item, null);
viewHolder.img1 = (ImageView) convertView
.findViewById(R.id.img1);
viewHolder.title = (TextView) convertView
.findViewById(R.id.title);
viewHolder.content = (TextView) convertView
.findViewById(R.id.content);
viewHolder.time = (TextView) convertView
.findViewById(R.id.time);
viewHolder.code = (ImageView) convertView
.findViewById(R.id.code);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
// 获取List集合中的map对象
Map<String, Object> map = data.get(position);
// 获取图片的url路径
String pic = map.get("pic").toString();
// 这里调用了图片加载工具类的setImage方法将图片直接显示到控件上
GetImageByUrl getImageByUrl = new GetImageByUrl();
getImageByUrl.setImage(viewHolder.img1, pic);
String title = map.get("title").toString();
viewHolder.title.setText(title);
String content = map.get("content").toString();
viewHolder.content.setText(content);
String time = map.get("time").toString();
viewHolder.time.setText(time);
// 获取图片的url路径
String code = map.get("code").toString();
// 这里调用了图片加载工具类的setImage方法将图片直接显示到控件上
GetImageByUrl getImageByUrl2 = new GetImageByUrl();
getImageByUrl2.setImage(viewHolder.code, code);
return convertView;
}
/**
* 内部类 记录单个条目中所有属性
*
*
*
*/
class ViewHolder {
public ImageView img1;
public TextView title;
public TextView content;
public TextView time;
public ImageView code;
}
}

View File

@@ -0,0 +1,95 @@
package com.example.teambag.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.example.teambag.Msg;
import com.example.teambag.R;
import com.example.teambag.tools.GetImageByUrl;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.zip.Inflater;
public class MsgAdapter extends RecyclerView.Adapter<MsgAdapter.ViewHolder> {
List<Msg> mMsgList;
GetImageByUrl getImageByUrl = new GetImageByUrl();
//把显示的数据源传进来
public MsgAdapter(List<Msg> msgList) {
super();
mMsgList = msgList;
}
//创建ViewHolder实例
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.msg_item,parent,false);
return new ViewHolder(view);
}
//对RecyclerView子项数据进行赋值
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Msg msg = mMsgList.get(position);
holder.time.setText((CharSequence)msg.getTime());
if(msg.getType() == Msg.TYPE_RECEIVED){ //接收端
getImageByUrl.setImage(holder.his_head,msg.getImageId());
//holder.his_head.setImageResource(msg.getImageId());
holder.leftLayout.setVisibility(View.VISIBLE); //左可见
holder.rightLayout.setVisibility(View.GONE); //右不可见
holder.hisName.setText(msg.getName());
holder.leftMsg.setText(msg.getContent()); //左边显示消息
}else if(msg.getType() == Msg.TYPE_SENT){
getImageByUrl.setImage(holder.my_head,msg.getImageId());
//holder.my_head.setImageResource(msg.getImageId());
holder.rightLayout.setVisibility(View.VISIBLE);
holder.leftLayout.setVisibility(View.GONE);
holder.name.setText(msg.getName());
holder.rightMsg.setText(msg.getContent());
}
}
//告诉RecycleView一共多少子项返回数据源长度
@Override
public int getItemCount() {
return mMsgList.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
LinearLayout leftLayout ;
LinearLayout rightLayout;
TextView leftMsg;
TextView rightMsg;
TextView time;
TextView name;
TextView hisName;
ImageView my_head;
ImageView his_head;
public ViewHolder(View view) {
super(view);
leftLayout = view.findViewById(R.id.left_layout);
rightLayout = view.findViewById(R.id.right_layout);
leftMsg = view.findViewById(R.id.left_msg);
rightMsg = view.findViewById(R.id.right_msg);
time = view.findViewById(R.id.time); //显示时间
name = view.findViewById(R.id.my_name);
hisName = view.findViewById(R.id.others_name);
my_head = view.findViewById(R.id.head_my);
his_head = view.findViewById(R.id.head_others);
}
}
}

View File

@@ -0,0 +1,177 @@
package com.example.teambag.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;
import com.example.teambag.R;
import com.example.teambag.tools.User;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
public class SearchSortAdapter extends BaseAdapter{
//自定义handler机制
private ImageHandler imgHandler = new ImageHandler();
private Bitmap img;
private ViewHolder viewHolder;
private String newText;
private List<User> list = null;;
private List<Map<String, String>> data = null;
private Context mContext;
public SearchSortAdapter(Context mContext, List<Map<String, String>> data, List<User> list,
String newText, ListView mListView) {
this.mContext = mContext;
this.list = list;
this.data = data;
this.newText = newText;
}
public int getCount() {
return this.list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup arg2) {
final User user = list.get(position);
if (view == null) {
viewHolder = new ViewHolder();
//获取listview对应的item布局
view = LayoutInflater.from(mContext).inflate(R.layout.search_item, null);
//初始化组件
viewHolder.search_img = (ImageView) view.findViewById(R.id.search_img);
viewHolder.search_text = (TextView) view.findViewById(R.id.search_text);
viewHolder.search_list = (LinearLayout) view.findViewById(R.id.search_list);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
if (this.list.get(position).getName().equals("新的朋友") || this.list.get(position).getName().equals("标签")
|| this.list.get(position).getName().equals("群聊") || this.list.get(position).getName().equals("公众号")) {
}else {
Map<String, String> map = data.get(0);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
img = getImg(map.get(list.get(position).getName()));
Message msg = imgHandler.obtainMessage();
msg.what = 0;
msg.obj = img;
imgHandler.sendMessage(msg);
}
});
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
viewHolder.search_img.setImageBitmap(img);
viewHolder.search_text.setText(this.list.get(position).getName());
}
return view;
}
final static class ViewHolder {
TextView search_text;
ImageView search_img;
LinearLayout search_list;
}
/**
* 从服务器读取图片流数据并转换为Bitmap格式
* @return Bitmap
*/
private Bitmap getImg(String url){
Bitmap img = null;
try {
URL imgUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imgUrl.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(1000 * 6);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");
conn.connect();
//输出流写参数
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
String param = getParam();
dos.writeBytes(param);
dos.flush();
dos.close();
int resultCode = conn.getResponseCode();
if(HttpURLConnection.HTTP_OK == resultCode){
InputStream is = conn.getInputStream();
img = BitmapFactory.decodeStream(is);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
/**
* 测试参数
* @return
*/
private String getParam(){
JSONObject jsObj = new JSONObject();
try {
jsObj.put("picFormat", "jpg");
jsObj.put("testParam", "9527");
} catch (JSONException e) {
e.printStackTrace();
}
return jsObj.toString();
}
/**
* 异步线程请求到的图片数据利用Handler在主线程中显示
*/
class ImageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
img = (Bitmap)msg.obj;
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,217 @@
package com.example.teambag.adapter;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.teambag.R;
import com.example.teambag.tools.User;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
public class SortAdapter extends BaseAdapter{
//自定义handler机制
private ImageHandler imgHandler = new ImageHandler();
private Bitmap img;
private ViewHolder viewHolder;
private List<User> list = null;
private List<Integer> list2 = null;
private List<Map<String, String>> data = null;
private Context mContext;
public SortAdapter(Context mContext, List<User> list, List<Integer> list2, List<Map<String, String>> data) {
this.mContext = mContext;
this.list = list;
this.list2 = list2;
this.data = data;
}
public int getCount() {
return this.list.size();
}
public Object getItem(int position) {
return list.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup arg2) {
final User user = list.get(position);
if (view == null) {
viewHolder = new ViewHolder();
//获取listview对应的item布局
view = LayoutInflater.from(mContext).inflate(R.layout.contactlist_item, null);
//初始化组件
viewHolder.img = (ImageView) view.findViewById(R.id.img);
viewHolder.name = (TextView) view.findViewById(R.id.name);
viewHolder.catalog = (TextView) view.findViewById(R.id.catalog);
viewHolder.contact_count = (TextView) view.findViewById(R.id.contact_count);
viewHolder.divider = (View) view.findViewById(R.id.divider);
view.setTag(viewHolder);
} else {
System.out.println("position=" + position);
viewHolder = (ViewHolder) view.getTag();
}
//0~3是标签单独处理
if (position == 0 || position == 1 || position == 2 || position == 3) {
viewHolder.catalog.setVisibility(View.GONE);
viewHolder.img.setImageResource(list2.get(position));
viewHolder.name.setText(this.list.get(position).getName());
viewHolder.divider.setVisibility(View.GONE);
viewHolder.contact_count.setVisibility(View.GONE);
}else {
//根据position获取首字母作为目录catalog
String catalog = list.get(position).getFirstLetter();
//如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
if(position == getPositionForSection(catalog)){
viewHolder.catalog.setVisibility(View.VISIBLE);
viewHolder.catalog.setText(user.getFirstLetter().toUpperCase());
}else{
viewHolder.catalog.setVisibility(View.GONE);
}
Map<String, String> map = data.get(0);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
img = getImg(map.get(list.get(position).getName()));
Message msg = imgHandler.obtainMessage();
msg.what = 0;
msg.obj = img;
imgHandler.sendMessage(msg);
}
});
thread1.start();
try {
thread1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
viewHolder.img.setImageBitmap(img);
viewHolder.name.setText(this.list.get(position).getName());
if (position == list.size() - 1) {
viewHolder.divider.setVisibility(View.VISIBLE);
viewHolder.contact_count.setVisibility(View.VISIBLE);
viewHolder.contact_count.setText(Integer.toString(position - 3) + "个朋友");
}else {
viewHolder.divider.setVisibility(View.GONE);
viewHolder.contact_count.setVisibility(View.GONE);
}
}
return view;
}
final static class ViewHolder {
TextView catalog;
ImageView img;
TextView name;
TextView contact_count;
View divider;
}
/**
* 获取catalog首次出现位置
*/
public int getPositionForSection(String catalog) {
for (int i = 0; i < getCount(); i++) {
if (list.get(i).getName() != "新的朋友" && list.get(i).getName() != "群聊" &&
list.get(i).getName() != "标签" && list.get(i).getName() != "公众号") {
String sortStr = list.get(i).getFirstLetter();
if (catalog.equalsIgnoreCase(sortStr)) {
return i;
}
}
}
return -1;
}
/**
* 从服务器读取图片流数据并转换为Bitmap格式
* @return Bitmap
*/
private Bitmap getImg(String url){
Bitmap img = null;
try {
URL imgUrl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) imgUrl.openConnection();
conn.setRequestMethod("POST");
conn.setConnectTimeout(1000 * 6);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.setRequestProperty("Charset", "UTF-8");
conn.connect();
//输出流写参数
DataOutputStream dos = new DataOutputStream(conn.getOutputStream());
String param = getParam();
dos.writeBytes(param);
dos.flush();
dos.close();
int resultCode = conn.getResponseCode();
if(HttpURLConnection.HTTP_OK == resultCode){
InputStream is = conn.getInputStream();
img = BitmapFactory.decodeStream(is);
is.close();
}
} catch (IOException e) {
e.printStackTrace();
}
return img;
}
/**
* 测试参数
* @return
*/
private String getParam(){
JSONObject jsObj = new JSONObject();
try {
jsObj.put("picFormat", "jpg");
jsObj.put("testParam", "9527");
} catch (JSONException e) {
e.printStackTrace();
}
return jsObj.toString();
}
/**
* 异步线程请求到的图片数据利用Handler在主线程中显示
*/
class ImageHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 0:
img = (Bitmap)msg.obj;
break;
default:
break;
}
}
}
}

View File

@@ -0,0 +1,90 @@
package com.example.teambag.adapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.teambag.R;
import java.util.List;
import java.util.Map;
public class findSortAdapter extends BaseAdapter{
private ViewHolder viewHolder;
private List<Map<String, String>> data = null;
private Context mContext;
public findSortAdapter(Context mContext, List<Map<String, String>> data) {
this.mContext = mContext;
this.data = data;
}
public int getCount() {
return this.data.size();
}
public Object getItem(int position) {
return data.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(final int position, View view, ViewGroup arg2) {
if (view == null) {
viewHolder = new ViewHolder();
//获取listview对应的item布局
view = LayoutInflater.from(mContext).inflate(R.layout.find_item, null);
//初始化组件
viewHolder.pic = (ImageView) view.findViewById(R.id.pic);
viewHolder.title = (TextView) view.findViewById(R.id.title);
viewHolder.pic1 = (ImageView) view.findViewById(R.id.pic1);
viewHolder.divider = (View) view.findViewById(R.id.divider);
viewHolder.divider1 = (View) view.findViewById(R.id.divider1);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
if (position == 0 || position == 1 || position == 3 || position == 5 ||
position == 6 || position == 8) {
Map<String, String> map = data.get(position);
viewHolder.pic.setImageResource(Integer.parseInt(map.get("pic")));
viewHolder.title.setText(map.get("title"));
viewHolder.pic1.setImageResource(Integer.parseInt(map.get("pic1")));
viewHolder.divider.setVisibility(View.VISIBLE);
viewHolder.divider1.setVisibility(View.GONE);
}else {
if (position == 9) {
Map<String, String> map = data.get(position);
viewHolder.pic.setImageResource(Integer.parseInt(map.get("pic")));
viewHolder.title.setText(map.get("title"));
viewHolder.pic1.setImageResource(Integer.parseInt(map.get("pic1")));
viewHolder.divider.setVisibility(View.GONE);
viewHolder.divider1.setVisibility(View.VISIBLE);
}else {
Map<String, String> map = data.get(position);
viewHolder.pic.setImageResource(Integer.parseInt(map.get("pic")));
viewHolder.title.setText(map.get("title"));
viewHolder.pic1.setImageResource(Integer.parseInt(map.get("pic1")));
viewHolder.divider.setVisibility(View.GONE);
viewHolder.divider1.setVisibility(View.GONE);
}
}
return view;
}
final static class ViewHolder {
ImageView pic;
TextView title;
ImageView pic1;
View divider;
View divider1;
}
}

View File

@@ -0,0 +1,60 @@
package com.example.teambag.tools;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
/** * 汉字转换位汉语拼音,英文字符不变 */
public class Cn2Spell {
public static StringBuffer sb = new StringBuffer();
/** * 获取汉字字符串的首字母,英文字符不变 * 例如阿飞→af */
public static String getPinYinHeadChar(String chines) {
sb.setLength(0);
char[] chars = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < chars.length; i++) {
if (chars[i] > 128) {
try {
sb.append(PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat)[0].charAt(0)); }
catch (Exception e) {
e.printStackTrace(); }
}
else {
sb.append(chars[i]); }
}
return sb.toString(); }
/** * 获取汉字字符串的第一个字母 */
public static String getPinYinFirstLetter(String str) {
sb.setLength(0);
char c = str.charAt(0);
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
if (pinyinArray != null) {
sb.append(pinyinArray[0].charAt(0)); }
else {
sb.append(c);
}
return sb.toString();
}
/** * 获取汉字字符串的汉语拼音,英文字符不变 */
public static String getPinYin(String chines) {
sb.setLength(0);
char[] nameChar = chines.toCharArray();
HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
for (int i = 0; i < nameChar.length; i++) {
if (nameChar[i] > 128) {
try {
sb.append(PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0]);}
catch (Exception e) {
e.printStackTrace(); }
}
else {
sb.append(nameChar[i]); }
}
return sb.toString();
}
}

View File

@@ -0,0 +1,79 @@
package com.example.teambag.tools;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.widget.ImageView;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 根据图片url路径获取图片
*
*
*
*/
public class GetImageByUrl {
private PicHandler pic_hdl;
private ImageView imgView;
private String url;
/**
* 通过图片url路径获取图片并显示到对应控件上
*
*
*
*/
public void setImage(ImageView imgView, String url) {
this.url = url;
this.imgView = imgView;
pic_hdl = new PicHandler();
Thread t = new LoadPicThread();
t.start();
}
class LoadPicThread extends Thread {
@Override
public void run() {
Bitmap img = getUrlImage(url);
System.out.println(img + "---");
Message msg = pic_hdl.obtainMessage();
msg.what = 0;
msg.obj = img;
pic_hdl.sendMessage(msg);
}
}
class PicHandler extends Handler {
@Override
public void handleMessage(Message msg) {
Bitmap myimg = (Bitmap) msg.obj;
imgView.setImageBitmap(myimg);
}
}
public Bitmap getUrlImage(String url) {
Bitmap img = null;
try {
URL picurl = new URL(url);
HttpURLConnection conn = (HttpURLConnection) picurl
.openConnection();
conn.setConnectTimeout(6000);
conn.setDoInput(true);
conn.setUseCaches(false);
conn.connect();
InputStream is = conn.getInputStream();
img = BitmapFactory.decodeStream(is);
is.close();
} catch (Exception e) {
e.printStackTrace();
}
return img;
}
}

View File

@@ -0,0 +1,5 @@
package com.example.teambag.tools;
public interface IEditTextChangeListener {
void textChange(boolean isHasContent);
}

View File

@@ -0,0 +1,79 @@
package com.example.teambag.tools;
import java.util.Random;
public class RandomUserName {
private static final char[] eng_char = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
private static final String[] first_name = new String[]{"zhao", "qian", "sun", "li", "zhou", "wang", "wu", "zheng", "feng", "chen", "chu", "wei", "jiang", "shen", "yang"
, "zhu", "qin", "you", "xu", "he", "shi", "zhan", "kong", "cao", "xie", "jin", "shu", "fang", "yuan"};
private static final String[] tel_head = new String[]{"13", "18", "15"};
private static final String[] email_suffix = new String[]{"@gmail.com", "@yahoo.com", "@msn.com", "@hotmail.com", "@aol.com", "@ask.com"
, "@live.com", "@qq.com", "@0355.net", "@163.com", "@163.net", "@263.net"
, "@3721.net", "@yeah.net", "@googlemail.com", "@126.com", "@sina.com", "@sohu.com", "@yahoo.com.cn"};
private Random random = new Random();
public String generate() {
StringBuilder uName = new StringBuilder();
int randomType = random.nextInt(Integer.MAX_VALUE) % 3;
switch (randomType) {
case 0: // firstName + randomSecName + birthday
uName.append(first_name[random.nextInt(Integer.MAX_VALUE) % first_name.length])
.append(eng_char[random.nextInt(Integer.MAX_VALUE) % eng_char.length]);
if (random.nextInt(Integer.MAX_VALUE) % 2 == 0) {
uName.append(eng_char[random.nextInt(Integer.MAX_VALUE) % eng_char.length]);
}
// birthday
if (random.nextInt(Integer.MAX_VALUE) % 2 == 0) {
uName.append(String.valueOf(2014 - (random.nextInt(Integer.MAX_VALUE) % (50 - 15) + 15))); // 大于15小于50岁
}
if (random.nextInt(Integer.MAX_VALUE) % 2 == 0) {
int month = random.nextInt(Integer.MAX_VALUE) % 11 + 1;
int day = random.nextInt(Integer.MAX_VALUE) % 29 + 1;
if (month < 10)
uName.append("0");
uName.append(month);
if (day < 10)
uName.append("0");
uName.append(day);
}
if (random.nextInt(Integer.MAX_VALUE % 4) == 0) {// add email suffix , 1/4 rate
uName.append(email_suffix[random.nextInt(Integer.MAX_VALUE) % email_suffix.length]);
}
break;
case 1: // tel
uName.append(tel_head[random.nextInt(Integer.MAX_VALUE) % tel_head.length])
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10);
break;
case 2: // qq
uName.append(random.nextInt(Integer.MAX_VALUE) % 9 + 1)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10)
.append(random.nextInt(Integer.MAX_VALUE) % 10);
int lenth = 0;
while (random.nextInt(Integer.MAX_VALUE) % 2 == 0) {
if (lenth > 6)
break;
uName.append(random.nextInt(Integer.MAX_VALUE) % 10);
lenth++;
}
break;
default:
break;
}
return uName.toString();
}
}

View File

@@ -0,0 +1,202 @@
package com.example.teambag.tools;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import androidx.appcompat.widget.AppCompatTextView;
import com.example.teambag.R;
public class SideBar extends AppCompatTextView {
private String[] letters = new String[]{"A", "B", "C", "D", "E", "F",
"G", "H", "I", "J", "K", "L",
"M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
"W", "X", "Y", "Z", "#"};
private Paint textPaint;
private Paint bigTextPaint;
private Paint scaleTextPaint;
private Canvas canvas;
private int itemH;
private int w;
private int h;
/**
* 普通情况下字体大小
*/
float singleTextH;
/**
* 缩放离原始的宽度
*/
private float scaleWidth;
/**
* 滑动的Y
*/
private float eventY = 0;
/**
* 缩放的倍数
*/
private int scaleSize = 1;
/**
* 缩放个数item即开口大小
*/
private int scaleItemCount = 6;
private ISideBarSelectCallBack callBack;
public SideBar(Context context) {
this(context, null);
}
public SideBar(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SideBar(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs);
}
private void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SideBar);
scaleSize = ta.getInteger(R.styleable.SideBar_scaleSize, 1);
scaleItemCount = ta.getInteger(R.styleable.SideBar_scaleItemCount, 6);
scaleWidth = ta.getDimensionPixelSize(R.styleable.SideBar_scaleWidth, dp(100));
ta.recycle();
}
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setColor(getCurrentTextColor());
textPaint.setTextSize(getTextSize());
textPaint.setTextAlign(Paint.Align.CENTER);
bigTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
bigTextPaint.setColor(getCurrentTextColor());
bigTextPaint.setTextSize(getTextSize() * (scaleSize + 3));
bigTextPaint.setTextAlign(Paint.Align.CENTER);
scaleTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
scaleTextPaint.setColor(getCurrentTextColor());
scaleTextPaint.setTextSize(getTextSize() * (scaleSize + 1));
scaleTextPaint.setTextAlign(Paint.Align.CENTER);
}
public void setDataResource(String[] data) {
letters = data;
invalidate();
}
public void setOnStrSelectCallBack(ISideBarSelectCallBack callBack) {
this.callBack = callBack;
}
/**
* 设置字体缩放比例 * * @param scale
*/
public void setScaleSize(int scale) {
scaleSize = scale;
invalidate();
}
/**
* 设置缩放字体的个数,即开口大小 * * @param scaleItemCount
*/
public void setScaleItemCount(int scaleItemCount) {
this.scaleItemCount = scaleItemCount;
invalidate();
}
private int dp(int px) {
final float scale = getContext().getResources().getDisplayMetrics().density;
return (int) (px * scale + 0.5f);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
eventY = event.getY();
invalidate();
return true;
} else {
eventY = 0;
invalidate();
break;
}
case MotionEvent.ACTION_CANCEL:
eventY = 0;
invalidate();
return true;
case MotionEvent.ACTION_UP:
if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
eventY = 0;
invalidate();
return true;
} else
break;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
DrawView(eventY);
}
private void DrawView(float y) {
int currentSelectIndex = -1;
if (y != 0) {
for (int i = 0; i < letters.length; i++) {
float currentItemY = itemH * i;
float nextItemY = itemH * (i + 1);
if (y >= currentItemY && y < nextItemY) {
currentSelectIndex = i;
if (callBack != null) {
callBack.onSelectStr(currentSelectIndex, letters[i]);
} //画大的字母
Paint.FontMetrics fontMetrics = bigTextPaint.getFontMetrics();
float bigTextSize = fontMetrics.descent - fontMetrics.ascent;
canvas.drawText(letters[i], w - getPaddingRight() - scaleWidth - bigTextSize,
singleTextH + itemH * i, bigTextPaint);
}
}
}
drawLetters(y, currentSelectIndex);
}
private void drawLetters(float y, int index) { //第一次进来没有缩放情况,默认画原图
if (index == -1) {
w = getMeasuredWidth();
h = getMeasuredHeight();
itemH = h / letters.length;
Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
singleTextH = fontMetrics.descent - fontMetrics.ascent;
for (int i = 0; i < letters.length; i++) {
canvas.drawText(letters[i], w - getPaddingRight(), singleTextH + itemH * i, textPaint);
} //触摸的时候画缩放图
} else { //遍历所有字母
for (int i = 0; i < letters.length; i++) { //要画的字母的起始Y坐标
float currentItemToDrawY = singleTextH + itemH * i;
float centerItemToDrawY;
if (index < i)
centerItemToDrawY = singleTextH + itemH * (index + scaleItemCount);
else
centerItemToDrawY = singleTextH + itemH * (index - scaleItemCount);
float delta = 1 - Math.abs((y - currentItemToDrawY) / (centerItemToDrawY - currentItemToDrawY));
float maxRightX = w - getPaddingRight(); //如果大于0表明在y坐标上方
scaleTextPaint.setTextSize(getTextSize() + getTextSize() * delta);
float drawX = maxRightX - scaleWidth * delta; //超出边界直接花在边界上
if (drawX > maxRightX)
canvas.drawText(letters[i], maxRightX, singleTextH + itemH * i, textPaint);
else
canvas.drawText(letters[i], drawX, singleTextH + itemH * i, scaleTextPaint);
}
}
}
public interface ISideBarSelectCallBack {
void onSelectStr(int index, String selectStr);
}
}

View File

@@ -0,0 +1,35 @@
package com.example.teambag.tools;
public class User implements Comparable<User> {
private String name; // 姓名
private String pinyin; // 姓名对应的拼音
private String firstLetter; // 拼音的首字母
public User() { }
public User(String name) {
this.name = name;
pinyin = Cn2Spell.getPinYin(name); // 根据姓名获取拼音
firstLetter = pinyin.substring(0, 1).toUpperCase(); // 获取拼音首字母并转成大写
if (!firstLetter.matches("[A-Z]")) { // 如果不在A-Z中则默认为“#”
firstLetter = "#"; }
}
public String getName() {
return name;
}
public String getPinyin() {
return pinyin;
}
public String getFirstLetter() {
return firstLetter;
}
@Override
public int compareTo(com.example.teambag.tools.User another) {
if (firstLetter.equals("#") && !another.getFirstLetter().equals("#")) {
return 1;
}
else if (!firstLetter.equals("#") && another.getFirstLetter().equals("#")){
return -1;
} else {
return pinyin.compareToIgnoreCase(another.getPinyin());
}
}
}

View File

@@ -0,0 +1,74 @@
package com.example.teambag.tools;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.widget.Button;
import android.widget.EditText;
public class WorksSizeCheckUtil {
static IEditTextChangeListener mChangeListener;
public static void setChangeListener(IEditTextChangeListener changeListener) {
mChangeListener = changeListener;
}
//检测输入框是否都输入了内容 从而改变按钮的是否可点击
public static class textChangeListener {
private Button button;
private EditText[] editTexts;
public textChangeListener(Button button) {
this.button = button;
}
public textChangeListener addAllEditText(EditText... editTexts) {
this.editTexts = editTexts;
initEditListener();
return this;
}
private void initEditListener() {
//调用了遍历editext的方法
for (EditText editText : editTexts) {
editText.addTextChangedListener(new textChange());
}
}
// edit输入的变化来改变按钮的是否点击
private class textChange implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
if (checkAllEdit()) {
//所有EditText有值了
mChangeListener.textChange(true);
button.setEnabled(true);
} else {
//所有EditText值为空
button.setEnabled(false);
mChangeListener.textChange(false);
}
}
@Override
public void afterTextChanged(Editable editable) {
}
}
//检查所有的edit是否输入了数据
private boolean checkAllEdit() {
for (EditText editText : editTexts) {
if (!TextUtils.isEmpty(editText.getText() + "")) {
continue;
} else {
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true"
android:fillBefore="true"
android:fromXScale="1.0"
android:toXScale="1.0"
android:fromYScale="0"
android:toYScale="1.0"
android:pivotX="50%"
android:pivotY="10%"
android:duration="200" />

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- 上下滑入式 -->
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:fillAfter="true"
android:fillBefore="true"
android:fromXScale="1.0"
android:toXScale="1.0"
android:fromYScale="1.0"
android:toYScale="0"
android:pivotX="50%"
android:pivotY="10%"
android:duration="200" />

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<solid android:color="@color/login_dvier" />
<size android:height="1dp" />
<size android:width="1dp"></size>
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" android:drawable="@drawable/btn_style_radius_pressed"/>
<item android:state_focused="false" android:drawable="@drawable/btn_style_radius"/>
</selector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#4CAF50"/>
<corners android:topLeftRadius="10dip"
android:topRightRadius="10dip"
android:bottomRightRadius="10dip"
android:bottomLeftRadius="10dip" />
</shape>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#387E3B"/>
<corners android:topLeftRadius="10dip"
android:topRightRadius="10dip"
android:bottomRightRadius="10dip"
android:bottomLeftRadius="10dip" />
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 814 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<size android:width="1dp" />
<size android:height="10dp"/>
<solid android:color="@color/loginButtonBackgroundFouse" />
</shape>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="55dp"
android:right="0dp">
<shape android:shape="rectangle" >
<solid android:color="#33000000" />
</shape>
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1012 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#C4424040"/>
<corners android:topLeftRadius="30dip"
android:topRightRadius="30dip"
android:bottomRightRadius="30dip"
android:bottomLeftRadius="30dip" />
</shape>

View File

@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/loginButtonBackgroundFouse" /><!-- 填充的颜色 -->
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners
android:bottomLeftRadius="6dp"
android:bottomRightRadius="6dp"
android:topLeftRadius="6dp"
android:topRightRadius="6dp" />
<!-- 边框粗细及颜色 -->
</shape>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/loginButtonBackgroundNotFouse" /><!-- 填充的颜色 -->
<!-- 设置按钮的四个角为弧形 -->
<!-- android:radius 弧形的半径 -->
<corners
android:bottomLeftRadius="6dp"
android:bottomRightRadius="6dp"
android:topLeftRadius="6dp"
android:topRightRadius="6dp" />
<!-- 边框粗细及颜色 -->
</shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item
android:left="80dp"
android:right="0dp">
<shape android:shape="rectangle" >
<solid android:color="#33000000" />
</shape>
</item>
</layer-list>

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 429 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 244 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 872 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 204 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,8 @@
<?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"
android:background="@drawable/welcome">
</LinearLayout>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="45dp"
android:id="@+id/title"
android:background="#E5E5E5 "
android:gravity="center_vertical" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="聊天"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="@color/black" />
<ImageButton
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/plus"
android:layout_centerVertical="true"
android:layout_marginRight="34dp"
android:background="#E5E5E5 "
android:onClick="search"
android:src="@drawable/search" />
<ImageButton
android:id="@+id/plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="29dp"
android:background="#E5E5E5 "
android:onClick="buttonTopRight"
android:src="@drawable/plus" />
</RelativeLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="50dp"
android:divider="@drawable/main_list_divider_line"
android:dividerHeight="1.5px" />
</LinearLayout>

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_marginTop="300dp"
android:padding="10dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/img1"
android:layout_width="20dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"/>
<LinearLayout
android:orientation="vertical"
android:layout_marginLeft="23dp"
android:layout_width="8dp"
android:layout_height="match_parent"
android:layout_weight="4">
<TextView
android:id="@+id/title"
android:textColor="#000000"
android:textSize="18dp"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"/>
<TextView
android:id="@+id/content"
android:textColor="#A8A8A8"
android:gravity="center_vertical"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1.5"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingRight="-50dp"
android:layout_weight="1"
android:gravity="right"
android:orientation="vertical">
<TextView
android:id="@+id/time"
android:textColor="#A8A8A8"
android:textSize="15dp"
android:layout_gravity="right"
android:layout_marginRight="1dp"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"/>
<ImageView
android:id="@+id/code"
android:background="#00FFFFFF"
android:layout_gravity="right"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="0.5"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,69 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#2FF1EEEE">
<Button
android:id="@+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FFFFFF"
android:textSize="30sp"
android:background="#00FFFFFF"
android:text="&#060;"/>
<TextView
android:id="@+id/tv_room"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="ChatRoom"
android:textColor="#CDFFFFFF"
android:textSize="23sp" />
</androidx.appcompat.widget.Toolbar>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/msg_recycler_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:layout_marginLeft="10dp">
<EditText
android:id="@+id/input_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="10dp"
android:hint="Type Something"
android:maxLines="2" />
<Button
android:id="@+id/send"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:text="Send"
android:textColor="#AAFFFFFF"/>
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="com.example.teambag.Main">
<RelativeLayout
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:background="#E5E5E5 "
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="通信录"
android:textColor="@color/black"
android:textSize="20sp" />
<ImageButton
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="30dp"
android:layout_toLeftOf="@id/plus"
android:background="#E5E5E5 "
android:onClick="search"
android:src="@drawable/search" />
<ImageButton
android:id="@+id/plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="29dp"
android:background="#E5E5E5 "
android:onClick="buttonTopRight"
android:src="@drawable/plus" />
</RelativeLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="50dp"
android:layout_marginBottom="50dp"
android:drawSelectorOnTop="true"
android:background="#E0E0E0"
android:divider="@drawable/main_list_divider_line"
android:dividerHeight="1.5px" />
<com.example.teambag.tools.SideBar
android:id="@+id/side_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_marginTop="100dp"
android:layout_marginBottom="100dp"
android:paddingRight="10dp"
android:textColor="@color/black"
android:textSize="9sp" />
</RelativeLayout>

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="vertical">
<TextView
android:id="@+id/catalog"
android:layout_width="match_parent"
android:layout_height="32dp"
android:background="#E0E0E0"
android:paddingLeft="10dp"
android:paddingTop="5dp"
android:textColor="#454545"
android:textSize="13sp" />
<LinearLayout
android:drawSelectorOnTop="true"
android:background="#FFFFFF"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<ImageView
android:id="@+id/img"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="10dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="10dp"
android:textColor="#336598"
android:textSize="16sp" />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#90909090" />
<TextView
android:id="@+id/contact_count"
android:layout_width="match_parent"
android:layout_height="25dp"
android:background="#FFFFFF"
android:paddingLeft="150dp"
android:paddingTop="5dp"
android:textColor="#454545"
android:textSize="13sp" />
</LinearLayout>

View File

@@ -0,0 +1,50 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E0E0E0"
android:orientation="vertical">
<RelativeLayout
android:id="@+id/title"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:background="#E5E5E5 "
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="发现"
android:textColor="@color/black"
android:textSize="20sp" />
<ImageButton
android:id="@+id/search"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_marginRight="34dp"
android:layout_toLeftOf="@id/plus"
android:background="#E5E5E5 "
android:onClick="search"
android:src="@drawable/search" />
<ImageButton
android:id="@+id/plus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginRight="29dp"
android:background="#E5E5E5 "
android:onClick="buttonTopRight"
android:src="@drawable/plus" />
</RelativeLayout>
<ListView
android:id="@+id/listView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/white"
android:divider="@drawable/find_list_divider_line"
android:dividerHeight="1.5px" />
</LinearLayout>

View File

@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="@+id/pic"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="10dp" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:padding="10dp"
android:textColor="#336598"
android:textSize="16sp" />
<View
android:id="@+id/fill"
android:layout_width="180dp"
android:layout_height="match_parent" />
<ImageView
android:id="@+id/pic1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/tab_settings_pressed" />
</LinearLayout>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="8dp"
android:background="#E0E0E0" />
<View
android:id="@+id/divider1"
android:layout_width="match_parent"
android:layout_height="63dp"
android:background="#E0E0E0" />
</LinearLayout>

View File

@@ -0,0 +1,35 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="180dp"
android:layout_height="180dp"
android:layout_centerInParent="true"
android:background="@drawable/loading_style">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:gravity="center"
android:orientation="vertical">
<ProgressBar
android:id="@+id/progressBar1"
style="?android:attr/progressBarStyleLarge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="正在登录"
android:textColor="#fff"
android:textSize="20sp" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/title"
android:orientation="vertical">
<!--返回按钮-->
<ImageView
android:id="@+id/close"
android:layout_width="17dp"
android:layout_height="17dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="45dp"
android:onClick="login_activity_back"
android:src="@drawable/backpay" />
<!--标题-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="45dp"
android:text="手机号登录"
android:textColor="@color/loginText"
android:textSize="25sp" />
<!--账号输入-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="手机号"
android:textColor="@color/loginText"
android:textSize="16sp" />
<EditText
android:id="@+id/log_phone"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="35dp"
android:background="@null"
android:hint="请填写手机号"
android:singleLine="true"
android:textColorHint="@color/textColorHint"
android:textCursorDrawable="@drawable/edit_cursor_color"
android:textSize="16sp" />
</LinearLayout>
<!--下划线-->
<ImageView
android:id="@+id/login_diver1"
android:layout_width="320dp"
android:layout_height="1dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="17dp"
android:background="@color/input_dvier" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="密码"
android:textColor="@color/loginText"
android:textSize="16sp" />
<EditText
android:id="@+id/log_passwd"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:password="true"
android:layout_marginLeft="55dp"
android:background="@null"
android:hint="请填写密码"
android:singleLine="true"
android:textColorHint="@color/textColorHint"
android:textCursorDrawable="@drawable/edit_cursor_color"
android:textSize="16sp" />
</LinearLayout>
<!--下划线-->
<ImageView
android:id="@+id/login_diver2"
android:layout_width="320dp"
android:layout_height="1dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="17dp"
android:background="@color/input_dvier" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/user_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="30dp"
android:text="用账号登录"
android:textColor="@color/massageLogin"
android:textSize="17dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:gravity="center_horizontal">
<!--登录按钮-->
<Button
android:id="@+id/log_button"
android:layout_width="321dp"
android:layout_height="48dp"
android:background="@drawable/login_button_shape"
android:text="登录"
android:textColor="@color/loginButtonText"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="150dp"
android:divider="@drawable/login_dvier"
android:gravity="center_horizontal"
android:showDividers="middle">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="找回密码"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="紧急冻结"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="安全中心"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,158 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/title"
android:orientation="vertical">
<!--返回按钮-->
<ImageView
android:id="@+id/close"
android:layout_width="17dp"
android:layout_height="17dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="45dp"
android:onClick="login_activity_back"
android:src="@drawable/backpay" />
<!--标题-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="45dp"
android:text="欢迎 / 账号登录"
android:textColor="@color/loginText"
android:textSize="25sp" />
<!--账号输入-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="账号"
android:textColor="@color/loginText"
android:textSize="16sp" />
<EditText
android:id="@+id/log_user_number"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="55dp"
android:background="@null"
android:hint="请填写账号"
android:singleLine="true"
android:textColorHint="@color/textColorHint"
android:textCursorDrawable="@drawable/edit_cursor_color"
android:textSize="16sp" />
</LinearLayout>
<!--下划线-->
<ImageView
android:id="@+id/login_diver1"
android:layout_width="320dp"
android:layout_height="1dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="17dp"
android:background="@color/input_dvier" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:text="密码"
android:textColor="@color/loginText"
android:textSize="16sp" />
<EditText
android:id="@+id/log_passwd"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_marginLeft="55dp"
android:password="true"
android:background="@null"
android:hint="请填写密码"
android:singleLine="true"
android:textColorHint="@color/textColorHint"
android:textCursorDrawable="@drawable/edit_cursor_color"
android:textSize="16sp" />
</LinearLayout>
<!--下划线-->
<ImageView
android:id="@+id/login_diver2"
android:layout_width="320dp"
android:layout_height="1dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="17dp"
android:background="@color/input_dvier" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/phone_log"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="30dp"
android:text="用手机号登录"
android:textColor="@color/massageLogin"
android:textSize="17dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="40dp"
android:gravity="center_horizontal">
<!--登录按钮-->
<Button
android:id="@+id/log_button"
android:layout_width="321dp"
android:layout_height="48dp"
android:background="@drawable/login_button_shape"
android:text="登录"
android:textColor="@color/loginButtonText"
android:textSize="16sp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="300dp"
android:divider="@drawable/login_dvier"
android:gravity="center_horizontal"
android:showDividers="middle">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="找回密码"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="紧急冻结"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingHorizontal="10dp"
android:text="微信安全中心"
android:textColor="@color/massageLogin"
android:textSize="14dp" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,137 @@
<?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">
<FrameLayout
android:id="@+id/fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/white">
</FrameLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="48dp"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_alignParentBottom="true"
android:background="#f7f7f7"
android:gravity="center"
android:orientation="horizontal">
<LinearLayout
android:id="@+id/chat_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_weight="1"
android:orientation="vertical"
android:padding="3dp">
<ImageView
android:id="@+id/chat_img"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/tab_chat_pressed" />
<TextView
android:id="@+id/chat_text"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:gravity="top"
android:text="聊天"
android:textColor="#82858b"
android:textSize="13dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/contacts_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_weight="1"
android:orientation="vertical"
android:padding="3dp">
<ImageView
android:id="@+id/contact_img"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/tab_address_normal" />
<TextView
android:id="@+id/contact_text"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:gravity="top"
android:text="通讯录"
android:textColor="#82858b"
android:textSize="13dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/find_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_weight="1"
android:orientation="vertical"
android:padding="3dp">
<ImageView
android:id="@+id/find_img"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/tab_find_frd_normal" />
<TextView
android:id="@+id/find_text"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:gravity="top"
android:text="发现"
android:textColor="#82858b"
android:textSize="13dp" />
</LinearLayout>
<LinearLayout
android:id="@+id/self_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_weight="1"
android:orientation="vertical"
android:padding="3dp">
<ImageView
android:id="@+id/self_img"
android:layout_width="wrap_content"
android:layout_height="24dp"
android:layout_gravity="center_horizontal"
android:src="@drawable/tab_settings_normal" />
<TextView
android:id="@+id/self_text"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:gravity="top"
android:text="我"
android:textColor="#82858b"
android:textSize="13dp" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>

Some files were not shown because too many files have changed in this diff Show More