This commit is contained in:
ZhanGSKen 2025-02-26 15:09:29 +08:00
parent 2f0293103c
commit a15f6bad8f
7 changed files with 141 additions and 43 deletions

View File

@ -49,23 +49,19 @@ android {
}
dependencies {
// 使
api 'com.google.zxing:core:3.4.1'
api 'com.journeyapps:zxing-android-embedded:3.6.0'
implementation fileTree(dir: 'libs', include: ['*.jar'])
api 'io.github.medyo:android-about-page:2.0.0'
api 'com.github.getActivity:ToastUtils:10.5'
api 'com.jcraft:jsch:0.1.55'
api 'org.jsoup:jsoup:1.13.1'
api 'com.squareup.okhttp3:okhttp:4.4.1'
// https://mvnrepository.com/artifact/com.github.open-android/pinyin4j
implementation 'com.github.open-android:pinyin4j:2.5.0'
implementation 'io.github.medyo:android-about-page:2.0.0'
implementation 'com.github.getActivity:ToastUtils:10.5'
api 'androidx.appcompat:appcompat:1.1.0'
api 'androidx.viewpager:viewpager:1.0.0'
api 'androidx.fragment:fragment:1.1.0'
api 'com.google.android.material:material:1.4.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.viewpager:viewpager:1.0.0'
implementation 'androidx.fragment:fragment:1.1.0'
implementation 'com.google.android.material:material:1.4.0'
api 'cc.winboll.studio:libapputils:9.3.2'
api 'cc.winboll.studio:libappbase:1.5.6'
api fileTree(dir: 'libs', include: ['*.jar'])
implementation 'cc.winboll.studio:libapputils:9.3.2'
implementation 'cc.winboll.studio:libappbase:1.5.6'
}

View File

@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle
#Wed Feb 26 06:08:35 GMT 2025
#Wed Feb 26 06:42:40 GMT 2025
stageCount=4
libraryProject=
baseVersion=1.0
publishVersion=1.0.3
buildCount=5
buildCount=8
baseBetaVersion=1.0.4

View File

@ -5,9 +5,12 @@ package cc.winboll.studio.contacts.adapters;
* @Date 2025/02/26 13:35:44
* @Describe ContactAdapter
*/
import android.content.Intent;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
@ -19,6 +22,7 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
public static final String TAG = "ContactAdapter";
private List<ContactModel> contactList;
public ContactAdapter(List<ContactModel> contactList) {
@ -34,9 +38,18 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
@Override
public void onBindViewHolder(@NonNull ContactViewHolder holder, int position) {
ContactModel contact = contactList.get(position);
final ContactModel contact = contactList.get(position);
holder.contactName.setText(contact.getName());
holder.contactNumber.setText(contact.getNumber());
holder.dialButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String phoneNumber = contact.getNumber();
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:" + phoneNumber));
holder.itemView.getContext().startActivity(intent);
}
});
}
@Override
@ -47,11 +60,14 @@ public class ContactAdapter extends RecyclerView.Adapter<ContactAdapter.ContactV
public class ContactViewHolder extends RecyclerView.ViewHolder {
TextView contactName;
TextView contactNumber;
Button dialButton;
public ContactViewHolder(@NonNull View itemView) {
super(itemView);
contactName = itemView.findViewById(R.id.contact_name);
contactNumber = itemView.findViewById(R.id.contact_number);
dialButton = itemView.findViewById(R.id.dial_button);
}
}
}

View File

@ -5,16 +5,48 @@ package cc.winboll.studio.contacts.beans;
* @Date 2025/02/26 13:37:00
* @Describe ContactModel
*/
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
public class ContactModel {
public static final String TAG = "ContactModel";
private String name;
private String number;
private String pinyin;
public ContactModel(String name, String number) {
this.name = name;
this.number = number;
this.pinyin = convertToPinyin(name);
}
private String convertToPinyin(String chinese) {
HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
StringBuilder pinyin = new StringBuilder();
for (int i = 0; i < chinese.length(); i++) {
char ch = chinese.charAt(i);
if (Character.toString(ch).matches("[\\u4e00 - \\u9fa5]")) {
try {
String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(ch, format);
if (pinyinArray != null) {
pinyin.append(pinyinArray[0]);
}
} catch (BadHanyuPinyinOutputFormatCombination e) {
e.printStackTrace();
}
} else {
pinyin.append(ch);
}
}
return pinyin.toString();
}
public String getName() {
@ -24,5 +56,9 @@ public class ContactModel {
public String getNumber() {
return number;
}
public String getPinyin() {
return pinyin;
}
}

View File

@ -10,9 +10,12 @@ import android.content.pm.PackageManager;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
@ -36,7 +39,8 @@ public class ContactsFragment extends Fragment {
private RecyclerView recyclerView;
private ContactAdapter contactAdapter;
private List<ContactModel> contactList = new ArrayList<>();
private List<ContactModel> originalContactList = new ArrayList<>();
private EditText searchEditText;
public static ContactsFragment newInstance(int page) {
Bundle args = new Bundle();
@ -54,10 +58,6 @@ public class ContactsFragment extends Fragment {
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
@ -72,6 +72,22 @@ public class ContactsFragment extends Fragment {
contactAdapter = new ContactAdapter(contactList);
recyclerView.setAdapter(contactAdapter);
searchEditText = view.findViewById(R.id.search_edit_text);
searchEditText.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) {
filterContacts(s.toString());
}
@Override
public void afterTextChanged(Editable s) {
}
});
if (ActivityCompat.checkSelfPermission(requireContext(), Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(requireActivity(), new String[]{Manifest.permission.READ_CONTACTS}, REQUEST_READ_CONTACTS);
} else {
@ -91,6 +107,7 @@ public class ContactsFragment extends Fragment {
private void readContacts() {
contactList.clear();
originalContactList.clear();
Cursor cursor = requireContext().getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null,
@ -102,10 +119,29 @@ public class ContactsFragment extends Fragment {
while (cursor.moveToNext()) {
String name = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME));
String number = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactList.add(new ContactModel(name, number));
ContactModel contact = new ContactModel(name, number);
contactList.add(contact);
originalContactList.add(contact);
}
cursor.close();
contactAdapter.notifyDataSetChanged();
}
}
private void filterContacts(String query) {
contactList.clear();
if (query.isEmpty()) {
contactList.addAll(originalContactList);
} else {
for (ContactModel contact : originalContactList) {
if (contact.getName().toLowerCase().contains(query.toLowerCase()) ||
contact.getPinyin().toLowerCase().contains(query.toLowerCase()) ||
contact.getNumber().toLowerCase().contains(query.toLowerCase())) {
contactList.add(contact);
}
}
}
contactAdapter.notifyDataSetChanged();
}
}

View File

@ -6,6 +6,13 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="@+id/search_edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Search contacts"
android:padding="16dp"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/contacts_recycler_view"
android:layout_width="match_parent"

View File

@ -1,24 +1,31 @@
<?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"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:textStyle="bold"/>
<TextView
android:id="@+id/contact_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp"/>
<TextView
android:id="@+id/contact_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginTop="4dp"/>
<Button
android:id="@+id/dial_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Dial"
android:layout_marginTop="8dp"/>
</LinearLayout>