Skip to content

Commit fab38e6

Browse files
committed
first commit
0 parents  commit fab38e6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+2109
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package top.grapedge.grapeschat;
2+
3+
import android.content.Context;
4+
import android.support.test.InstrumentationRegistry;
5+
import android.support.test.runner.AndroidJUnit4;
6+
7+
import org.junit.Test;
8+
import org.junit.runner.RunWith;
9+
10+
import static org.junit.Assert.*;
11+
12+
/**
13+
* Instrumented test, which will execute on an Android device.
14+
*
15+
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
16+
*/
17+
@RunWith(AndroidJUnit4.class)
18+
public class ExampleInstrumentedTest {
19+
@Test
20+
public void useAppContext() {
21+
// Context of the app under test.
22+
Context appContext = InstrumentationRegistry.getTargetContext();
23+
24+
assertEquals("top.grapedge.qqlogin", appContext.getPackageName());
25+
}
26+
}

main/AndroidManifest.xml

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
package="top.grapedge.qqlogin">
5+
6+
<uses-permission android:name="android.permission.INTERNET" />
7+
8+
<application
9+
android:allowBackup="true"
10+
android:icon="@mipmap/ic_launcher"
11+
android:label="@string/app_name"
12+
android:roundIcon="@mipmap/ic_launcher_round"
13+
android:supportsRtl="true"
14+
android:theme="@style/AppTheme"
15+
android:usesCleartextTraffic="true"
16+
tools:ignore="GoogleAppIndexingWarning">
17+
<activity android:name="top.grapedge.grapeschat.SplashActivity">
18+
<intent-filter>
19+
<action android:name="android.intent.action.MAIN" />
20+
21+
<category android:name="android.intent.category.LAUNCHER" />
22+
</intent-filter>
23+
</activity>
24+
<activity android:name="top.grapedge.grapeschat.LoginActivity">
25+
<intent-filter>
26+
<action android:name="top.grapedge.qqlogin.intent.action.LOGIN" />
27+
28+
<category android:name="android.intent.category.DEFAULT" />
29+
</intent-filter>
30+
</activity>
31+
<activity android:name="top.grapedge.grapeschat.MainActivity" />
32+
<activity
33+
android:name="top.grapedge.grapeschat.RegisterActivity"
34+
android:label="注册" />
35+
36+
<activity android:name="top.grapedge.grapeschat.AddFriendActivity"/>
37+
</application>
38+
39+
</manifest>
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package top.grapedge.grapeschat;
2+
3+
import android.content.Context;
4+
import android.os.Bundle;
5+
import android.support.annotation.NonNull;
6+
import android.support.v7.widget.LinearLayoutManager;
7+
import android.support.v7.widget.RecyclerView;
8+
import android.view.KeyEvent;
9+
import android.view.LayoutInflater;
10+
import android.view.View;
11+
import android.view.ViewGroup;
12+
import android.view.inputmethod.EditorInfo;
13+
import android.view.inputmethod.InputMethodManager;
14+
import android.widget.Button;
15+
import android.widget.EditText;
16+
import android.widget.TextView;
17+
import android.widget.Toast;
18+
19+
import com.google.gson.Gson;
20+
import com.google.gson.reflect.TypeToken;
21+
22+
import java.util.ArrayList;
23+
import java.util.List;
24+
25+
import top.grapedge.qqlogin.R;
26+
27+
public class AddFriendActivity extends BaseActivity implements TextView.OnEditorActionListener {
28+
29+
// 用户输入框
30+
private EditText userNameEdit;
31+
// 用户列表
32+
private List<UserJsonData> users = new ArrayList<>();
33+
// 显示列表
34+
private RecyclerView recyclerView;
35+
// 适配器
36+
private FriendRecyclerViewAdapter adapter;
37+
// 登录用户的 json 信息
38+
private UserJsonData loginUser;
39+
// 返回按钮
40+
private TextView backText;
41+
42+
@Override
43+
protected void onCreate(Bundle savedInstanceState) {
44+
super.onCreate(savedInstanceState);
45+
setContentView(R.layout.activity_add_friend);
46+
// 初始化控件
47+
initView();
48+
}
49+
50+
private void initView() {
51+
// 获取当前登录用户
52+
loginUser = parseUserFromString(getIntent().getStringExtra("user_data"));
53+
// 初始化控件
54+
userNameEdit = findViewById(R.id.add_friend_edit);
55+
userNameEdit.requestFocus();
56+
recyclerView = findViewById(R.id.add_friend_list);
57+
backText = findViewById(R.id.add_friend_back);
58+
backText.setOnClickListener(new View.OnClickListener() {
59+
@Override
60+
public void onClick(View v) {
61+
finish();
62+
}
63+
});
64+
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
65+
recyclerView.setLayoutManager(linearLayoutManager);
66+
// 适配器
67+
adapter = new FriendRecyclerViewAdapter();
68+
recyclerView.setAdapter(adapter);
69+
userNameEdit.setOnEditorActionListener(this);
70+
}
71+
72+
73+
// 更新搜索列表
74+
private void updateUserList(final String key) {
75+
new Thread(new Runnable() {
76+
@Override
77+
public void run() {
78+
final String json = new Gson().fromJson(HttpUtil.Get(HttpUtil.QUERY_URL + "?key=" + key), JsonData.class).getObj();
79+
runOnUiThread(new Runnable() {
80+
@Override
81+
public void run() {
82+
// 通过解析 json 获得用户列表
83+
users = new Gson().fromJson(json, new TypeToken<List<UserJsonData>>(){}.getType());
84+
adapter.updateList();
85+
Toast.makeText(AddFriendActivity.this, "一共找到" + users.size() + "位用户", Toast.LENGTH_SHORT).show();
86+
}
87+
});
88+
}
89+
}).start();
90+
}
91+
92+
// 设置输入框是否可以进行输入
93+
private void setEditTextActive(final boolean active) {
94+
runOnUiThread(new Runnable() {
95+
@Override
96+
public void run() {
97+
userNameEdit.setFocusable(active);
98+
userNameEdit.setFocusableInTouchMode(active);
99+
}
100+
});
101+
}
102+
103+
// 进行搜索
104+
private void search(final EditText editText) {
105+
// 隐藏软键盘
106+
((InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE)).toggleSoftInput(0, InputMethodManager.HIDE_NOT_ALWAYS);
107+
if (editText.getText().toString().length() == 0) {
108+
Toast.makeText(this, "请输入用户名!", Toast.LENGTH_SHORT).show();
109+
return;
110+
}
111+
new Thread(new Runnable() {
112+
@Override
113+
public void run() {
114+
// 禁用输入框
115+
setEditTextActive(false);
116+
// 得到输入数据
117+
String key = editText.getText().toString();
118+
// 更新列表数据
119+
updateUserList(key);
120+
// 启用输入框
121+
setEditTextActive(true);
122+
}
123+
}).start();
124+
}
125+
126+
// 添加好友
127+
private void addFriend(final UserJsonData addUser) {
128+
new Thread(new Runnable() {
129+
@Override
130+
public void run() {
131+
// 获取返回数据,传入登录用户和添加用户
132+
String data = HttpUtil.Get(HttpUtil.ADD_FRIEND_URL + "?userId=" + loginUser.getId() + "&friendId=" + addUser.getId());
133+
final JsonData jsonData = new Gson().fromJson(data, JsonData.class);
134+
135+
// 更新 UI
136+
runOnUiThread(new Runnable() {
137+
@Override
138+
public void run() {
139+
Toast.makeText(AddFriendActivity.this, addUser.getNickname() + " " + jsonData.getObj(), Toast.LENGTH_SHORT).show();
140+
}
141+
});
142+
}
143+
}).start();
144+
}
145+
146+
// 输入动作发生时
147+
@Override
148+
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
149+
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
150+
// 如果按了软键盘上的搜索键
151+
search(userNameEdit);
152+
}
153+
return false;
154+
}
155+
156+
class FriendRecyclerViewAdapter extends RecyclerView.Adapter {
157+
158+
@NonNull
159+
@Override
160+
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
161+
// 创建子项
162+
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.add_friend_item, viewGroup, false);
163+
UserHolder holder = new UserHolder(view);
164+
return holder;
165+
}
166+
167+
@Override
168+
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
169+
// 得到对应项的数据
170+
UserJsonData data = users.get(i);
171+
UserHolder userHolder = (UserHolder)viewHolder;
172+
// 设置昵称
173+
userHolder.userName.setText(data.getNickname());
174+
// 设置对应的按钮的 Tag
175+
userHolder.addButton.setTag(users.get(i));
176+
}
177+
178+
// 更新列表
179+
public void updateList() {
180+
notifyDataSetChanged();
181+
}
182+
183+
// 清空用户列表,不过似乎我没用到
184+
public void clear() {
185+
users.clear();
186+
updateList();
187+
}
188+
189+
// 得到项目数量
190+
@Override
191+
public int getItemCount() {
192+
return users.size();
193+
}
194+
195+
// Holder
196+
class UserHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
197+
TextView userName;
198+
Button addButton;
199+
200+
public UserHolder(@NonNull View itemView) {
201+
super(itemView);
202+
userName = itemView.findViewById(R.id.friend_name);
203+
addButton = itemView.findViewById(R.id.add_friend);
204+
addButton.setOnClickListener(this);
205+
}
206+
207+
@Override
208+
public void onClick(View v) {
209+
// 获得对应的用户数据
210+
UserJsonData userJsonData = (UserJsonData) addButton.getTag();
211+
// 添加好友
212+
addFriend(userJsonData);
213+
}
214+
}
215+
}
216+
217+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package top.grapedge.grapeschat;
2+
3+
import android.graphics.Rect;
4+
import android.os.Bundle;
5+
import android.support.annotation.Nullable;
6+
import android.support.v7.app.AppCompatActivity;
7+
import android.view.MotionEvent;
8+
import android.view.View;
9+
import android.view.ViewTreeObserver;
10+
import android.view.inputmethod.InputMethodManager;
11+
import android.widget.EditText;
12+
13+
import com.google.gson.Gson;
14+
15+
public class BaseActivity extends AppCompatActivity {
16+
17+
// 使用这个键值表示创建
18+
public final static String EXTRA_USER_DATA = "user_data";
19+
20+
protected DataManager dataManager;
21+
22+
// protected UserJsonData loginUser;
23+
24+
@Override
25+
protected void onCreate(@Nullable Bundle savedInstanceState) {
26+
super.onCreate(savedInstanceState);
27+
dataManager = new DataManager(this);
28+
}
29+
30+
// 实现点击空白处隐藏软键盘
31+
protected void touchBlank(View v, MotionEvent ev) {
32+
if (v != null && v instanceof EditText) {
33+
Rect rect = new Rect();
34+
v.getHitRect(rect);
35+
// 判断点击点是否在编辑框区域外
36+
if (!rect.contains((int)ev.getX(), (int)ev.getY())) {
37+
// 隐藏软键盘
38+
((InputMethodManager)getSystemService(INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(v.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
39+
}
40+
}
41+
}
42+
43+
public UserJsonData parseUserFromString(String obj) {
44+
if (obj == null) return new UserJsonData();
45+
return new Gson().fromJson(obj, UserJsonData.class);
46+
}
47+
48+
// 分发点击事件
49+
@Override
50+
public boolean dispatchTouchEvent(MotionEvent ev) {
51+
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
52+
touchBlank (getCurrentFocus(), ev);
53+
}
54+
return super.dispatchTouchEvent(ev);
55+
}
56+
57+
// 防止遮挡控件
58+
private int scrollTo = 0;
59+
protected void scrollToView(final View scrollView, final View targetView) {
60+
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
61+
@Override
62+
public void onGlobalLayout() {
63+
Rect rect = new Rect();
64+
// 获得可见区域的高度
65+
scrollView.getWindowVisibleDisplayFrame(rect);
66+
// 父布局的高度减去可见区域的底部高度就是不可见区域的高度
67+
int invisibleHeight = scrollView.getRootView().getHeight() - rect.bottom;
68+
// 如果不可见高度大于150说明键盘已经打开
69+
if (invisibleHeight > 150) {
70+
// 下面的部分和 ScrollView 版是相似原理
71+
int[] location = new int[2];
72+
targetView.getLocationInWindow(location);
73+
74+
scrollTo += location[1] + targetView.getHeight() - rect.bottom;
75+
76+
} else scrollTo = 0;
77+
78+
scrollView.scrollTo(0, scrollTo);
79+
}
80+
});
81+
}
82+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package top.grapedge.grapeschat;
2+
3+
import android.os.Bundle;
4+
import android.support.annotation.NonNull;
5+
import android.support.annotation.Nullable;
6+
import android.support.v4.app.Fragment;
7+
import android.view.LayoutInflater;
8+
import android.view.View;
9+
import android.view.ViewGroup;
10+
11+
import com.google.gson.Gson;
12+
13+
public class BaseFragment extends Fragment {
14+
public static final String EXTRA_USER_DATA = BaseActivity.EXTRA_USER_DATA;
15+
16+
// 当前登录用户
17+
protected UserJsonData loginUser;
18+
// 登录用户的json信息
19+
protected String loginUserJson;
20+
21+
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
22+
loginUserJson = getActivity().getIntent().getStringExtra(EXTRA_USER_DATA);
23+
loginUser = new Gson().fromJson(loginUserJson, UserJsonData.class);
24+
return initView(inflater, container, savedInstanceState);
25+
}
26+
27+
public View initView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
28+
return super.onCreateView(inflater, container, savedInstanceState);
29+
}
30+
}

0 commit comments

Comments
 (0)