fix(聊天模块): 修复聊天扩展菜单以及表情键盘的切换逻辑
修复聊天扩展菜单以及表情键盘的切换逻辑
This commit is contained in:
parent
543ddafe60
commit
89601df784
20
.idea/GitCommitMessageStorage.xml
Normal file
20
.idea/GitCommitMessageStorage.xml
Normal file
@ -0,0 +1,20 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitCommitMessageStorage">
|
||||
<option name="messageStorage">
|
||||
<MessageStorage>
|
||||
<option name="commitTemplate">
|
||||
<CommitTemplate>
|
||||
<option name="body" value="" />
|
||||
<option name="changes" value="" />
|
||||
<option name="closes" value="" />
|
||||
<option name="scope" value="" />
|
||||
<option name="skipCi" value="" />
|
||||
<option name="subject" value="" />
|
||||
<option name="type" value="feat" />
|
||||
</CommitTemplate>
|
||||
</option>
|
||||
</MessageStorage>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
15
.idea/git_toolbox_prj.xml
Normal file
15
.idea/git_toolbox_prj.xml
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
.idea/vcs.xml
Normal file
6
.idea/vcs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
@ -20,6 +20,9 @@
|
||||
android:theme="@style/Theme.KChatAndroid"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".view.activity.TestActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".view.activity.ProfileActivity"
|
||||
android:exported="false" />
|
||||
@ -53,7 +56,7 @@
|
||||
<activity
|
||||
android:name=".view.activity.ChatActivity"
|
||||
android:exported="false"
|
||||
android:windowSoftInputMode="adjustNothing" />
|
||||
android:windowSoftInputMode="adjustResize" />
|
||||
<activity
|
||||
android:name=".view.activity.MainActivity"
|
||||
android:exported="true" />
|
||||
|
@ -13,7 +13,7 @@ import okhttp3.Callback;
|
||||
*/
|
||||
public class NetworkInterface {
|
||||
|
||||
public static final String URL = "192.168.0.101:8080";
|
||||
public static final String URL = "192.168.31.18:8080";
|
||||
public static final String SERVER_URL = "http://" + URL;
|
||||
public static final String WEBSOCKET_SERVER_URL = "ws://" + URL;
|
||||
public static final String WEBSOCKET = "/websocket/single/";
|
||||
|
17
app/src/main/java/com/kaixed/kchat/utils/ConstantsUtil.java
Normal file
17
app/src/main/java/com/kaixed/kchat/utils/ConstantsUtil.java
Normal file
@ -0,0 +1,17 @@
|
||||
package com.kaixed.kchat.utils;
|
||||
|
||||
import static com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA;
|
||||
|
||||
import com.tencent.mmkv.MMKV;
|
||||
|
||||
/**
|
||||
* @Author: kaixed
|
||||
* @Date: 2024/8/18 13:18
|
||||
* @Description: TODO
|
||||
*/
|
||||
public class ConstantsUtil {
|
||||
public static int getKeyboardHeight() {
|
||||
return MMKV.mmkvWithID(MMKV_COMMON_DATA)
|
||||
.getInt("keyboardHeight", 200);
|
||||
}
|
||||
}
|
@ -1,12 +1,15 @@
|
||||
package com.kaixed.kchat.view.activity;
|
||||
|
||||
import static com.kaixed.kchat.utils.Constants.MMKV_COMMON_DATA;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.ServiceConnection;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@ -14,15 +17,21 @@ import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
import android.view.inputmethod.EditorInfo;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.TextView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.activity.OnBackPressedCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.lifecycle.Observer;
|
||||
import androidx.recyclerview.widget.GridLayoutManager;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
@ -34,12 +43,12 @@ import com.kaixed.kchat.database.entity.Messages;
|
||||
import com.kaixed.kchat.database.entity.Messages_;
|
||||
import com.kaixed.kchat.databinding.ActivityChatBinding;
|
||||
import com.kaixed.kchat.service.WebSocketService;
|
||||
import com.kaixed.kchat.utils.ConstantsUtil;
|
||||
import com.kaixed.kchat.utils.ImageSpanUtil;
|
||||
import com.kaixed.kchat.view.adapter.ChatAdapter;
|
||||
import com.kaixed.kchat.view.adapter.EmojiAdapter;
|
||||
import com.kaixed.kchat.view.adapter.FunctionPanelAdapter;
|
||||
import com.kaixed.kchat.view.i.OnItemClickListener;
|
||||
import com.tencent.mmkv.MMKV;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -58,22 +67,39 @@ import io.objectbox.query.QueryBuilder;
|
||||
public class ChatActivity extends AppCompatActivity implements OnItemClickListener {
|
||||
|
||||
private ChatAdapter chatAdapter;
|
||||
private final LinkedList<Messages> messagesList = new LinkedList<>();
|
||||
public static final String TAG = "ChatActivity";
|
||||
private Box<Messages> messagesBox;
|
||||
private String friendId;
|
||||
private static final long LIMIT = 50L;
|
||||
private boolean isLoading = false;
|
||||
private boolean isHasHistory = false;
|
||||
|
||||
private WebSocketService webSocketService;
|
||||
|
||||
private final LinkedList<Messages> messagesList = new LinkedList<>();
|
||||
|
||||
public static final String TAG = "ChatActivity";
|
||||
|
||||
private Box<Messages> messagesBox;
|
||||
|
||||
private String friendId;
|
||||
|
||||
private static final long LIMIT = 50L;
|
||||
|
||||
private boolean isLoading = false;
|
||||
|
||||
private boolean isHasHistory = false;
|
||||
|
||||
private boolean isBound = false;
|
||||
|
||||
private String username;
|
||||
|
||||
private long tempIndex;
|
||||
|
||||
private final Context mContext = this;
|
||||
|
||||
private List<String> strings;
|
||||
|
||||
private InputMethodManager imm;
|
||||
|
||||
private ActivityChatBinding binding;
|
||||
|
||||
private int softKeyboardHeight;
|
||||
|
||||
private String contactId;
|
||||
|
||||
private final ServiceConnection connection = new ServiceConnection() {
|
||||
@ -91,8 +117,7 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
}
|
||||
};
|
||||
|
||||
private boolean isKeyboardEject = false;
|
||||
|
||||
private boolean isKeyboardShown = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
@ -110,11 +135,133 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
handleIntent(getIntent());
|
||||
bindWebSocketService();
|
||||
|
||||
imm = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
|
||||
setPanelChange();
|
||||
|
||||
setBackPressListener();
|
||||
|
||||
getKeyBoardVisibility();
|
||||
|
||||
}
|
||||
|
||||
private void bindWebSocketService() {
|
||||
Intent serviceIntent = new Intent(this, WebSocketService.class);
|
||||
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
|
||||
private void getKeyBoardVisibility() {
|
||||
final View rootView = findViewById(android.R.id.content);
|
||||
|
||||
rootView.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
|
||||
Rect r = new Rect();
|
||||
rootView.getWindowVisibleDisplayFrame(r);
|
||||
int screenHeight = rootView.getRootView().getHeight();
|
||||
int keypadHeight = screenHeight - r.bottom;
|
||||
isKeyboardShown = keypadHeight > screenHeight * 0.15;
|
||||
});
|
||||
}
|
||||
|
||||
private void setBackPressListener() {
|
||||
getOnBackPressedDispatcher().addCallback(this, new OnBackPressedCallback(true) {
|
||||
@Override
|
||||
public void handleOnBackPressed() {
|
||||
if (binding.clBottomPanel.isShown()) {
|
||||
hidePanel(false);
|
||||
} else {
|
||||
setEnabled(false);
|
||||
onBackPressed();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private void setPanelChange() {
|
||||
binding.etInput.setOnTouchListener((v, event) -> {
|
||||
if (event.getAction() == MotionEvent.ACTION_UP && binding.clBottomPanel.isShown()) {
|
||||
lockContentViewHeight();
|
||||
hidePanel(true);
|
||||
unlockContentViewHeight();
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
binding.ivFunctionPanel.setOnClickListener(v -> {
|
||||
if (binding.clBottomPanel.isShown()) {
|
||||
if (binding.rvEmoji.isShown()) {
|
||||
handlePanelSwitch(false);
|
||||
} else {
|
||||
hideBottomPanel();
|
||||
}
|
||||
} else {
|
||||
switchPanel(false);
|
||||
}
|
||||
});
|
||||
|
||||
binding.ivEmoji.setOnClickListener(v -> {
|
||||
if (binding.clBottomPanel.isShown()) {
|
||||
if (binding.gvFunctionPanel.isShown()) {
|
||||
handlePanelSwitch(true);
|
||||
} else {
|
||||
hideBottomPanel();
|
||||
}
|
||||
} else {
|
||||
switchPanel(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void switchPanel(boolean isSwitchToEmoji) {
|
||||
if (isKeyboardShown) {
|
||||
lockContentViewHeight();
|
||||
handlePanelSwitch(isSwitchToEmoji);
|
||||
unlockContentViewHeight();
|
||||
} else {
|
||||
handlePanelSwitch(isSwitchToEmoji);
|
||||
}
|
||||
}
|
||||
|
||||
private void hideBottomPanel() {
|
||||
lockContentViewHeight();
|
||||
hidePanel(true);
|
||||
unlockContentViewHeight();
|
||||
}
|
||||
|
||||
private void lockContentViewHeight() {
|
||||
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.recycleChatList.getLayoutParams();
|
||||
layoutParams.height = binding.recycleChatList.getHeight();
|
||||
layoutParams.weight = 0f;
|
||||
binding.recycleChatList.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
private void unlockContentViewHeight() {
|
||||
binding.recycleChatList.postDelayed(() -> {
|
||||
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) binding.recycleChatList.getLayoutParams();
|
||||
layoutParams.weight = 1f;
|
||||
binding.recycleChatList.setLayoutParams(layoutParams);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
|
||||
private void setSoftKeyboardVisibility(boolean isShowKeyboard) {
|
||||
if (isShowKeyboard) {
|
||||
binding.etInput.requestFocus();
|
||||
imm.showSoftInput(binding.etInput, 0);
|
||||
} else {
|
||||
imm.hideSoftInputFromWindow(binding.etInput.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePanelSwitch(boolean isEmojiPanel) {
|
||||
setSoftKeyboardVisibility(false);
|
||||
binding.clBottomPanel.setVisibility(View.VISIBLE);
|
||||
|
||||
binding.rvEmoji.setVisibility(isEmojiPanel ? View.VISIBLE : View.INVISIBLE);
|
||||
binding.gvFunctionPanel.setVisibility(isEmojiPanel ? View.INVISIBLE : View.VISIBLE);
|
||||
}
|
||||
|
||||
private void hidePanel(boolean showSoftKeyboard) {
|
||||
if (binding.clBottomPanel.isShown()) {
|
||||
binding.clBottomPanel.setVisibility(View.GONE);
|
||||
if (showSoftKeyboard) {
|
||||
setSoftKeyboardVisibility(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleIntent(Intent intent) {
|
||||
@ -126,39 +273,18 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
}
|
||||
}
|
||||
|
||||
private void closeKeyboard() {
|
||||
View view = this.getCurrentFocus();
|
||||
if (view != null) {
|
||||
// 获取 InputMethodManager
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
// 隐藏软键盘
|
||||
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setListener() {
|
||||
|
||||
binding.ivEmoji.setOnClickListener(v -> {
|
||||
binding.clFunctionPanel.setVisibility(View.VISIBLE);
|
||||
if (isKeyboardEject) {
|
||||
closeKeyboard();
|
||||
}
|
||||
binding.gvFunctionPanel.setVisibility(View.GONE);
|
||||
binding.rvEmoji.setVisibility(View.VISIBLE);
|
||||
binding.tvContactName.setOnLongClickListener(v -> {
|
||||
Intent intent = new Intent(mContext, TestActivity.class);
|
||||
startActivity(intent);
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
binding.gvFunctionPanel.setSelector(new ColorDrawable(Color.TRANSPARENT));
|
||||
|
||||
binding.ivFunctionPanel.setOnClickListener(v -> {
|
||||
if (isKeyboardEject) {
|
||||
closeKeyboard();
|
||||
}
|
||||
binding.rvEmoji.setVisibility(View.GONE);
|
||||
binding.clFunctionPanel.setVisibility(View.VISIBLE);
|
||||
binding.gvFunctionPanel.setVisibility(View.VISIBLE);
|
||||
});
|
||||
|
||||
binding.tvSend.setOnClickListener(v -> sendMessage());
|
||||
binding.recycleChatList.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
@ -173,9 +299,7 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
}
|
||||
}
|
||||
});
|
||||
binding.ivBack.setOnClickListener(v -> {
|
||||
finish();
|
||||
});
|
||||
binding.ivBack.setOnClickListener(v -> finish());
|
||||
|
||||
binding.tvContactName.setOnClickListener(v -> {
|
||||
Intent intentContactsDetail = new Intent(mContext, ContactsDetailActivity.class);
|
||||
@ -187,47 +311,38 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
startActivity(intentChatDetail);
|
||||
});
|
||||
|
||||
binding.etInput.setOnFocusChangeListener((v, hasFocus) -> {
|
||||
isKeyboardEject = true;
|
||||
if (hasFocus) {
|
||||
binding.clFunctionPanel.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
});
|
||||
|
||||
binding.etInput.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
boolean isInputEmpty = binding.etInput.getText().toString().isEmpty();
|
||||
binding.ivFunctionPanel.setVisibility(!isInputEmpty ? View.GONE : View.VISIBLE);
|
||||
binding.tvSend.setVisibility(isInputEmpty ? View.GONE : View.VISIBLE);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
binding.etInput.setOnEditorActionListener(new TextView.OnEditorActionListener() {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE ||
|
||||
(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)) {
|
||||
sendMessage();
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
binding.etInput.addTextChangedListener(textWatcher);
|
||||
|
||||
binding.etInput.setOnEditorActionListener((v, actionId, event) -> {
|
||||
if (actionId == EditorInfo.IME_ACTION_DONE ||
|
||||
(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN)) {
|
||||
sendMessage();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
private final TextWatcher textWatcher = new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
boolean isInputEmpty = binding.etInput.getText().toString().isEmpty();
|
||||
binding.ivFunctionPanel.setVisibility(!isInputEmpty ? View.GONE : View.VISIBLE);
|
||||
binding.tvSend.setVisibility(isInputEmpty ? View.GONE : View.VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
private void setupFunctionPanel() {
|
||||
strings = new ArrayList<>();
|
||||
strings.add("[委屈]");
|
||||
@ -275,12 +390,9 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
}
|
||||
|
||||
private void setPanel() {
|
||||
int keyboard = MMKV.mmkvWithID(MMKV_COMMON_DATA)
|
||||
.getInt("keyboardHeight", 200);
|
||||
|
||||
ViewGroup.LayoutParams layoutParams = binding.clFunctionPanel.getLayoutParams();
|
||||
layoutParams.height = keyboard;
|
||||
binding.clFunctionPanel.setLayoutParams(layoutParams);
|
||||
ViewGroup.LayoutParams layoutParams = binding.clBottomPanel.getLayoutParams();
|
||||
layoutParams.height = softKeyboardHeight;
|
||||
binding.clBottomPanel.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
|
||||
@ -289,6 +401,7 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
username = UserManager.getInstance().getUsername();
|
||||
Intent intent = getIntent();
|
||||
friendId = intent.getStringExtra("friendId");
|
||||
softKeyboardHeight = ConstantsUtil.getKeyboardHeight();
|
||||
}
|
||||
|
||||
|
||||
@ -440,6 +553,11 @@ public class ChatActivity extends AppCompatActivity implements OnItemClickListen
|
||||
return query.find(offset, limit);
|
||||
}
|
||||
|
||||
private void bindWebSocketService() {
|
||||
Intent serviceIntent = new Intent(this, WebSocketService.class);
|
||||
bindService(serviceIntent, connection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
@ -86,7 +86,10 @@ public class LoginActivity extends AppCompatActivity {
|
||||
});
|
||||
});
|
||||
|
||||
getKeyboardHeight();
|
||||
}
|
||||
|
||||
private void getKeyboardHeight() {
|
||||
final FrameLayout rootLayout = findViewById(android.R.id.content);
|
||||
|
||||
rootLayout.getViewTreeObserver().addOnGlobalLayoutListener(() -> {
|
||||
@ -106,8 +109,6 @@ public class LoginActivity extends AppCompatActivity {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,11 +101,6 @@ public class MainActivity extends AppCompatActivity implements OnChatListItemCli
|
||||
isFlipped = !isFlipped;
|
||||
}
|
||||
|
||||
public int dpToPx(float dp) {
|
||||
float density = getResources().getDisplayMetrics().density;
|
||||
return Math.round(dp * density);
|
||||
}
|
||||
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
public void notifyData() {
|
||||
chatListAdapter.notifyDataSetChanged();
|
||||
@ -134,7 +129,6 @@ public class MainActivity extends AppCompatActivity implements OnChatListItemCli
|
||||
|
||||
ChatLists chatList = createChatList(talkerId, content, timestamp);
|
||||
|
||||
|
||||
int index = findChatListIndex(talkerId);
|
||||
if (index == -1) {
|
||||
chatLists.add(chatList);
|
||||
@ -142,7 +136,6 @@ public class MainActivity extends AppCompatActivity implements OnChatListItemCli
|
||||
updateChatList(chatLists.get(index), content, timestamp);
|
||||
}
|
||||
|
||||
|
||||
runOnUiThread(this::notifyData);
|
||||
isInDb(chatList);
|
||||
}
|
||||
@ -242,7 +235,7 @@ public class MainActivity extends AppCompatActivity implements OnChatListItemCli
|
||||
});
|
||||
}
|
||||
|
||||
ObjectAnimator createAnimator(int start, int end) {
|
||||
private ObjectAnimator createAnimator(int start, int end) {
|
||||
ObjectAnimator animator = ObjectAnimator.ofInt(binding.linearlayout, "top", start, end);
|
||||
long duration = 500;
|
||||
animator.setDuration(duration);
|
||||
|
141
app/src/main/java/com/kaixed/kchat/view/activity/TestActivity.kt
Normal file
141
app/src/main/java/com/kaixed/kchat/view/activity/TestActivity.kt
Normal file
@ -0,0 +1,141 @@
|
||||
package com.kaixed.kchat.view.activity
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.Bundle
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.inputmethod.InputMethodManager
|
||||
import android.widget.LinearLayout
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import com.kaixed.kchat.databinding.ActivityTestBinding
|
||||
import com.kaixed.kchat.utils.Constants
|
||||
import com.tencent.mmkv.MMKV
|
||||
|
||||
class TestActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var binding: ActivityTestBinding
|
||||
private lateinit var inputMethodManager: InputMethodManager
|
||||
|
||||
var keyboard: Int = MMKV.mmkvWithID(Constants.MMKV_COMMON_DATA)
|
||||
.getInt("keyboardHeight", 200)
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityTestBinding.inflate(layoutInflater)
|
||||
enableEdgeToEdge()
|
||||
setContentView(binding.root)
|
||||
|
||||
inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
|
||||
|
||||
// 处理 EditText 的触摸事件
|
||||
binding.etInput.setOnTouchListener { _, event ->
|
||||
if (event.action == MotionEvent.ACTION_UP && binding.clFunctionPanel.isShown) {
|
||||
lockContentViewHeight()
|
||||
hideEmojiPanel(true)
|
||||
unlockContentViewHeight()
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// 处理 RecyclerView 的触摸事件
|
||||
// binding.recycleChatList.setOnTouchListener { _, motionEvent ->
|
||||
// if (motionEvent.action == MotionEvent.ACTION_UP) {
|
||||
// if (binding.clFunctionPanel.isShown) {
|
||||
// hideEmojiPanel(false)
|
||||
// } else if (isSoftKeyboardShown()) {
|
||||
// hideSoftKeyboard()
|
||||
// }
|
||||
// }
|
||||
// false
|
||||
// }
|
||||
|
||||
// 表情面板切换按钮点击事件
|
||||
binding.ivEmoji.setOnClickListener {
|
||||
if (binding.clFunctionPanel.isShown) {
|
||||
lockContentViewHeight()
|
||||
hideEmojiPanel(true)
|
||||
unlockContentViewHeight()
|
||||
} else {
|
||||
if (isSoftKeyboardShown()) {
|
||||
lockContentViewHeight()
|
||||
showEmojiPanel()
|
||||
unlockContentViewHeight()
|
||||
} else {
|
||||
showEmojiPanel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun lockContentViewHeight() {
|
||||
val layoutParams = binding.recycleChatList.layoutParams as LinearLayout.LayoutParams
|
||||
layoutParams.height = binding.recycleChatList.height
|
||||
layoutParams.weight = 0f
|
||||
binding.recycleChatList.layoutParams = layoutParams
|
||||
}
|
||||
|
||||
private fun unlockContentViewHeight() {
|
||||
binding.recycleChatList.postDelayed({
|
||||
val layoutParams = binding.recycleChatList.layoutParams as LinearLayout.LayoutParams
|
||||
layoutParams.weight = 1f
|
||||
binding.recycleChatList.layoutParams = layoutParams
|
||||
}, 200)
|
||||
}
|
||||
|
||||
private fun getSoftKeyboardHeight(): Int {
|
||||
return keyboard
|
||||
}
|
||||
|
||||
private fun getSoftKeyboardHeightLocalValue(): Int {
|
||||
return keyboard
|
||||
}
|
||||
|
||||
private fun isSoftKeyboardShown(): Boolean {
|
||||
return getSoftKeyboardHeight() != 0
|
||||
}
|
||||
|
||||
private fun showSoftKeyboard(saveSoftKeyboardHeight: Boolean) {
|
||||
binding.etInput.requestFocus()
|
||||
inputMethodManager.showSoftInput(binding.etInput, 0)
|
||||
if (saveSoftKeyboardHeight) {
|
||||
binding.etInput.postDelayed({
|
||||
getSoftKeyboardHeight()
|
||||
}, 200)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideSoftKeyboard() {
|
||||
inputMethodManager.hideSoftInputFromWindow(binding.etInput.windowToken, 0)
|
||||
}
|
||||
|
||||
private fun showEmojiPanel() {
|
||||
var softKeyboardHeight = getSoftKeyboardHeight()
|
||||
if (softKeyboardHeight == 0) {
|
||||
softKeyboardHeight = getSoftKeyboardHeightLocalValue()
|
||||
} else {
|
||||
hideSoftKeyboard()
|
||||
}
|
||||
binding.clFunctionPanel.layoutParams.height = softKeyboardHeight
|
||||
binding.clFunctionPanel.visibility = View.VISIBLE
|
||||
}
|
||||
|
||||
private fun hideEmojiPanel(showSoftKeyboard: Boolean) {
|
||||
if (binding.clFunctionPanel.isShown) {
|
||||
binding.clFunctionPanel.visibility = View.GONE
|
||||
if (showSoftKeyboard) {
|
||||
showSoftKeyboard(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onBackPressed() {
|
||||
if (binding.clFunctionPanel.isShown) {
|
||||
hideEmojiPanel(false)
|
||||
} else {
|
||||
super.onBackPressed()
|
||||
}
|
||||
}
|
||||
}
|
@ -26,7 +26,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="7dp"
|
||||
android:text="friend"
|
||||
android:text="contact"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_contact_status"
|
||||
@ -139,7 +139,7 @@
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_function_panel"
|
||||
android:id="@+id/cl_bottom_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"
|
||||
android:minHeight="250dp"
|
||||
@ -161,6 +161,7 @@
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="250dp"
|
||||
android:numColumns="4"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
172
app/src/main/res/layout/activity_test.xml
Normal file
172
app/src/main/res/layout/activity_test.xml
Normal file
@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="10dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_back"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:src="@drawable/ic_left_arrow"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_contact_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="7dp"
|
||||
android:text="friend"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@id/tv_contact_status"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_back" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_contact_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="在线"
|
||||
android:textColor="@color/black"
|
||||
android:textSize="8sp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_back"
|
||||
app:layout_constraintStart_toStartOf="@id/tv_contact_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/tv_contact_name" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_more"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="22dp"
|
||||
android:layout_marginEnd="5dp"
|
||||
android:src="@drawable/ic_more"
|
||||
app:layout_constraintBottom_toBottomOf="@id/iv_back"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/iv_back" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycle_chat_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:background="#F1F1F1"
|
||||
android:overScrollMode="never" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#F7F7F7"
|
||||
android:paddingVertical="4dp">
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_input"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:background="@drawable/chat_bac_other"
|
||||
android:gravity="center_vertical"
|
||||
android:maxHeight="100dp"
|
||||
android:minHeight="36dp"
|
||||
android:paddingHorizontal="15dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/iv_emoji"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_emoji"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/chat_icon_emoji"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/ll_send"
|
||||
app:layout_constraintStart_toEndOf="@id/et_input" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/ll_send"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/iv_emoji"
|
||||
tools:ignore="UseCompoundDrawables">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/iv_function_panel"
|
||||
android:layout_width="28dp"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:layout_marginEnd="10dp"
|
||||
android:src="@drawable/chat_icon_add" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_send"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="28dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginVertical="4dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:background="@drawable/chat_bac_mine"
|
||||
android:gravity="center"
|
||||
android:paddingHorizontal="10dp"
|
||||
android:paddingVertical="6dp"
|
||||
android:text="发送"
|
||||
android:textColor="@color/white"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/cl_function_panel"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="250dp"
|
||||
android:minHeight="250dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_emoji"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:overScrollMode="never"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<GridView
|
||||
android:id="@+id/gv_function_panel"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="250dp"
|
||||
android:numColumns="4"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<domain-config cleartextTrafficPermitted="true">
|
||||
<domain includeSubdomains="true">192.168.0.101</domain>
|
||||
<domain includeSubdomains="true">192.168.31.18</domain>
|
||||
</domain-config>
|
||||
</network-security-config>
|
||||
|
Loading…
Reference in New Issue
Block a user