├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── profile
│ │ │ │ ├── p1.jpg
│ │ │ │ ├── p2.jpg
│ │ │ │ ├── p3.jpg
│ │ │ │ ├── p4.jpg
│ │ │ │ ├── p5.jpg
│ │ │ │ ├── p6.jpg
│ │ │ │ ├── p7.jpg
│ │ │ │ ├── p8.jpg
│ │ │ │ ├── p9.jpg
│ │ │ │ ├── p10.jpg
│ │ │ │ ├── p11.jpg
│ │ │ │ ├── p12.jpg
│ │ │ │ ├── p13.jpg
│ │ │ │ ├── p14.jpg
│ │ │ │ └── p15.jpg
│ │ │ ├── drawable
│ │ │ │ ├── app.png
│ │ │ │ ├── p1.jpg
│ │ │ │ ├── p10.jpg
│ │ │ │ ├── p11.jpg
│ │ │ │ ├── p12.jpg
│ │ │ │ ├── p13.jpg
│ │ │ │ ├── p14.jpg
│ │ │ │ ├── p15.jpg
│ │ │ │ ├── p16.jpg
│ │ │ │ ├── p17.jpg
│ │ │ │ ├── p18.jpg
│ │ │ │ ├── p2.jpg
│ │ │ │ ├── p3.jpg
│ │ │ │ ├── p4.jpg
│ │ │ │ ├── p5.jpg
│ │ │ │ ├── p6.jpg
│ │ │ │ ├── p7.jpg
│ │ │ │ ├── p8.jpg
│ │ │ │ ├── p9.jpg
│ │ │ │ ├── sex.png
│ │ │ │ ├── addbtn.png
│ │ │ │ ├── album.png
│ │ │ │ ├── back.png
│ │ │ │ ├── camera.png
│ │ │ │ ├── cards.png
│ │ │ │ ├── help.png
│ │ │ │ ├── mine.png
│ │ │ │ ├── news.png
│ │ │ │ ├── pyq1.jpg
│ │ │ │ ├── pyq2_1.jpg
│ │ │ │ ├── pyq2_2.jpg
│ │ │ │ ├── pyq3_1.PNG
│ │ │ │ ├── pyq3_2.PNG
│ │ │ │ ├── pyq4_1.jpg
│ │ │ │ ├── pyq4_2.jpg
│ │ │ │ ├── pyq4_3.jpg
│ │ │ │ ├── pyq5_1.jpg
│ │ │ │ ├── pyq5_2.jpg
│ │ │ │ ├── pyq6.jpg
│ │ │ │ ├── pyq7.jpg
│ │ │ │ ├── pyq8_1.jpg
│ │ │ │ ├── pyq8_2.jpg
│ │ │ │ ├── star.png
│ │ │ │ ├── star1.png
│ │ │ │ ├── star2.png
│ │ │ │ ├── address.png
│ │ │ │ ├── friends.png
│ │ │ │ ├── message.png
│ │ │ │ ├── notfound.png
│ │ │ │ ├── addfriend.png
│ │ │ │ ├── username_pic.png
│ │ │ │ ├── login_background.jpg
│ │ │ │ ├── news_background.jpg
│ │ │ │ ├── inputbackground.xml
│ │ │ │ ├── ic_home_black_24dp.xml
│ │ │ │ ├── dialog_left.xml
│ │ │ │ ├── dialog_right.xml
│ │ │ │ ├── ic_dashboard_black_24dp.xml
│ │ │ │ ├── buttonbackground.xml
│ │ │ │ ├── rounded_edittext.xml
│ │ │ │ ├── ic_notifications_black_24dp.xml
│ │ │ │ └── ic_launcher_background.xml
│ │ │ ├── mipmap-hdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── ic_launcher.png
│ │ │ │ └── ic_launcher_round.png
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── attrs.xml
│ │ │ │ ├── strings.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── themes.xml
│ │ │ ├── mipmap-anydpi-v26
│ │ │ │ ├── ic_launcher.xml
│ │ │ │ └── ic_launcher_round.xml
│ │ │ ├── layout
│ │ │ │ ├── fragment_index.xml
│ │ │ │ ├── fragment_friends.xml
│ │ │ │ ├── item.xml
│ │ │ │ ├── make_moment_page.xml
│ │ │ │ ├── empty_content_page.xml
│ │ │ │ ├── message_item.xml
│ │ │ │ ├── activity_index.xml
│ │ │ │ ├── msg_item.xml
│ │ │ │ ├── friends_item.xml
│ │ │ │ ├── login.xml
│ │ │ │ ├── activity_main.xml
│ │ │ │ ├── regist.xml
│ │ │ │ ├── fragment_news.xml
│ │ │ │ ├── news_item.xml
│ │ │ │ ├── chat_page.xml
│ │ │ │ ├── add_friend_page.xml
│ │ │ │ └── fragment_mine.xml
│ │ │ ├── menu
│ │ │ │ ├── popumenu.xml
│ │ │ │ └── bottom_nav_menu.xml
│ │ │ ├── values-night
│ │ │ │ └── themes.xml
│ │ │ ├── navigation
│ │ │ │ └── mobile_navigation.xml
│ │ │ └── drawable-v24
│ │ │ │ └── ic_launcher_foreground.xml
│ │ ├── assets
│ │ │ └── litePal.xml
│ │ ├── java
│ │ │ └── com
│ │ │ │ └── example
│ │ │ │ └── wechating
│ │ │ │ ├── EmptyContentPage.java
│ │ │ │ ├── ui
│ │ │ │ ├── index
│ │ │ │ │ ├── IndexViewModel.java
│ │ │ │ │ └── IndexFragment.java
│ │ │ │ ├── mine
│ │ │ │ │ ├── MineViewModel.java
│ │ │ │ │ └── MineFragment.java
│ │ │ │ ├── news
│ │ │ │ │ ├── NewsViewModel.java
│ │ │ │ │ └── NewsFragment.java
│ │ │ │ └── friends
│ │ │ │ │ ├── FriendsViewModel.java
│ │ │ │ │ └── FriendsFragment.java
│ │ │ │ ├── domain
│ │ │ │ ├── Msg.java
│ │ │ │ ├── User.java
│ │ │ │ └── Friends.java
│ │ │ │ ├── MakeMomentPage.java
│ │ │ │ ├── utils
│ │ │ │ ├── UserUtil.java
│ │ │ │ ├── FriendsUtil.java
│ │ │ │ └── JDBCUtils.java
│ │ │ │ ├── MainActivity.java
│ │ │ │ ├── LoginActivity.java
│ │ │ │ ├── AddFriendPage.java
│ │ │ │ ├── Index.java
│ │ │ │ ├── RegistActivity.java
│ │ │ │ ├── component
│ │ │ │ ├── SortAdapter.java
│ │ │ │ ├── MsgAdapter.java
│ │ │ │ ├── Cn2Spell.java
│ │ │ │ ├── NewsAdapter.java
│ │ │ │ ├── MessageSlideLayout.java
│ │ │ │ ├── FriendsSlideLayout.java
│ │ │ │ └── SideBar.java
│ │ │ │ └── ChatPage.java
│ │ └── AndroidManifest.xml
│ ├── androidTest
│ │ └── java
│ │ │ └── com
│ │ │ └── example
│ │ │ └── wechating
│ │ │ └── ExampleInstrumentedTest.java
│ └── test
│ │ └── java
│ │ └── com
│ │ └── example
│ │ └── wechating
│ │ └── ExampleUnitTest.java
├── proguard-rules.pro
└── build.gradle
├── settings.gradle
├── .idea
├── .gitignore
├── compiler.xml
├── misc.xml
├── gradle.xml
└── jarRepositories.xml
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── README.md
├── .gitignore
├── gradle.properties
├── gradlew.bat
└── gradlew
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 | rootProject.name = "WeChating"
--------------------------------------------------------------------------------
/.idea/.gitignore:
--------------------------------------------------------------------------------
1 | # Default ignored files
2 | /shelf/
3 | /workspace.xml
4 |
--------------------------------------------------------------------------------
/app/src/main/res/profile/p1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p3.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p4.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p5.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p6.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p7.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p8.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p9.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/app.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/app.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p10.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p11.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p12.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p13.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p14.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p15.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p16.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p17.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p18.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p3.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p4.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p5.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p6.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p7.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p8.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/p9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/p9.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/sex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/sex.png
--------------------------------------------------------------------------------
/app/src/main/res/profile/p10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p10.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p11.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p12.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p13.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p14.jpg
--------------------------------------------------------------------------------
/app/src/main/res/profile/p15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/profile/p15.jpg
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/app/src/main/res/drawable/addbtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/addbtn.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/album.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/album.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/back.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/back.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/camera.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/camera.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/cards.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/cards.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/help.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/help.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/mine.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/mine.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/news.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/news.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq2_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq2_1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq2_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq2_2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq3_1.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq3_1.PNG
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq3_2.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq3_2.PNG
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq4_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq4_1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq4_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq4_2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq4_3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq4_3.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq5_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq5_1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq5_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq5_2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq6.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq7.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq8_1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq8_1.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/pyq8_2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/pyq8_2.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/star.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/star1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/star1.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/star2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/star2.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # WeChating
2 | Android期末大作业,仿微信小应用
3 | 主要功能展示可到此博客查看:https://blog.csdn.net/qq_43553929/article/details/111411856
4 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/address.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/address.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/friends.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/friends.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/message.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/message.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/notfound.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/notfound.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/addfriend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/addfriend.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/username_pic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/username_pic.png
--------------------------------------------------------------------------------
/app/src/main/res/drawable/login_background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/login_background.jpg
--------------------------------------------------------------------------------
/app/src/main/res/drawable/news_background.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/drawable/news_background.jpg
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/txllg/WeChating/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/inputbackground.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Nov 30 20:06:09 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 | local.properties
16 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/assets/litePal.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/values/attrs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_home_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_left.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/dialog_right.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
5 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_dashboard_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/EmptyContentPage.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.os.Bundle;
6 |
7 |
8 | public class EmptyContentPage extends AppCompatActivity {
9 |
10 | @Override
11 | protected void onCreate(Bundle savedInstanceState) {
12 | super.onCreate(savedInstanceState);
13 | setContentView(R.layout.empty_content_page);
14 | }
15 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable/buttonbackground.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
11 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/rounded_edittext.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
10 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | WeChating
3 | MainActivity
4 | 消息
5 | 通讯录
6 | 朋友圈
7 | 我的
8 | 删除好友
9 | 删除
10 | 添加朋友
11 | 帮助与反馈
12 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_notifications_black_24dp.xml:
--------------------------------------------------------------------------------
1 |
6 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/index/IndexViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.index;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 | import androidx.lifecycle.ViewModel;
6 |
7 | public class IndexViewModel extends ViewModel {
8 |
9 | private MutableLiveData mText;
10 |
11 | public IndexViewModel() {
12 | mText = new MutableLiveData<>();
13 | mText.setValue("This is dashboard fragment");
14 | }
15 |
16 | public LiveData getText() {
17 | return mText;
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/mine/MineViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.mine;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 | import androidx.lifecycle.ViewModel;
6 |
7 | public class MineViewModel extends ViewModel {
8 |
9 | private MutableLiveData mText;
10 |
11 | public MineViewModel() {
12 | mText = new MutableLiveData<>();
13 | mText.setValue("This is notifications fragment");
14 | }
15 |
16 | public LiveData getText() {
17 | return mText;
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/news/NewsViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.news;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 | import androidx.lifecycle.ViewModel;
6 |
7 | public class NewsViewModel extends ViewModel {
8 |
9 | private MutableLiveData mText;
10 |
11 | public NewsViewModel() {
12 | mText = new MutableLiveData<>();
13 | mText.setValue("This is notifications fragment");
14 | }
15 |
16 | public LiveData getText() {
17 | return mText;
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_index.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/friends/FriendsViewModel.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.friends;
2 |
3 | import androidx.lifecycle.LiveData;
4 | import androidx.lifecycle.MutableLiveData;
5 | import androidx.lifecycle.ViewModel;
6 |
7 | public class FriendsViewModel extends ViewModel {
8 |
9 | private MutableLiveData mText;
10 |
11 | public FriendsViewModel() {
12 | mText = new MutableLiveData<>();
13 | mText.setValue("This is home fragment");
14 | }
15 |
16 | public LiveData getText() {
17 | return mText;
18 | }
19 | }
--------------------------------------------------------------------------------
/app/src/main/res/menu/popumenu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #FFBB86FC
4 | #FF6200EE
5 | #FF3700B3
6 | #FF03DAC5
7 | #FF018786
8 | #FF000000
9 | #FFFFFFFF
10 | #12de20
11 | #12de20
12 | #bfbfbf
13 | #ECE9E9
14 | #F3F3F3
15 |
--------------------------------------------------------------------------------
/app/src/main/res/menu/bottom_nav_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/example/wechating/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.ext.junit.runners.AndroidJUnit4;
6 |
7 | import com.example.wechating.domain.User;
8 | import com.example.wechating.utils.JDBCUtils;
9 |
10 | import org.junit.Test;
11 | import org.junit.runner.RunWith;
12 |
13 | import java.sql.SQLException;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 | import static com.example.wechating.utils.JDBCUtils.findAll;
18 | import static org.junit.Assert.*;
19 |
20 | /**
21 | * Instrumented test, which will execute on an Android device.
22 | *
23 | * @see Testing documentation
24 | */
25 | @RunWith(AndroidJUnit4.class)
26 | public class ExampleInstrumentedTest {
27 |
28 |
29 | }
--------------------------------------------------------------------------------
/app/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/values-night/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_friends.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
12 |
13 |
21 |
22 |
--------------------------------------------------------------------------------
/.idea/gradle.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
22 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
16 |
17 |
25 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/make_moment_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/empty_content_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
18 |
19 |
26 |
27 |
--------------------------------------------------------------------------------
/.idea/jarRepositories.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/domain/Msg.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.domain;
2 |
3 | public class Msg {
4 | public static final int type_received = 0;
5 | public static final int type_sent = 1;
6 | private String content;
7 | private int type;
8 | private int headerid;
9 |
10 | public Msg(String content, int type) {
11 | this.content = content;
12 | this.type = type;
13 | }
14 |
15 | public static int getType_sent() {
16 | return type_sent;
17 | }
18 |
19 | public String getContent() {
20 | return content;
21 | }
22 |
23 | public void setContent(String content) {
24 | this.content = content;
25 | }
26 |
27 | public int getType() {
28 | return type;
29 | }
30 |
31 | public void setType(int type) {
32 | this.type = type;
33 | }
34 |
35 | public int getHeaderid() {
36 | return headerid;
37 | }
38 |
39 | public void setHeaderid(int headerid) {
40 | this.headerid = headerid;
41 | }
42 |
43 | public static int getType_received() {
44 | return type_received;
45 | }
46 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app"s APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | android.enableJetifier=true
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/MakeMomentPage.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 |
10 | import com.example.wechating.ui.news.NewsFragment;
11 |
12 | public class MakeMomentPage extends AppCompatActivity {
13 |
14 | private Button makeMomentBtn;
15 |
16 | @Override
17 | protected void onCreate(Bundle savedInstanceState) {
18 | super.onCreate(savedInstanceState);
19 | setContentView(R.layout.make_moment_page);
20 |
21 |
22 | makeMomentBtn=(Button)findViewById(R.id.make_moment);
23 | makeMomentBtn.setOnClickListener(new View.OnClickListener() {
24 | @Override
25 | public void onClick(View v) {
26 | NewsFragment.update();
27 | Intent intent=new Intent(MakeMomentPage.this, Index.class);
28 | intent.putExtra("flag", 2);
29 | startActivity(intent);
30 | MakeMomentPage.this.finish();
31 | }
32 | });
33 | }
34 |
35 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/domain/User.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.domain;
2 |
3 | import org.litepal.annotation.Column;
4 | import org.litepal.crud.DataSupport;
5 |
6 | /**
7 | * Created by txllg on 2020/11/29.
8 | */
9 |
10 | public class User extends DataSupport {
11 | @Column(unique = true)//用户名唯一
12 | private String username;
13 | @Column(nullable = false)//密码不为空
14 | private String password;
15 |
16 |
17 | public User(String username, String password) {
18 | this.username = username;
19 | this.password = password;
20 | }
21 |
22 | public User() {
23 | }
24 |
25 | public String getUsername() {
26 | return username;
27 | }
28 |
29 | public void setUsername(String username) {
30 | this.username = username;
31 | }
32 |
33 | public String getPassword() {
34 | return password;
35 | }
36 |
37 | public void setPassword(String password) {
38 | this.password = password;
39 | }
40 |
41 |
42 | @Override
43 | public String toString() {
44 | return "User{" +
45 | "username='" + username + '\'' +
46 | ", password='" + password + '\'' +
47 | '}';
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/utils/UserUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.utils;
2 |
3 |
4 | import com.example.wechating.domain.User;
5 | import org.litepal.crud.DataSupport;
6 |
7 | import java.util.ArrayList;
8 | import java.util.List;
9 |
10 | public class UserUtil {
11 | public static boolean addUser(User user){//添加用户方法
12 | List users=new ArrayList();
13 | users=findAllUser();
14 | String username=user.getUsername();
15 |
16 |
17 | for(User e:users){
18 | if(e.getUsername().equals(username))
19 | return false;
20 | }
21 | return user.save();
22 | }
23 |
24 |
25 |
26 | public static List findAllUser(){//查询所有用户的方法
27 |
28 | List users= DataSupport.findAll(User.class);
29 | return users;
30 | }
31 |
32 | public static boolean login(User user){
33 | List users=new ArrayList();
34 | users=findAllUser();
35 | String username=user.getUsername();
36 | String password=user.getPassword();
37 | for(User e:users)
38 | if((e.getUsername().equals(username))&&(e.getPassword().equals(password)))
39 | return true;//登陆成功
40 |
41 |
42 | return false;//登录失败
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/app/src/main/res/navigation/mobile_navigation.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
19 |
20 |
25 |
26 |
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/utils/FriendsUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.utils;
2 |
3 | import android.widget.Toast;
4 |
5 | import com.example.wechating.domain.Friends;
6 | import com.example.wechating.domain.User;
7 |
8 | import org.litepal.crud.DataSupport;
9 |
10 | import java.util.ArrayList;
11 | import java.util.List;
12 |
13 | public class FriendsUtil {
14 | public static boolean addFriends(Friends friends){//添加好友
15 | List lists=new ArrayList();
16 | lists=findAllFriends();
17 | String name=friends.getName();
18 | for(Friends e:lists)
19 | if(e.getName().equals(name)){
20 | return false;
21 | }
22 | friends.save();
23 | return true;
24 | }
25 |
26 | public static List findAllFriends(){//查询所有好友
27 | List lists= DataSupport.findAll(Friends.class);
28 | return lists;
29 | }
30 |
31 | public static List findMyFriends(){//查询自己的好友
32 | List lists= DataSupport.findAll(Friends.class);
33 | List res=new ArrayList<>();
34 | for(Friends e:lists){
35 | if(e.getIsFriend()==1)
36 | res.add(e);
37 | }
38 | return res;
39 | }
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/message_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
12 |
22 |
23 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 |
10 | import org.litepal.LitePal;
11 |
12 | public class MainActivity extends AppCompatActivity implements View.OnClickListener {
13 |
14 | private Button signin;
15 | private Button newUser;
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_main);
21 | LitePal.initialize(this);
22 |
23 | signin = (Button) findViewById(R.id.signin);
24 | newUser = (Button) findViewById(R.id.newUser);
25 | signin.setOnClickListener(this);
26 | newUser.setOnClickListener(this);
27 | }
28 |
29 | @Override
30 | public void onClick(View v) {
31 | Intent intent;
32 | if (v.getId() == R.id.signin) {//转到登录界面
33 | intent = new Intent(MainActivity.this, LoginActivity.class);
34 | startActivity(intent);
35 | } else if (v.getId() == R.id.newUser) {//转到注册界面
36 | intent = new Intent(MainActivity.this, RegistActivity.class);
37 | startActivity(intent);
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
15 |
16 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/app/src/test/java/com/example/wechating/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import com.example.wechating.domain.Friends;
4 | import com.example.wechating.domain.User;
5 | import com.example.wechating.utils.JDBCUtils;
6 | import com.example.wechating.utils.UserUtil;
7 |
8 | import org.junit.Test;
9 | import org.litepal.LitePal;
10 |
11 | import java.sql.SQLException;
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | import static com.example.wechating.utils.JDBCUtils.findAll;
16 | import static org.junit.Assert.*;
17 |
18 | /**
19 | * Example local unit test, which will execute on the development machine (host).
20 | *
21 | * @see Testing documentation
22 | */
23 | public class ExampleUnitTest {
24 | @Test
25 | public void addition_isCorrect() {
26 | assertEquals(4, 2 + 2);
27 | }
28 |
29 | @Test
30 | public void testFindAll() throws Exception {
31 | List users=new ArrayList();//测试findAll方法
32 | users= UserUtil.findAllUser();
33 |
34 | for(User e:users)
35 | System.out.println(e);
36 | }
37 |
38 | //测试添加用户方法
39 | @Test
40 | public void testAddUser() throws SQLException {
41 | User user=new User("txl3","123");
42 | int res= JDBCUtils.addUser(user);
43 | if(res==1)
44 | System.out.println("添加成功");
45 | else if(res==0)
46 | System.out.println("添加失败");
47 | }
48 |
49 | @Test
50 | public void test2(){
51 | Friends f=new Friends("haha");
52 | System.out.println(f.toString());
53 | }
54 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_index.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
19 |
20 |
33 |
34 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'com.android.application'
3 | }
4 |
5 | android {
6 | compileSdkVersion 30
7 | buildToolsVersion "30.0.2"
8 |
9 | defaultConfig {
10 | applicationId "com.example.wechating"
11 | minSdkVersion 28
12 | targetSdkVersion 30
13 | versionCode 1
14 | versionName "1.0"
15 |
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 |
19 | buildTypes {
20 | release {
21 | minifyEnabled false
22 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
23 | }
24 | }
25 | compileOptions {
26 | sourceCompatibility JavaVersion.VERSION_1_8
27 | targetCompatibility JavaVersion.VERSION_1_8
28 | }
29 | }
30 |
31 | dependencies {
32 |
33 | implementation 'androidx.appcompat:appcompat:1.1.0'
34 | implementation 'com.google.android.material:material:1.1.0'
35 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
36 | implementation 'org.litepal.android:core:1.5.1'
37 | implementation 'androidx.recyclerview:recyclerview:1.0.0'
38 | implementation 'com.github.xubo.statusbarutils:StatusBarUtils:1.0.1'
39 | implementation 'com.belerweb:pinyin4j:2.5.0'
40 | implementation 'com.squareup.retrofit2:converter-gson:2.4.0'
41 | implementation 'androidx.navigation:navigation-fragment:2.3.1'
42 | implementation 'androidx.navigation:navigation-ui:2.3.1'
43 | implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
44 | implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
45 | testImplementation 'junit:junit:4.+'
46 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
47 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
48 | }
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 |
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.View;
7 | import android.widget.Button;
8 | import android.widget.EditText;
9 | import android.widget.TextView;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 |
13 | import com.example.wechating.domain.User;
14 | import com.example.wechating.utils.UserUtil;
15 |
16 | /**
17 | * Created by txllg on 2020/11/29.
18 | */
19 |
20 | public class LoginActivity extends AppCompatActivity {
21 | private Button loginbtn;
22 | private EditText usernameText;
23 | private EditText passwordText;
24 | private TextView errorTip;
25 |
26 | @Override
27 | protected void onCreate(Bundle savedInstanceState) {
28 | super.onCreate(savedInstanceState);
29 | setContentView(R.layout.login);
30 | loginbtn=(Button)findViewById(R.id.btn_login);
31 | usernameText=(EditText)findViewById(R.id.login_username_input);
32 | passwordText=(EditText)findViewById(R.id.login_password_input);
33 | errorTip=(TextView) findViewById(R.id.error_tip);
34 |
35 |
36 | loginbtn.setOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | String username=usernameText.getText().toString();
40 | String password=passwordText.getText().toString();
41 | User user=new User(username,password);
42 | Boolean res=UserUtil.login(user);
43 | if(!res)//用户名或密码错误
44 | errorTip.setText("用户名或密码错误,请检查");
45 |
46 | else{//登陆成功
47 | Intent intent=new Intent(LoginActivity.this,Index.class);
48 | startActivity(intent);
49 |
50 | }
51 | }
52 | });
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/mine/MineFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.mine;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.LinearLayout;
9 | import android.widget.ListView;
10 | import android.widget.TextView;
11 |
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.Nullable;
14 | import androidx.fragment.app.Fragment;
15 | import androidx.lifecycle.Observer;
16 | import androidx.lifecycle.ViewModelProvider;
17 |
18 | import com.example.wechating.EmptyContentPage;
19 | import com.example.wechating.MainActivity;
20 | import com.example.wechating.R;
21 |
22 | public class MineFragment extends Fragment implements View.OnClickListener{
23 |
24 | private MineViewModel mineViewModel;
25 | private LinearLayout linearLayoutStar;
26 | private LinearLayout linearLayoutCards;
27 |
28 | public View onCreateView(@NonNull LayoutInflater inflater,
29 | ViewGroup container, Bundle savedInstanceState) {
30 | mineViewModel =
31 | new ViewModelProvider(this).get(MineViewModel.class);
32 | View root = inflater.inflate(R.layout.fragment_mine, container, false);
33 | mineViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
34 | @Override
35 | public void onChanged(@Nullable String s) {
36 | }
37 | });
38 | linearLayoutStar=root.findViewById(R.id.linear_start);
39 | linearLayoutCards=root.findViewById(R.id.linear_cards);
40 | linearLayoutStar.setOnClickListener(this);
41 | linearLayoutCards.setOnClickListener(this);
42 | return root;
43 | }
44 |
45 | @Override
46 | public void onClick(View v) {
47 | Intent intent=new Intent(getActivity(), EmptyContentPage.class);
48 | startActivity(intent);
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/msg_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
29 |
30 |
31 |
32 |
33 |
34 |
44 |
45 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/friends_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
9 |
14 |
15 |
23 |
24 |
29 |
30 |
31 |
42 |
43 |
44 |
45 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/AddFriendPage.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.EditText;
10 | import android.widget.LinearLayout;
11 | import android.widget.Toast;
12 |
13 | import com.example.wechating.ui.friends.FriendsFragment;
14 |
15 | public class AddFriendPage extends AppCompatActivity implements View.OnClickListener{
16 | private Button search;
17 | private Button addfriendBtn;
18 | private LinearLayout l1;
19 | private LinearLayout l2;
20 | private EditText searchEdit;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.add_friend_page);
26 | search=(Button)findViewById(R.id.search_id);
27 | addfriendBtn=(Button)findViewById(R.id.add_friend_btn);
28 | l1=(LinearLayout)findViewById(R.id.add_friend_page);
29 | l2=(LinearLayout)findViewById(R.id.add_friend_page2);
30 | searchEdit=(EditText)findViewById(R.id.add_friend_edit);
31 | l1.setVisibility(View.GONE);
32 | l2.setVisibility(View.GONE);
33 | search.setOnClickListener(this);
34 | addfriendBtn.setOnClickListener(this);
35 | }
36 |
37 | @Override
38 | public void onClick(View v) {
39 | if(v.getId()==R.id.search_id){
40 | if(searchEdit.getText().toString().equals("txltxl8")){
41 | l2.setVisibility(View.GONE);
42 | l1.setVisibility(View.VISIBLE);
43 | }
44 | else
45 | l2.setVisibility(View.VISIBLE);
46 |
47 | }
48 | else if(v.getId()==R.id.add_friend_btn){
49 | Toast.makeText(AddFriendPage.this,"恭喜,添加成功!",Toast.LENGTH_LONG).show();
50 | FriendsFragment.update();
51 | Intent intent=new Intent(AddFriendPage.this, Index.class);
52 | intent.putExtra("flag", 2);
53 | startActivity(intent);
54 | AddFriendPage.this.finish();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/Index.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.Menu;
6 | import android.view.MenuInflater;
7 | import android.view.MenuItem;
8 |
9 | import com.google.android.material.bottomnavigation.BottomNavigationView;
10 |
11 | import androidx.appcompat.app.AppCompatActivity;
12 | import androidx.navigation.NavController;
13 | import androidx.navigation.Navigation;
14 | import androidx.navigation.ui.AppBarConfiguration;
15 | import androidx.navigation.ui.NavigationUI;
16 |
17 | public class Index extends AppCompatActivity {
18 |
19 | @Override
20 | protected void onCreate(Bundle savedInstanceState) {
21 | super.onCreate(savedInstanceState);
22 | setContentView(R.layout.activity_index);
23 | BottomNavigationView navView = findViewById(R.id.nav_view);
24 | // Passing each menu ID as a set of Ids because each
25 | // menu should be considered as top level destinations.
26 | AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
27 | R.id.message_id, R.id.friends_id, R.id.news_id,R.id.mine_id)
28 | .build();
29 | NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
30 | NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
31 | NavigationUI.setupWithNavController(navView, navController);
32 | }
33 |
34 | @Override
35 | public boolean onCreateOptionsMenu(Menu menu) {
36 | MenuInflater inflater=getMenuInflater();
37 | inflater.inflate(R.menu.popumenu,menu);
38 | return true;
39 | }
40 |
41 | @Override
42 | public boolean onOptionsItemSelected(MenuItem item) {
43 | switch (item.getItemId()){
44 | case R.id.menu_addFriend:
45 | Intent intent = new Intent(Index.this, AddFriendPage.class);
46 | startActivity(intent);
47 | return true;
48 | case R.id.menu_help:
49 | return true;
50 | default:
51 | return super.onOptionsItemSelected(item);
52 | }
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/RegistActivity.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import android.widget.EditText;
8 | import android.widget.TextView;
9 | import android.widget.Toast;
10 |
11 |
12 | import androidx.appcompat.app.AppCompatActivity;
13 |
14 | import com.example.wechating.domain.User;
15 | import com.example.wechating.utils.JDBCUtils;
16 | import com.example.wechating.utils.UserUtil;
17 |
18 | import java.sql.SQLException;
19 |
20 | /**
21 | * Created by txllg on 2020/11/29.
22 | */
23 |
24 | public class RegistActivity extends AppCompatActivity implements View.OnClickListener{
25 |
26 | private EditText usernameText;
27 | private EditText passwordText;
28 | private TextView errorTip;
29 | private Button registbtn;
30 | private Button toLoginbtn;
31 |
32 | @Override
33 | protected void onCreate( Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(R.layout.regist);
36 | registbtn=(Button)findViewById(R.id.btn_regist);
37 | toLoginbtn=(Button)findViewById(R.id.toLogin_id);
38 | usernameText=(EditText)findViewById(R.id.regist_username_input);
39 | passwordText=(EditText)findViewById(R.id.regist_password_input);
40 | errorTip=(TextView)findViewById(R.id.error_tip);
41 | registbtn.setOnClickListener(this);
42 | toLoginbtn.setOnClickListener(this);
43 | }
44 |
45 | @Override
46 | public void onClick(View v) {
47 | if(v.getId()==R.id.btn_regist){//注册
48 | User user=new User(usernameText.getText().toString(),passwordText.getText().toString());
49 | boolean res=false;
50 | res= UserUtil.addUser(user);//res为true,则插入成功
51 |
52 | if(!res)//用户名存在
53 | errorTip.setText("用户名已经存在,请重新输入");
54 | else{
55 | errorTip.setText("");
56 | Toast.makeText(RegistActivity.this,"注册成功,现在可以去登陆了",Toast.LENGTH_LONG).show();
57 | }
58 | }
59 | else if(v.getId()==R.id.toLogin_id){//去登陆页面
60 | Intent intent=new Intent(RegistActivity.this,LoginActivity.class);
61 | startActivity(intent);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
17 | set DEFAULT_JVM_OPTS=
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windows variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 |
53 | :win9xME_args
54 | @rem Slurp the command line arguments.
55 | set CMD_LINE_ARGS=
56 | set _SKIP=2
57 |
58 | :win9xME_args_slurp
59 | if "x%~1" == "x" goto execute
60 |
61 | set CMD_LINE_ARGS=%*
62 |
63 | :execute
64 | @rem Setup the command line
65 |
66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
67 |
68 | @rem Execute Gradle
69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
70 |
71 | :end
72 | @rem End local scope for the variables with windows NT shell
73 | if "%ERRORLEVEL%"=="0" goto mainEnd
74 |
75 | :fail
76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
77 | rem the _cmd.exe /c_ return code!
78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
79 | exit /b 1
80 |
81 | :mainEnd
82 | if "%OS%"=="Windows_NT" endlocal
83 |
84 | :omega
85 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/SortAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.BaseAdapter;
8 | import android.widget.TextView;
9 |
10 | import com.example.wechating.R;
11 | import com.example.wechating.domain.Friends;
12 |
13 | import java.util.List;
14 |
15 | public class SortAdapter extends BaseAdapter{
16 |
17 | private List list = null;
18 | private Context mContext;
19 |
20 | public SortAdapter(Context mContext, List list) {
21 | this.mContext = mContext;
22 | this.list = list;
23 | }
24 |
25 | public int getCount() {
26 | return this.list.size();
27 | }
28 |
29 | public Object getItem(int position) {
30 | return list.get(position);
31 | }
32 |
33 | public long getItemId(int position) {
34 | return position;
35 | }
36 |
37 | public View getView(final int position, View view, ViewGroup arg2) {
38 | ViewHolder viewHolder;
39 | final Friends friends = list.get(position);
40 | if (view == null) {
41 | viewHolder = new ViewHolder();
42 | view = LayoutInflater.from(mContext).inflate(R.layout.friends_item, null);
43 | viewHolder.name = (TextView) view.findViewById(R.id.name);
44 | viewHolder.catalog = (TextView) view.findViewById(R.id.catalog);
45 | view.setTag(viewHolder);
46 | } else {
47 | viewHolder = (ViewHolder) view.getTag();
48 | }
49 |
50 | //根据position获取首字母作为目录catalog
51 | String catalog = list.get(position).getFirstLetter();
52 |
53 | //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
54 | if(position == getPositionForSection(catalog)){
55 | viewHolder.catalog.setVisibility(View.VISIBLE);
56 | viewHolder.catalog.setText(friends.getFirstLetter().toUpperCase());
57 | }else{
58 | viewHolder.catalog.setVisibility(View.GONE);
59 | }
60 |
61 | viewHolder.name.setText(this.list.get(position).getName());
62 |
63 | return view;
64 |
65 | }
66 |
67 | final static class ViewHolder {
68 | TextView catalog;
69 | TextView name;
70 | }
71 |
72 | /**
73 | * 获取catalog首次出现位置
74 | */
75 | public int getPositionForSection(String catalog) {
76 | for (int i = 0; i < getCount(); i++) {
77 | String sortStr = list.get(i).getFirstLetter();
78 | if (catalog.equalsIgnoreCase(sortStr)) {
79 | return i;
80 | }
81 | }
82 | return -1;
83 | }
84 |
85 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/login.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
19 |
20 |
32 |
33 |
46 |
47 |
56 |
57 |
67 |
68 |
69 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/MsgAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.LinearLayout;
8 | import android.widget.TextView;
9 |
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | import androidx.annotation.NonNull;
15 | import androidx.recyclerview.widget.RecyclerView;
16 |
17 | import com.example.wechating.R;
18 | import com.example.wechating.domain.Msg;
19 |
20 | public class MsgAdapter extends RecyclerView.Adapter {
21 | List msgs = new ArrayList<>();
22 | Context context;
23 | LayoutInflater inflater;
24 |
25 | public MsgAdapter(List msgs, Context context) {
26 | this.msgs = msgs;
27 | this.context = context;
28 | inflater = LayoutInflater.from(context);
29 | }
30 |
31 | @NonNull
32 | @Override
33 | public MsgAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
34 | View view = inflater.inflate(R.layout.msg_item, null);
35 | ViewHolder viewHolder = new ViewHolder(view);
36 | return viewHolder;
37 | }
38 |
39 | @Override
40 | public void onBindViewHolder(@NonNull MsgAdapter.ViewHolder holder, int position) {
41 | Msg msg = msgs.get(position);
42 | if (msg.getType() == Msg.type_received) {
43 | if(position<2)
44 | holder.left_layout.setVisibility(View.VISIBLE);
45 | else
46 | holder.left_layout.setVisibility(View.GONE);
47 | holder.right_layout.setVisibility(View.GONE);
48 | holder.left_msg.setText(msg.getContent());
49 | } else if (msg.getType() == Msg.type_sent) {
50 | holder.right_layout.setVisibility(View.VISIBLE);
51 | holder.left_layout.setVisibility(View.GONE);
52 | holder.right_msg.setText(msg.getContent());
53 |
54 | }
55 | }
56 |
57 | @Override
58 | public int getItemCount() {
59 | return msgs.size();
60 | }
61 |
62 | public class ViewHolder extends RecyclerView.ViewHolder {
63 | TextView left_msg;
64 | TextView right_msg;
65 | LinearLayout left_layout;
66 | LinearLayout right_layout;
67 |
68 | public ViewHolder(@NonNull View itemView) {
69 | super(itemView);
70 | left_msg = itemView.findViewById(R.id.left_msg);
71 | right_msg = itemView.findViewById(R.id.right_msg);
72 | left_layout = itemView.findViewById(R.id.left_layout);
73 | right_layout = itemView.findViewById(R.id.right_layout);
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/Cn2Spell.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import net.sourceforge.pinyin4j.PinyinHelper;
4 | import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
5 | import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
6 | import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
7 |
8 | /**
9 | * 汉字转换位汉语拼音,英文字符不变
10 | */
11 | public class Cn2Spell {
12 |
13 | public static StringBuffer sb = new StringBuffer();
14 |
15 | /**
16 | * 获取汉字字符串的首字母,英文字符不变
17 | * 例如:阿飞→af
18 | */
19 | public static String getPinYinHeadChar(String chines) {
20 | sb.setLength(0);
21 | char[] chars = chines.toCharArray();
22 | HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
23 | defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
24 | defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
25 | for (int i = 0; i < chars.length; i++) {
26 | if (chars[i] > 128) {
27 | try {
28 | sb.append(PinyinHelper.toHanyuPinyinStringArray(chars[i], defaultFormat)[0].charAt(0));
29 | } catch (Exception e) {
30 | e.printStackTrace();
31 | }
32 | } else {
33 | sb.append(chars[i]);
34 | }
35 | }
36 | return sb.toString();
37 | }
38 |
39 | /**
40 | * 获取汉字字符串的第一个字母
41 | */
42 | public static String getPinYinFirstLetter(String str) {
43 | sb.setLength(0);
44 | char c = str.charAt(0);
45 | String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
46 | if (pinyinArray != null) {
47 | sb.append(pinyinArray[0].charAt(0));
48 | } else {
49 | sb.append(c);
50 | }
51 | return sb.toString();
52 | }
53 |
54 | /**
55 | * 获取汉字字符串的汉语拼音,英文字符不变
56 | */
57 | public static String getPinYin(String chines) {
58 | sb.setLength(0);
59 | char[] nameChar = chines.toCharArray();
60 | HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat();
61 | defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE);
62 | defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
63 | for (int i = 0; i < nameChar.length; i++) {
64 | if (nameChar[i] > 128) {
65 | try {
66 | sb.append(PinyinHelper.toHanyuPinyinStringArray(nameChar[i], defaultFormat)[0]);
67 | } catch (Exception e) {
68 | e.printStackTrace();
69 | }
70 | } else {
71 | sb.append(nameChar[i]);
72 | }
73 | }
74 | return sb.toString();
75 | }
76 |
77 | }
78 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/domain/Friends.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.domain;
2 |
3 | import com.example.wechating.component.Cn2Spell;
4 |
5 | import org.litepal.annotation.Column;
6 | import org.litepal.crud.DataSupport;
7 |
8 | public class Friends extends DataSupport implements Comparable{
9 | private String nickname;
10 | private String username;
11 | private int isFriend;
12 |
13 | @Column(ignore = true)
14 | private String pinyin; // 姓名对应的拼音
15 | @Column(ignore = true)
16 | private String firstLetter; // 拼音的首字母
17 |
18 | public Friends() {
19 | }
20 |
21 | public String getNickname() {
22 | return nickname;
23 | }
24 |
25 | public void setNickname(String nickname) {
26 | this.nickname = nickname;
27 | }
28 |
29 | public int getIsFriend() {
30 | return isFriend;
31 | }
32 |
33 | public void setIsFriend(int isFriend) {
34 | this.isFriend = isFriend;
35 | }
36 |
37 | public Friends(String name) {
38 | this.nickname = name;
39 | pinyin = Cn2Spell.getPinYin(name); // 根据姓名获取拼音
40 | firstLetter = pinyin.substring(0, 1).toUpperCase(); // 获取拼音首字母并转成大写
41 | if (!firstLetter.matches("[A-Z]")) { // 如果不在A-Z中则默认为“#”
42 | firstLetter = "#";
43 | }
44 | }
45 |
46 | public String getName() {
47 | return nickname;
48 | }
49 |
50 | public void setName(String name) {
51 | this.nickname = name;
52 | }
53 |
54 | public String getPinyin() {
55 | return pinyin;
56 | }
57 |
58 | public void setPinyin(String pinyin) {
59 | this.pinyin = pinyin;
60 | }
61 |
62 | public String getFirstLetter() {
63 | return firstLetter;
64 | }
65 |
66 | public void setFirstLetter(String firstLetter) {
67 | this.firstLetter = firstLetter;
68 | }
69 |
70 | public String getUsername() {
71 | return username;
72 | }
73 |
74 |
75 | public void setUsername(String username) {
76 | this.username = username;
77 | }
78 |
79 |
80 | @Override
81 | public String toString() {
82 | return "Friends{" +
83 | "nickname='" + nickname + '\'' +
84 | ", username='" + username + '\'' +
85 | ", isFriend=" + isFriend +
86 | ", pinyin='" + pinyin + '\'' +
87 | ", firstLetter='" + firstLetter + '\'' +
88 | '}';
89 | }
90 |
91 | @Override
92 | public int compareTo(Friends another) {
93 | if (firstLetter.equals("#") && !another.getFirstLetter().equals("#")) {
94 | return 1;
95 | } else if (!firstLetter.equals("#") && another.getFirstLetter().equals("#")){
96 | return -1;
97 | } else {
98 | return pinyin.compareToIgnoreCase(another.getPinyin());
99 | }
100 |
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
49 |
50 |
56 |
57 |
68 |
69 |
70 |
71 |
77 |
78 |
88 |
89 |
90 |
91 |
92 |
93 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/regist.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
11 |
19 |
20 |
32 |
33 |
46 |
47 |
56 |
57 |
67 |
68 |
78 |
79 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_news.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
20 |
21 |
29 |
30 |
40 |
41 |
48 |
49 |
55 |
56 |
57 |
58 |
59 |
65 |
66 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/news_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
11 |
14 |
15 |
21 |
22 |
30 |
31 |
36 |
37 |
43 |
44 |
45 |
52 |
53 |
57 |
58 |
62 |
63 |
67 |
68 |
69 |
76 |
77 |
78 |
87 |
88 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/chat_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
18 |
19 |
26 |
27 |
35 |
36 |
40 |
41 |
45 |
46 |
51 |
52 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
87 |
88 |
89 |
90 |
91 |
92 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/add_friend_page.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
17 |
18 |
22 |
23 |
35 |
36 |
42 |
43 |
44 |
45 |
52 |
53 |
59 |
60 |
70 |
71 |
77 |
78 |
79 |
80 |
87 |
88 |
93 |
94 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/NewsAdapter.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import android.content.Context;
4 | import android.view.LayoutInflater;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 | import android.widget.ImageView;
8 | import android.widget.TextView;
9 |
10 | import androidx.cardview.widget.CardView;
11 | import androidx.recyclerview.widget.RecyclerView;
12 |
13 | import com.example.wechating.R;
14 | import com.example.wechating.domain.Friends;
15 |
16 | import java.util.List;
17 |
18 | public class NewsAdapter extends RecyclerView.Adapter{
19 | private Context mContext;
20 | private List mFriendList;
21 | private List profiles;
22 | private List nickname;
23 | private List> itemPictures;
24 | private List copyWriting;
25 | private List times;
26 |
27 | static class ViewHolder extends RecyclerView.ViewHolder {
28 | CardView cardView;
29 | ImageView image1;
30 | ImageView image2;
31 | ImageView image3;
32 | ImageView imageStar;
33 | ImageView profile;
34 | TextView nickname;
35 | TextView timeText;
36 | TextView copyWriting;
37 |
38 | public ViewHolder(View view) {
39 | super(view);
40 | cardView = (CardView) view;
41 | image1 = (ImageView) view.findViewById(R.id.friend_image1);
42 | image2 = (ImageView) view.findViewById(R.id.friend_image2);
43 | image3 = (ImageView) view.findViewById(R.id.friend_image3);
44 | imageStar=(ImageView) view.findViewById(R.id.star1);
45 | profile=(ImageView) view.findViewById(R.id.news_profile);
46 | nickname=(TextView) view.findViewById(R.id.friend_name);
47 | timeText=(TextView) view.findViewById(R.id.time_text);
48 | copyWriting=(TextView) view.findViewById(R.id.copyWriting);
49 | }
50 | }
51 |
52 | public NewsAdapter(List friendList,List profiles,
53 | List nickname,List> itemPictures,List copyWriting,List times) {
54 |
55 | mFriendList = friendList;//朋友圈好友显示的昵称
56 | this.profiles=profiles;
57 | this.nickname=nickname;
58 | this.itemPictures=itemPictures;
59 | this.copyWriting=copyWriting;
60 | this.times=times;
61 | }
62 |
63 | @Override
64 | public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
65 | if (mContext == null) {
66 | mContext = parent.getContext();
67 | }
68 | View view = LayoutInflater.from(mContext).inflate(R.layout.news_item,parent,false);
69 | return new ViewHolder(view);
70 | }
71 |
72 | @Override
73 | public void onBindViewHolder(ViewHolder holder,int position) {
74 |
75 | holder.imageStar.setOnClickListener(new View.OnClickListener() {//点赞
76 | @Override
77 | public void onClick(View v) {
78 | holder.imageStar.setImageResource(R.drawable.star2);
79 | }
80 | });
81 |
82 | holder.profile.setImageResource(profiles.get(position));
83 | holder.nickname.setText(nickname.get(position));
84 | holder.copyWriting.setText(copyWriting.get(position));
85 | if(itemPictures.get(position).size()==0);
86 | else if(itemPictures.get(position).size()==1)
87 | holder.image1.setImageResource(itemPictures.get(position).get(0));
88 | else if(itemPictures.get(position).size()==2)
89 | holder.image2.setImageResource(itemPictures.get(position).get(1));
90 | else if(itemPictures.get(position).size()==3)
91 | holder.image3.setImageResource(itemPictures.get(position).get(2));
92 |
93 |
94 | int time=times.get(position);
95 | if(time>0&&time<9)
96 | holder.timeText.setText(time+"小时前");
97 | else if(time>10)
98 | holder.timeText.setText(time+"分钟前");
99 | else holder.timeText.setText("刚刚");
100 | }
101 |
102 | @Override
103 | public int getItemCount() {
104 | return mFriendList.size();
105 | }
106 |
107 | }
108 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/utils/JDBCUtils.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.utils;
2 |
3 |
4 | import com.example.wechating.domain.User;
5 |
6 | import java.lang.reflect.Field;
7 | import java.sql.Connection;
8 | import java.sql.DriverManager;
9 | import java.sql.PreparedStatement;
10 | import java.sql.ResultSet;
11 | import java.sql.ResultSetMetaData;
12 | import java.sql.SQLException;
13 | import java.sql.Statement;
14 | import java.util.ArrayList;
15 | import java.util.List;
16 |
17 |
18 | /**
19 | * Created by txllg on 2020/11/29.
20 | */
21 |
22 | public class JDBCUtils {
23 |
24 | public static Connection getConnection(){
25 | final Connection[] conn = new Connection[1];
26 | new Thread(new Runnable() {
27 | @Override
28 | public void run() {
29 | //获取mysql数据库连接
30 | try{//加载MySql的驱动类
31 | Class.forName("com.mysql.jdbc.Driver") ;
32 | }catch(ClassNotFoundException e){
33 | System.out.println("找不到驱动程序类 ,加载驱动失败!");
34 | e.printStackTrace() ;
35 | }
36 |
37 | String url = "jdbc:mysql://localhost:3306/android?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=utf8" ;
38 | String username = "root" ;
39 | String password = "root" ;
40 | try{
41 | conn[0] = DriverManager.getConnection(url , username , password ) ;
42 | }catch(SQLException se){
43 | System.out.println("数据库连接失败!");
44 | se.printStackTrace() ;
45 | }
46 | }
47 | }).start();
48 | return conn[0];
49 | }
50 |
51 | public static int addUser(User user) throws SQLException {//添加用户
52 | List users=new ArrayList();
53 | users=findAll();
54 | String username=user.getUsername();
55 | String password=user.getPassword();
56 |
57 | for(User e:users){
58 | if(username.equals(e.getUsername()))
59 | return 0;//用户名已经存在,添加失败
60 | }
61 |
62 | Connection conn=getConnection();
63 | PreparedStatement pst=conn.prepareStatement("insert into user(`username`,`password`) values(?,?)");
64 | pst.setString(1,username);
65 | pst.setString(2,password);
66 | pst.executeUpdate();
67 | return 1;//添加成功
68 | }
69 |
70 | public static List findAll() throws SQLException {
71 | List users=new ArrayList();
72 |
73 | Connection conn=getConnection();
74 | System.out.println("现在测试connection的值是否为空:"+conn);
75 | Statement stmt = conn.createStatement() ;
76 | ResultSet resultSet=stmt.executeQuery("select * from User");
77 | users= (List) resultToList(resultSet,User.class);//将resultSet转化为List
78 | return users;
79 | }
80 |
81 | //resultToList方法
82 | public static List resultToList(ResultSet resultSet, Class clazz) {
83 | //创建一个 T 类型的数组
84 | List list = new ArrayList<>();
85 | try {
86 | //获取resultSet 的列的信息
87 | ResultSetMetaData metaData = resultSet.getMetaData();
88 | //遍历resultSet
89 | while (resultSet.next()) {
90 | //遍历每一列
91 | //通过反射获取对象的实例
92 | User t = (User)clazz.newInstance();
93 | for (int i = 0; i < metaData.getColumnCount(); i++) {
94 | //获取列的名字
95 | String fName = metaData.getColumnLabel(i + 1);
96 |
97 | Field[] fields = clazz.getDeclaredFields();
98 | for (Field field : fields) {
99 | if (fName.equals(field.getName())) {
100 | Object obj = resultSet.getObject(fName);
101 | field.setAccessible(true);
102 | //可以根据自己的需求添加几个
103 | if (field.getType().getName().equals("java.lang.Integer")) {
104 | field.set(t, Integer.parseInt(String.valueOf(obj)));
105 | }
106 | if (field.getType().getName().equals("java.lang.String")) {
107 | field.set(t, String.valueOf(obj).equals("null") ? " ": String.valueOf(obj));
108 | }
109 | field.setAccessible(false);
110 | }
111 | }
112 | }
113 | //把赋值后的对象 加入到list集合中
114 | list.add(t);
115 | }
116 |
117 | } catch (Exception e) {
118 | e.printStackTrace();
119 | }
120 | // 返回list
121 | return list;
122 | }
123 |
124 |
125 | }
126 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS=""
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 | # Determine the Java command to use to start the JVM.
70 | if [ -n "$JAVA_HOME" ] ; then
71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
72 | # IBM's JDK on AIX uses strange locations for the executables
73 | JAVACMD="$JAVA_HOME/jre/sh/java"
74 | else
75 | JAVACMD="$JAVA_HOME/bin/java"
76 | fi
77 | if [ ! -x "$JAVACMD" ] ; then
78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
79 |
80 | Please set the JAVA_HOME variable in your environment to match the
81 | location of your Java installation."
82 | fi
83 | else
84 | JAVACMD="java"
85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
86 |
87 | Please set the JAVA_HOME variable in your environment to match the
88 | location of your Java installation."
89 | fi
90 |
91 | # Increase the maximum file descriptors if we can.
92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
93 | MAX_FD_LIMIT=`ulimit -H -n`
94 | if [ $? -eq 0 ] ; then
95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
96 | MAX_FD="$MAX_FD_LIMIT"
97 | fi
98 | ulimit -n $MAX_FD
99 | if [ $? -ne 0 ] ; then
100 | warn "Could not set maximum file descriptor limit: $MAX_FD"
101 | fi
102 | else
103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
104 | fi
105 | fi
106 |
107 | # For Darwin, add options to specify how the application appears in the dock
108 | if $darwin; then
109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
110 | fi
111 |
112 | # For Cygwin, switch paths to Windows format before running java
113 | if $cygwin ; then
114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
116 | JAVACMD=`cygpath --unix "$JAVACMD"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Escape application args
158 | save () {
159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
160 | echo " "
161 | }
162 | APP_ARGS=$(save "$@")
163 |
164 | # Collect all arguments for the java command, following the shell quoting and substitution rules
165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
166 |
167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
169 | cd "$(dirname "$0")"
170 | fi
171 |
172 | exec "$JAVACMD" "$@"
173 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/MessageSlideLayout.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.widget.FrameLayout;
8 | import android.widget.Scroller;
9 |
10 | import com.example.wechating.R;
11 |
12 | public class MessageSlideLayout extends FrameLayout {
13 |
14 | private View contentView;
15 | private View menuView;
16 |
17 | private int viewHeight; //高是相同的
18 | private int contentWidth;
19 | private int menuWidth;
20 | private int catlogWidth;
21 |
22 | //滑动器
23 | private Scroller scroller;
24 |
25 | public MessageSlideLayout(Context context, AttributeSet attrs) {
26 | super(context, attrs);
27 | scroller = new Scroller(context);
28 | }
29 |
30 | /**
31 | * 布局文件加载完成时被调用
32 | */
33 | @Override
34 | protected void onFinishInflate() {
35 | super.onFinishInflate();
36 | contentView = findViewById(R.id.content);
37 | menuView = findViewById(R.id.message_menu);
38 | }
39 |
40 | @Override
41 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
42 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
43 |
44 | viewHeight = getMeasuredHeight();
45 |
46 | contentWidth = contentView.getMeasuredWidth();
47 | menuWidth = menuView.getMeasuredWidth();
48 | }
49 |
50 | @Override
51 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
52 | super.onLayout(changed, left, top, right, bottom);
53 | menuView.layout(contentWidth, 0, contentWidth+menuWidth, viewHeight);
54 | }
55 |
56 |
57 | private float startX;
58 | private float startY;
59 |
60 | private float downX;
61 | private float downY;
62 |
63 | @Override
64 | public boolean onTouchEvent(MotionEvent event) {
65 | super.onTouchEvent(event);
66 | switch (event.getAction())
67 | {
68 | case MotionEvent.ACTION_DOWN:
69 | downX = startX = event.getX();
70 | downY = startY = event.getY();
71 | break;
72 | case MotionEvent.ACTION_MOVE:
73 | float endX = event.getX();
74 | float endY = event.getY();
75 |
76 | //计算偏移量
77 | float distanceX = endX - startX;
78 |
79 | int toScrollX = (int) (getScrollX()-distanceX);
80 | //屏蔽非法值
81 | if (toScrollX < 0 )
82 | {
83 | toScrollX = 0;
84 | }
85 | if (toScrollX > menuWidth)
86 | {
87 | toScrollX = menuWidth;
88 | }
89 | System.out.println("toScroll-->"+toScrollX+"-->"+getScrollX());
90 | scrollTo(toScrollX,getScrollY());
91 |
92 | startX = event.getX();
93 |
94 | float dx = Math.abs(event.getX()-downX);
95 | float dy = Math.abs(event.getY()-downY);
96 | if (dx > dy && dx > 6)
97 | {
98 | //事件反拦截,使父ListView的事件传递到自身SlideLayout
99 | getParent().requestDisallowInterceptTouchEvent(true);
100 | }
101 |
102 | break;
103 | case MotionEvent.ACTION_UP:
104 |
105 | if (getScrollX() > menuWidth/2)
106 | {
107 | //打开menu
108 | openMenu();
109 | }else {
110 | closeMenu();
111 | }
112 |
113 | break;
114 | }
115 | return true;
116 | }
117 |
118 | @Override
119 | public boolean onInterceptTouchEvent(MotionEvent event) {
120 | switch (event.getAction())
121 | {
122 | case MotionEvent.ACTION_DOWN:
123 | downX = startX = event.getX();
124 | downY = startY = event.getY();
125 | if (onStateChangeListener != null)
126 | {
127 | onStateChangeListener.onMove(this);
128 | }
129 | break;
130 | case MotionEvent.ACTION_MOVE:
131 |
132 | float dx = Math.abs(event.getX()-downX);
133 | float dy = Math.abs(event.getY()-downY);
134 | if (dx > dy && dx > 6)
135 | {
136 | //拦截事件
137 | return true;
138 | }
139 |
140 | break;
141 | case MotionEvent.ACTION_UP:
142 | break;
143 | }
144 | return super.onInterceptTouchEvent(event);
145 | }
146 |
147 | /**
148 | * 打开menu菜单
149 | */
150 | public void openMenu() {
151 | int dx = menuWidth-getScrollX();
152 | scroller.startScroll(getScrollX(), getScrollY(),dx, getScrollY());
153 | invalidate();
154 | if (onStateChangeListener != null)
155 | {
156 | onStateChangeListener.onOpen(this);
157 | }
158 | }
159 |
160 | /**
161 | * 关闭菜单
162 | */
163 | public void closeMenu() {
164 | //0表示menu移动到的目标距离
165 | int dx = 0-getScrollX();
166 | scroller.startScroll(getScrollX(), getScrollY(),dx, getScrollY());
167 | invalidate();
168 | if (onStateChangeListener != null)
169 | {
170 | onStateChangeListener.onClose(this);
171 | }
172 | }
173 |
174 | @Override
175 | public void computeScroll() {
176 | super.computeScroll();
177 | if (scroller.computeScrollOffset())
178 | {
179 | scrollTo(scroller.getCurrX(), scroller.getCurrY());
180 | invalidate();
181 | }
182 | }
183 |
184 | public interface OnStateChangeListener
185 | {
186 | void onOpen(MessageSlideLayout slideLayout);
187 | void onMove(MessageSlideLayout slideLayout);
188 | void onClose(MessageSlideLayout slideLayout);
189 | }
190 |
191 | public OnStateChangeListener onStateChangeListener;
192 |
193 | public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
194 | this.onStateChangeListener = onStateChangeListener;
195 | }
196 | }
197 |
198 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/FriendsSlideLayout.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.widget.FrameLayout;
8 | import android.widget.Scroller;
9 |
10 | import com.example.wechating.R;
11 |
12 | public class FriendsSlideLayout extends FrameLayout {
13 |
14 | private View contentView;
15 | private View menuView;
16 | private View catlogView;
17 |
18 | private int viewHeight; //高是相同的
19 | private int contentWidth;
20 | private int menuWidth;
21 | private int catlogWidth;
22 |
23 | //滑动器
24 | private Scroller scroller;
25 |
26 | public FriendsSlideLayout(Context context, AttributeSet attrs) {
27 | super(context, attrs);
28 | scroller = new Scroller(context);
29 | }
30 |
31 | /**
32 | * 布局文件加载完成时被调用
33 | */
34 | @Override
35 | protected void onFinishInflate() {
36 | super.onFinishInflate();
37 | contentView = findViewById(R.id.name);
38 | menuView = findViewById(R.id.menu_friends);
39 | catlogView=findViewById(R.id.catalog);
40 | }
41 |
42 | @Override
43 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
44 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
45 |
46 | viewHeight = getMeasuredHeight();
47 |
48 | contentWidth = contentView.getMeasuredWidth();
49 | menuWidth = menuView.getMeasuredWidth();
50 | catlogWidth=catlogView.getMeasuredWidth();
51 | }
52 |
53 | @Override
54 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
55 | super.onLayout(changed, left, top, right, bottom);
56 | menuView.layout(contentWidth, 0, contentWidth+menuWidth, viewHeight);
57 | }
58 |
59 |
60 | private float startX;
61 | private float startY;
62 |
63 | private float downX;
64 | private float downY;
65 |
66 | @Override
67 | public boolean onTouchEvent(MotionEvent event) {
68 | super.onTouchEvent(event);
69 | switch (event.getAction())
70 | {
71 | case MotionEvent.ACTION_DOWN:
72 | downX = startX = event.getX();
73 | downY = startY = event.getY();
74 | break;
75 | case MotionEvent.ACTION_MOVE:
76 | float endX = event.getX();
77 | float endY = event.getY();
78 |
79 | //计算偏移量
80 | float distanceX = endX - startX;
81 |
82 | int toScrollX = (int) (getScrollX()-distanceX);
83 | //屏蔽非法值
84 | if (toScrollX < 0 )
85 | {
86 | toScrollX = 0;
87 | }
88 | if (toScrollX > menuWidth)
89 | {
90 | toScrollX = menuWidth;
91 | }
92 | System.out.println("toScroll-->"+toScrollX+"-->"+getScrollX());
93 | scrollTo(toScrollX,getScrollY());
94 |
95 | startX = event.getX();
96 |
97 | float dx = Math.abs(event.getX()-downX);
98 | float dy = Math.abs(event.getY()-downY);
99 | if (dx > dy && dx > 6)
100 | {
101 | //事件反拦截,使父ListView的事件传递到自身SlideLayout
102 | getParent().requestDisallowInterceptTouchEvent(true);
103 | }
104 |
105 | break;
106 | case MotionEvent.ACTION_UP:
107 |
108 | if (getScrollX() > menuWidth/2)
109 | {
110 | //打开menu
111 | openMenu();
112 | }else {
113 | closeMenu();
114 | }
115 |
116 | break;
117 | }
118 | return true;
119 | }
120 |
121 | @Override
122 | public boolean onInterceptTouchEvent(MotionEvent event) {
123 | switch (event.getAction())
124 | {
125 | case MotionEvent.ACTION_DOWN:
126 | downX = startX = event.getX();
127 | downY = startY = event.getY();
128 | if (onStateChangeListener != null)
129 | {
130 | onStateChangeListener.onMove(this);
131 | }
132 | break;
133 | case MotionEvent.ACTION_MOVE:
134 |
135 | float dx = Math.abs(event.getX()-downX);
136 | float dy = Math.abs(event.getY()-downY);
137 | if (dx > dy && dx > 6)
138 | {
139 | //拦截事件
140 | return true;
141 | }
142 |
143 | break;
144 | case MotionEvent.ACTION_UP:
145 | break;
146 | }
147 | return super.onInterceptTouchEvent(event);
148 | }
149 |
150 | /**
151 | * 打开menu菜单
152 | */
153 | public void openMenu() {
154 | int dx = menuWidth-getScrollX();
155 | scroller.startScroll(getScrollX(), getScrollY(),dx, getScrollY());
156 | invalidate();
157 | if (onStateChangeListener != null)
158 | {
159 | onStateChangeListener.onOpen(this);
160 | }
161 | }
162 |
163 | /**
164 | * 关闭菜单
165 | */
166 | public void closeMenu() {
167 | //0表示menu移动到的目标距离
168 | int dx = 0-getScrollX();
169 | scroller.startScroll(getScrollX(), getScrollY(),dx, getScrollY());
170 | invalidate();
171 | if (onStateChangeListener != null)
172 | {
173 | onStateChangeListener.onClose(this);
174 | }
175 | }
176 |
177 | @Override
178 | public void computeScroll() {
179 | super.computeScroll();
180 | if (scroller.computeScrollOffset())
181 | {
182 | scrollTo(scroller.getCurrX(), scroller.getCurrY());
183 | invalidate();
184 | }
185 | }
186 |
187 | public interface OnStateChangeListener
188 | {
189 | void onOpen(FriendsSlideLayout slideLayout);
190 | void onMove(FriendsSlideLayout slideLayout);
191 | void onClose(FriendsSlideLayout slideLayout);
192 | }
193 |
194 | public OnStateChangeListener onStateChangeListener;
195 |
196 | public void setOnStateChangeListener(OnStateChangeListener onStateChangeListener) {
197 | this.onStateChangeListener = onStateChangeListener;
198 | }
199 | }
200 |
201 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ChatPage.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 | import androidx.appcompat.widget.Toolbar;
5 | import androidx.recyclerview.widget.LinearLayoutManager;
6 | import androidx.recyclerview.widget.RecyclerView;
7 |
8 | import android.annotation.SuppressLint;
9 | import android.content.Context;
10 | import android.content.Intent;
11 | import android.os.Build;
12 | import android.os.Bundle;
13 | import android.text.Editable;
14 | import android.text.TextWatcher;
15 | import android.view.MotionEvent;
16 | import android.view.View;
17 | import android.widget.Button;
18 | import android.widget.EditText;
19 | import android.widget.LinearLayout;
20 | import android.widget.TextView;
21 | import android.widget.Toast;
22 |
23 | import com.example.wechating.component.MsgAdapter;
24 | import com.example.wechating.domain.Msg;
25 | import com.github.xubo.statusbarutils.StatusBarUtils;
26 |
27 | import java.util.ArrayList;
28 | import java.util.List;
29 |
30 | public class ChatPage extends AppCompatActivity {
31 |
32 | List list = new ArrayList<>();
33 | RecyclerView recyclerView;
34 | Toolbar toolbar;
35 | MsgAdapter msgAdapter;
36 | Context context = ChatPage.this;
37 | EditText msg_say;
38 | Button emoji;
39 | TextView send;
40 | LinearLayout linearLayout;
41 | int lastx = 0;
42 | int lasty = 0;
43 | @Override
44 | protected void onCreate(Bundle savedInstanceState) {
45 | super.onCreate(savedInstanceState);
46 | setContentView(R.layout.chat_page);
47 | System.out.println("执行了charPage");
48 | recyclerView = findViewById(R.id.msg_list);
49 | toolbar = findViewById(R.id.msg_toolbar);
50 | msg_say = findViewById(R.id.msg_say);
51 | // emoji = findViewById(R.id.msg_emoji);
52 | send = findViewById(R.id.msg_send);
53 | linearLayout = findViewById(R.id.linear);
54 | initData();
55 | initView();
56 | initStatusBar();
57 | }
58 |
59 | @SuppressLint("ResourceAsColor")
60 | private void initStatusBar() {
61 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
62 | getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
63 | | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
64 | StatusBarUtils.setStatusBarColor(ChatPage.this, R.color.colorGray);
65 | }
66 | }
67 |
68 | private void initData() {
69 | // User user = (User) getIntent().getSerializableExtra("user_data");
70 | // toolbar.setTitle(user.getName());
71 | Intent intent=getIntent();
72 | toolbar.setTitle(intent.getStringExtra("nickname"));
73 |
74 | Msg msg = new Msg("hello", Msg.type_received);
75 | list.add(msg);
76 | Msg msg1 = new Msg("hello", Msg.type_sent);
77 | list.add(msg1);
78 |
79 |
80 | }
81 |
82 | private void initView() {
83 | LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
84 | recyclerView.setLayoutManager(linearLayoutManager);
85 | msgAdapter = new MsgAdapter(list, context);
86 | recyclerView.setAdapter(msgAdapter);
87 | toolbar.setNavigationOnClickListener(new View.OnClickListener() {
88 | @Override
89 | public void onClick(View v) {
90 | finish();
91 | }
92 | });
93 | // send.getLayoutParams().width = emoji.getLayoutParams().width;
94 | msg_say.addTextChangedListener(textWatcher);
95 | // WithSoftUp.addLayoutListener(findViewById(R.id.parent), linearLayout);
96 | send.setOnClickListener(new View.OnClickListener() {
97 | @Override
98 | public void onClick(View v) {
99 | if (msg_say.getEditableText().length() >= 1) {
100 | String content = msg_say.getText().toString();
101 | if (!"".equals(content)) {
102 | Msg msg = new Msg(content, Msg.type_sent);
103 | list.add(msg);
104 | Msg msg1 = new Msg(content, Msg.type_received);
105 | list.add(msg1);
106 | msgAdapter.notifyItemInserted(list.size() - 1);
107 | recyclerView.scrollToPosition(list.size() - 1);
108 | msg_say.setText("");
109 |
110 | }
111 | } else {
112 | Toast.makeText(context, "点击add", Toast.LENGTH_SHORT).show();
113 | }
114 | }
115 | });
116 | }
117 |
118 | TextWatcher textWatcher = new TextWatcher() {
119 | @Override
120 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
121 |
122 | }
123 |
124 | @Override
125 | public void onTextChanged(CharSequence s, int start, int before, int count) {
126 |
127 | }
128 |
129 | @SuppressLint("ResourceAsColor")
130 | @Override
131 | public void afterTextChanged(Editable s) {
132 | if (msg_say.getEditableText().length() >= 1) {
133 | send.setBackgroundResource(R.drawable.buttonbackground);
134 | send.setText("发送");
135 | // send.getLayoutParams().height = emoji.getLayoutParams().height;
136 | // send.getLayoutParams().width = emoji.getLayoutParams().width + 30;
137 | send.setTextColor(context.getResources().getColor(R.color.white));
138 | } else {
139 | send.setBackgroundResource(R.drawable.addbtn);
140 | // send.getLayoutParams().height = emoji.getLayoutParams().height;
141 | // send.getLayoutParams().width = emoji.getLayoutParams().width;
142 | send.setText("");
143 | }
144 | }
145 | };
146 |
147 | @Override
148 | public boolean dispatchTouchEvent(MotionEvent event) {
149 | int x = (int) event.getX();
150 | int y = (int) event.getY();
151 | switch (event.getAction()) {
152 | case MotionEvent.ACTION_DOWN:
153 | lastx = x;
154 | lasty = y;
155 | break;
156 | case MotionEvent.ACTION_UP:
157 | int curx = x;
158 | int cury = y;
159 |
160 | if (curx-lastx>300&&Math.abs(cury-lasty)<200)
161 | finish();
162 | break;
163 | }
164 | return super.dispatchTouchEvent(event);
165 | }
166 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/index/IndexFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.index;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.Menu;
8 | import android.view.MenuInflater;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 | import android.view.ViewGroup;
12 | import android.widget.BaseAdapter;
13 | import android.widget.ImageView;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 | import android.widget.Toast;
17 |
18 | import androidx.annotation.NonNull;
19 | import androidx.annotation.Nullable;
20 | import androidx.fragment.app.Fragment;
21 | import androidx.lifecycle.Observer;
22 | import androidx.lifecycle.ViewModelProvider;
23 |
24 | import com.example.wechating.AddFriendPage;
25 | import com.example.wechating.Index;
26 | import com.example.wechating.R;
27 | import com.example.wechating.component.MessageSlideLayout;
28 | import com.example.wechating.domain.Friends;
29 |
30 | import java.util.ArrayList;
31 | import java.util.HashSet;
32 | import java.util.Set;
33 |
34 | public class IndexFragment extends Fragment {
35 |
36 | private IndexViewModel indexViewModel;
37 | private ListView listView;
38 | private ArrayList mDatas;
39 | private ArrayList idList;
40 | private MyAdapter myAdapter;
41 | private Set sets = new HashSet();
42 |
43 | public View onCreateView(@NonNull LayoutInflater inflater,
44 | ViewGroup container, Bundle savedInstanceState) {
45 | indexViewModel =
46 | new ViewModelProvider(this).get(IndexViewModel.class);
47 | View root = inflater.inflate(R.layout.fragment_index, container, false);
48 | indexViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
49 | @Override
50 | public void onChanged(@Nullable String s) {
51 | }
52 | });
53 |
54 |
55 | listView=(ListView)root.findViewById(R.id.index_listView);
56 | initData();
57 | return root;
58 | }
59 |
60 | public void initData(){
61 | mDatas = new ArrayList<>();
62 | mDatas.add(new Friends("四狗子"));
63 | mDatas.add(new Friends("刘富贵"));
64 | mDatas.add(new Friends("梁朝伟"));
65 | mDatas.add(new Friends("杜琪峰"));
66 | mDatas.add(new Friends("大炮"));
67 | mDatas.add(new Friends("饿汉"));
68 | mDatas.add(new Friends("美羊羊"));
69 |
70 | myAdapter = new MyAdapter(getActivity().getApplicationContext(), mDatas);
71 | listView.setAdapter(myAdapter);
72 |
73 | idList=new ArrayList();
74 | idList.add(R.drawable.p12);
75 | idList.add(R.drawable.p8);
76 | idList.add(R.drawable.p7);
77 | idList.add(R.drawable.p4);
78 | idList.add(R.drawable.p3);
79 | idList.add(R.drawable.p5);
80 | idList.add(R.drawable.p9);
81 |
82 | }
83 |
84 | class MyAdapter extends BaseAdapter
85 | {
86 | private Context content;
87 | private ArrayList datas;
88 | private MyAdapter(Context context, ArrayList datas)
89 | {
90 | this.content = context;
91 | this.datas = datas;
92 | }
93 | @Override
94 | public int getCount() {
95 | return datas.size();
96 | }
97 |
98 | @Override
99 | public Object getItem(int position) {
100 | return datas.get(position);
101 | }
102 |
103 | @Override
104 | public long getItemId(int position) {
105 | return position;
106 | }
107 |
108 | @Override
109 | public View getView(int position, View convertView, ViewGroup parent) {
110 | ViewHolder viewHolder=null;
111 | if (convertView == null)
112 | {
113 | convertView = LayoutInflater.from(content).inflate(R.layout.message_item, null);
114 | viewHolder = new ViewHolder();
115 | viewHolder.contentView= (TextView) convertView.findViewById(R.id.content);
116 | viewHolder.menuView = (TextView) convertView.findViewById(R.id.message_menu);
117 | viewHolder.profile=(ImageView) convertView.findViewById(R.id.message_profile);
118 | convertView.setTag(viewHolder);
119 | }else {
120 | viewHolder = (ViewHolder) convertView.getTag();
121 | }
122 | viewHolder.profile.setImageResource(idList.get(position));
123 | viewHolder.contentView.setText(datas.get(position).getName());
124 |
125 | viewHolder.contentView.setOnClickListener(new View.OnClickListener() {
126 | @Override
127 | public void onClick(View v) {
128 | Toast.makeText(content, "click "+((TextView)v).getText(), Toast.LENGTH_SHORT).show();
129 | }
130 | });
131 | final Friends myContent = datas.get(position);
132 | final Integer p_id=idList.get(position);
133 |
134 | viewHolder.menuView.setOnClickListener(new View.OnClickListener() {
135 | @Override
136 | public void onClick(View v) {
137 | MessageSlideLayout slideLayout = (MessageSlideLayout) v.getParent();
138 | slideLayout.closeMenu(); //解决删除item后下一个item变成open状态问题
139 | datas.remove(myContent);
140 | idList.remove(p_id);
141 | notifyDataSetChanged();
142 | }
143 | });
144 |
145 | MessageSlideLayout slideLayout = (MessageSlideLayout) convertView;
146 | slideLayout.setOnStateChangeListener(new MyOnStateChangeListener());
147 |
148 |
149 | return convertView;
150 | }
151 |
152 | public MessageSlideLayout slideLayout = null;
153 | class MyOnStateChangeListener implements MessageSlideLayout.OnStateChangeListener
154 | {
155 | /**
156 | * 滑动后每次手势抬起保证只有一个item是open状态,加入sets集合中
157 | **/
158 | @Override
159 | public void onOpen(MessageSlideLayout layout) {
160 | slideLayout = layout;
161 | if (sets.size() > 0) {
162 | for (MessageSlideLayout s : sets) {
163 | s.closeMenu();
164 | sets.remove(s);
165 | }
166 | }
167 | sets.add(layout);
168 | }
169 |
170 | @Override
171 | public void onMove(MessageSlideLayout layout) {
172 | if (slideLayout != null && slideLayout !=layout)
173 | {
174 | slideLayout.closeMenu();
175 | }
176 | }
177 |
178 | @Override
179 | public void onClose(MessageSlideLayout layout) {
180 | if (sets.size() > 0) {
181 | sets.remove(layout);
182 | }
183 | if(slideLayout ==layout){
184 | slideLayout = null;
185 | }
186 | }
187 | }
188 | }
189 |
190 | static class ViewHolder
191 | {
192 | public TextView contentView;
193 | public TextView menuView;
194 | public ImageView profile;
195 | }
196 |
197 | }
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_mine.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
21 |
22 |
27 |
28 |
29 |
30 |
37 |
38 |
39 |
40 |
48 |
49 |
54 |
55 |
56 |
57 |
64 |
65 |
72 |
73 |
74 |
75 |
76 |
85 |
86 |
91 |
92 |
93 |
94 |
101 |
102 |
110 |
111 |
112 |
121 |
122 |
127 |
128 |
129 |
130 |
137 |
138 |
139 |
140 |
150 |
151 |
156 |
157 |
158 |
159 |
166 |
167 |
168 |
169 |
170 |
179 |
180 |
185 |
186 |
187 |
188 |
195 |
196 |
204 |
205 |
206 |
207 |
208 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/news/NewsFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.news;
2 |
3 | import android.content.Intent;
4 | import android.graphics.Color;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.Button;
10 | import android.widget.ImageView;
11 | import android.widget.ListView;
12 |
13 | import androidx.annotation.NonNull;
14 | import androidx.annotation.Nullable;
15 | import androidx.fragment.app.Fragment;
16 | import androidx.lifecycle.Observer;
17 | import androidx.lifecycle.ViewModelProvider;
18 | import androidx.recyclerview.widget.LinearLayoutManager;
19 | import androidx.recyclerview.widget.RecyclerView;
20 |
21 | import com.example.wechating.MainActivity;
22 | import com.example.wechating.MakeMomentPage;
23 | import com.example.wechating.R;
24 | import com.example.wechating.component.NewsAdapter;
25 | import com.example.wechating.domain.Friends;
26 | import com.google.android.material.appbar.AppBarLayout;
27 | import com.google.android.material.appbar.CollapsingToolbarLayout;
28 |
29 | import java.util.ArrayList;
30 | import java.util.List;
31 | import java.util.Random;
32 |
33 | public class NewsFragment extends Fragment implements View.OnClickListener {
34 |
35 | private NewsViewModel newsViewModel;
36 | private List list;
37 | private static NewsAdapter adapter;
38 | private ImageView goMakeMoment;
39 | private List profiles;
40 | private List nickname;
41 | private List> itemPictures;
42 | private List itemPicture;
43 | private List copyWriting;
44 | private List times;
45 | private static boolean flag=false;
46 |
47 |
48 |
49 | public View onCreateView(@NonNull LayoutInflater inflater,
50 | ViewGroup container, Bundle savedInstanceState) {
51 | newsViewModel =
52 | new ViewModelProvider(this).get(NewsViewModel.class);
53 | View root = inflater.inflate(R.layout.fragment_news, container, false);
54 | newsViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
55 | @Override
56 | public void onChanged(@Nullable String s) {
57 |
58 | }
59 | });
60 |
61 |
62 | AppBarLayout appBarLayout = root.findViewById(R.id.appBar);
63 | appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
64 | @Override
65 | public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {
66 | CollapsingToolbarLayout collapsingToolbar = root.findViewById(R.id.collapsing_toolbar);
67 | int color = Color.argb(200,0,0,0);
68 | collapsingToolbar.setCollapsedTitleTextColor(color);
69 | ImageView imageView = root.findViewById(R.id.image1);
70 | if (Math.abs(verticalOffset) >= appBarLayout.getTotalScrollRange()) { // 折叠状态
71 | collapsingToolbar.setTitle("朋友圈");
72 | imageView.setVisibility(View.GONE);
73 | } else { // 非折叠状态
74 | collapsingToolbar.setTitle("");
75 | imageView.setVisibility(View.VISIBLE);
76 | }
77 | }
78 | });
79 | initFriends();
80 | RecyclerView recyclerView = (RecyclerView) root.findViewById(R.id.recycler_view);
81 | LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity().getApplicationContext());
82 | recyclerView.setLayoutManager(layoutManager);
83 | adapter = new NewsAdapter(list,profiles,nickname,itemPictures,copyWriting,times);
84 | recyclerView.setAdapter(adapter);
85 |
86 |
87 | goMakeMoment=root.findViewById(R.id.camera_id);
88 | goMakeMoment.setOnClickListener(this);
89 |
90 | return root;
91 | }
92 |
93 | @Override
94 | public void onClick(View v) {
95 | Intent intent=new Intent(getActivity(), MakeMomentPage.class);
96 | startActivity(intent);
97 |
98 | }
99 |
100 |
101 |
102 | private void initFriends() {
103 | list=new ArrayList<>();
104 | if(flag)
105 | list.add(new Friends("陈冠希"));
106 | list.add(new Friends("四狗子"));
107 | list.add(new Friends("五娃"));
108 | list.add(new Friends("刘富贵"));
109 | list.add(new Friends("七娃"));
110 | list.add(new Friends("梁朝伟"));
111 | list.add(new Friends("亳州"));
112 | list.add(new Friends("杜琪峰"));
113 | list.add(new Friends("大炮"));
114 |
115 | nickname=new ArrayList<>();
116 | if(flag)
117 | nickname.add("陈冠希");
118 | nickname.add("四狗子");
119 | nickname.add("五娃");
120 | nickname.add("刘富贵");
121 | nickname.add("七娃");
122 | nickname.add("梁朝伟");
123 | nickname.add("亳州");
124 | nickname.add("杜琪峰");
125 | nickname.add("大炮");
126 |
127 | profiles=new ArrayList<>();//朋友圈好友的头像
128 | if(flag)
129 | profiles.add(R.drawable.p16);
130 | profiles.add(R.drawable.p12);
131 | profiles.add(R.drawable.p13);
132 | profiles.add(R.drawable.p8);
133 | profiles.add(R.drawable.p10);
134 | profiles.add(R.drawable.p7);
135 | profiles.add(R.drawable.p2);
136 | profiles.add(R.drawable.p4);
137 | profiles.add(R.drawable.p3);
138 |
139 | times=new ArrayList<>();//发布动态距离现在的时间
140 | if(flag)
141 | times.add(0);
142 | times.add(25);
143 | times.add(35);
144 | times.add(50);
145 | times.add(1);
146 | times.add(2);
147 | times.add(5);
148 | times.add(7);
149 | times.add(8);
150 |
151 |
152 |
153 | itemPictures=new ArrayList<>();
154 | itemPicture=new ArrayList<>();
155 | if(flag){
156 | itemPictures.add(itemPicture);
157 | }
158 |
159 | itemPicture=new ArrayList<>();
160 | itemPicture.add(R.drawable.pyq1);
161 | itemPictures.add(itemPicture);
162 |
163 | itemPicture=new ArrayList<>();
164 | itemPicture.add(R.drawable.pyq2_1);
165 | itemPicture.add(R.drawable.pyq2_2);
166 | itemPictures.add(itemPicture);
167 |
168 | itemPicture=new ArrayList<>();
169 | itemPicture.add(R.drawable.pyq3_1);
170 | itemPicture.add(R.drawable.pyq3_2);
171 | itemPictures.add(itemPicture);
172 |
173 | itemPicture=new ArrayList<>();
174 | itemPicture.add(R.drawable.pyq4_1);
175 | itemPicture.add(R.drawable.pyq4_2);
176 | itemPicture.add(R.drawable.pyq4_3);
177 | itemPictures.add(itemPicture);
178 |
179 | itemPicture=new ArrayList<>();
180 | itemPicture.add(R.drawable.pyq5_1);
181 | itemPicture.add(R.drawable.pyq5_2);
182 | itemPictures.add(itemPicture);
183 |
184 | itemPicture=new ArrayList<>();
185 | itemPicture.add(R.drawable.pyq6);
186 | itemPictures.add(itemPicture);
187 |
188 | itemPicture=new ArrayList<>();
189 | itemPicture.add(R.drawable.pyq7);
190 | itemPictures.add(itemPicture);
191 |
192 | itemPicture=new ArrayList<>();
193 | itemPicture.add(R.drawable.pyq8_1);
194 | itemPicture.add(R.drawable.pyq8_2);
195 | itemPictures.add(itemPicture);
196 |
197 |
198 | copyWriting=new ArrayList<>();
199 | if(flag)
200 | copyWriting.add("hello");
201 | copyWriting.add("又挂科了");
202 | copyWriting.add("今天辛苦了,犒劳自己一下");
203 | copyWriting.add("给大家推荐两部好看的电影,真心不错");
204 | copyWriting.add("今天天气真不错");
205 | copyWriting.add("两只都好可爱");
206 | copyWriting.add("有要打球的吗?没有我等一会儿再来问问");
207 | copyWriting.add("哪位大哥有爱奇艺会员,求借一下");
208 | copyWriting.add("风景真的好");
209 |
210 | }
211 |
212 | public static void update(){
213 | flag=true;
214 | adapter.notifyDataSetChanged();
215 | }
216 |
217 | }
218 |
219 |
220 |
221 |
222 |
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/component/SideBar.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.component;
2 |
3 |
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Canvas;
7 | import android.graphics.Paint;
8 | import android.util.AttributeSet;
9 | import android.view.MotionEvent;
10 |
11 | import com.example.wechating.R;
12 |
13 | //边框字母栏
14 |
15 | public class SideBar extends androidx.appcompat.widget.AppCompatTextView {
16 | private String[] letters = new String[]{"A", "B", "C", "D", "E", "F", "G", "H", "I",
17 | "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
18 | "W", "X", "Y", "Z", "#"};
19 | private Paint textPaint;
20 | private Paint bigTextPaint;
21 | private Paint scaleTextPaint;
22 |
23 | private Canvas canvas;
24 | private int itemH;
25 | private int w;
26 | private int h;
27 | /**
28 | * 普通情况下字体大小
29 | */
30 | float singleTextH;
31 | /**
32 | * 缩放离原始的宽度
33 | */
34 | private float scaleWidth;
35 | /**
36 | * 滑动的Y
37 | */
38 | private float eventY = 0;
39 | /**
40 | * 缩放的倍数
41 | */
42 | private int scaleSize = 1;
43 | /**
44 | * 缩放个数item,即开口大小
45 | */
46 | private int scaleItemCount = 6;
47 | private ISideBarSelectCallBack callBack;
48 |
49 | public SideBar(Context context) {
50 | this(context, null);
51 | }
52 |
53 | public SideBar(Context context, AttributeSet attrs) {
54 | this(context, attrs, 0);
55 | }
56 |
57 | public SideBar(Context context, AttributeSet attrs, int defStyleAttr) {
58 | super(context, attrs, defStyleAttr);
59 | init(attrs);
60 | }
61 |
62 | private void init(AttributeSet attrs) {
63 | if (attrs != null) {
64 | TypedArray ta = getContext().obtainStyledAttributes(attrs, R.styleable.SideBar);
65 | scaleSize = ta.getInteger(R.styleable.SideBar_scaleSize, 1);
66 | scaleItemCount = ta.getInteger(R.styleable.SideBar_scaleItemCount, 6);
67 | scaleWidth = ta.getDimensionPixelSize(R.styleable.SideBar_scaleWidth, dp(100));
68 | ta.recycle();
69 | }
70 | textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
71 | textPaint.setColor(getCurrentTextColor());
72 | textPaint.setTextSize(getTextSize());
73 | textPaint.setTextAlign(Paint.Align.CENTER);
74 | bigTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
75 | bigTextPaint.setColor(getCurrentTextColor());
76 | bigTextPaint.setTextSize(getTextSize() * (scaleSize + 3));
77 | bigTextPaint.setTextAlign(Paint.Align.CENTER);
78 | scaleTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
79 | scaleTextPaint.setColor(getCurrentTextColor());
80 | scaleTextPaint.setTextSize(getTextSize() * (scaleSize + 1));
81 | scaleTextPaint.setTextAlign(Paint.Align.CENTER);
82 | }
83 |
84 | public void setDataResource(String[] data) {
85 | letters = data;
86 | invalidate();
87 | }
88 |
89 | public void setOnStrSelectCallBack(ISideBarSelectCallBack callBack) {
90 | this.callBack = callBack;
91 | }
92 |
93 | /**
94 | * 设置字体缩放比例
95 | *
96 | * @param scale
97 | */
98 | public void setScaleSize(int scale) {
99 | scaleSize = scale;
100 | invalidate();
101 | }
102 |
103 | /**
104 | * 设置缩放字体的个数,即开口大小
105 | *
106 | * @param scaleItemCount
107 | */
108 | public void setScaleItemCount(int scaleItemCount) {
109 | this.scaleItemCount = scaleItemCount;
110 | invalidate();
111 | }
112 |
113 | private int dp(int px) {
114 | final float scale = getContext().getResources().getDisplayMetrics().density;
115 | return (int) (px * scale + 0.5f);
116 | }
117 |
118 | @Override
119 | public boolean onTouchEvent(MotionEvent event) {
120 | switch (event.getAction()) {
121 | case MotionEvent.ACTION_DOWN:
122 | case MotionEvent.ACTION_MOVE:
123 | if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
124 | eventY = event.getY();
125 | invalidate();
126 | return true;
127 | } else {
128 | eventY = 0;
129 | invalidate();
130 | break;
131 | }
132 | case MotionEvent.ACTION_CANCEL:
133 | eventY = 0;
134 | invalidate();
135 | return true;
136 | case MotionEvent.ACTION_UP:
137 | if (event.getX() > (w - getPaddingRight() - singleTextH - 10)) {
138 | eventY = 0;
139 | invalidate();
140 | return true;
141 | } else
142 | break;
143 | }
144 | return super.onTouchEvent(event);
145 | }
146 |
147 |
148 | @Override
149 | protected void onDraw(Canvas canvas) {
150 | this.canvas = canvas;
151 | DrawView(eventY);
152 | }
153 |
154 | private void DrawView(float y) {
155 | int currentSelectIndex = -1;
156 | if (y != 0) {
157 | for (int i = 0; i < letters.length; i++) {
158 | float currentItemY = itemH * i;
159 | float nextItemY = itemH * (i + 1);
160 | if (y >= currentItemY && y < nextItemY) {
161 | currentSelectIndex = i;
162 | if (callBack != null) {
163 | callBack.onSelectStr(currentSelectIndex, letters[i]);
164 | }
165 | //画大的字母
166 | Paint.FontMetrics fontMetrics = bigTextPaint.getFontMetrics();
167 | float bigTextSize = fontMetrics.descent - fontMetrics.ascent;
168 | canvas.drawText(letters[i], w - getPaddingRight() - scaleWidth - bigTextSize, singleTextH + itemH * i, bigTextPaint);
169 | }
170 | }
171 | }
172 | drawLetters(y, currentSelectIndex);
173 | }
174 |
175 | private void drawLetters(float y, int index) {
176 | //第一次进来没有缩放情况,默认画原图
177 | if (index == -1) {
178 | w = getMeasuredWidth();
179 | h = getMeasuredHeight();
180 | itemH = h / letters.length;
181 | Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
182 | singleTextH = fontMetrics.descent - fontMetrics.ascent;
183 | for (int i = 0; i < letters.length; i++) {
184 | canvas.drawText(letters[i], w - getPaddingRight(), singleTextH + itemH * i, textPaint);
185 | }
186 | //触摸的时候画缩放图
187 | } else {
188 | //遍历所有字母
189 | for (int i = 0; i < letters.length; i++) {
190 | //要画的字母的起始Y坐标
191 | float currentItemToDrawY = singleTextH + itemH * i;
192 | float centerItemToDrawY;
193 | if (index < i)
194 | centerItemToDrawY = singleTextH + itemH * (index + scaleItemCount);
195 | else
196 | centerItemToDrawY = singleTextH + itemH * (index - scaleItemCount);
197 | float delta = 1 - Math.abs((y - currentItemToDrawY) / (centerItemToDrawY - currentItemToDrawY));
198 | float maxRightX = w - getPaddingRight();
199 | //如果大于0,表明在y坐标上方
200 | scaleTextPaint.setTextSize(getTextSize() + getTextSize() * delta);
201 | float drawX = maxRightX - scaleWidth * delta;
202 | //超出边界直接花在边界上
203 | if (drawX > maxRightX)
204 | canvas.drawText(letters[i], maxRightX, singleTextH + itemH * i, textPaint);
205 | else
206 | canvas.drawText(letters[i], drawX, singleTextH + itemH * i, scaleTextPaint);
207 | }
208 | }
209 | }
210 |
211 | public interface ISideBarSelectCallBack {
212 | void onSelectStr(int index, String selectStr);
213 | }
214 |
215 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/example/wechating/ui/friends/FriendsFragment.java:
--------------------------------------------------------------------------------
1 | package com.example.wechating.ui.friends;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 | import android.widget.BaseAdapter;
10 | import android.widget.ImageView;
11 | import android.widget.ListView;
12 | import android.widget.TextView;
13 | import android.widget.Toast;
14 |
15 | import androidx.annotation.NonNull;
16 | import androidx.annotation.Nullable;
17 | import androidx.fragment.app.Fragment;
18 | import androidx.lifecycle.Observer;
19 | import androidx.lifecycle.ViewModelProvider;
20 |
21 | import com.example.wechating.ChatPage;
22 | import com.example.wechating.R;
23 | import com.example.wechating.component.SideBar;
24 | import com.example.wechating.component.FriendsSlideLayout;
25 | import com.example.wechating.domain.Friends;
26 |
27 | import java.util.ArrayList;
28 | import java.util.Collections;
29 | import java.util.HashSet;
30 | import java.util.Set;
31 |
32 | public class FriendsFragment extends Fragment {
33 |
34 | private FriendsViewModel friendsViewModel;
35 | private ListView listView;
36 | private SideBar sideBar;
37 | private ArrayList list;
38 | private ArrayList idList;
39 | private MyAdapter myAdapter;
40 | private Set sets = new HashSet();
41 | private static boolean flag=false;
42 |
43 |
44 | public View onCreateView(@NonNull LayoutInflater inflater,
45 | ViewGroup container, Bundle savedInstanceState) {
46 | friendsViewModel =
47 | new ViewModelProvider(this).get(FriendsViewModel.class);
48 | View root = inflater.inflate(R.layout.fragment_friends, container, false);
49 | friendsViewModel.getText().observe(getViewLifecycleOwner(), new Observer() {
50 | @Override
51 | public void onChanged(@Nullable String s) {
52 |
53 | }
54 | });
55 | listView = (ListView) root.findViewById(R.id.friends_listView);
56 | sideBar = (SideBar) root.findViewById(R.id.side_bar);
57 | initView();
58 | initData();
59 | return root;
60 | }
61 |
62 |
63 | private void initView() {
64 |
65 | sideBar.setOnStrSelectCallBack(new SideBar.ISideBarSelectCallBack() {
66 | @Override
67 | public void onSelectStr(int index, String selectStr) {
68 | for (int i = 0; i < list.size(); i++) {
69 | if (selectStr.equalsIgnoreCase(list.get(i).getFirstLetter())) {
70 | listView.setSelection(i); // 选择到首字母出现的位置
71 | return;
72 | }
73 | }
74 | }
75 | });
76 | }
77 |
78 |
79 |
80 |
81 | class MyAdapter extends BaseAdapter
82 | {
83 | private Context content;
84 | private ArrayList datas;
85 | private MyAdapter(Context context, ArrayList datas)
86 | {
87 | this.content = context;
88 | this.datas = datas;
89 | }
90 | @Override
91 | public int getCount() {
92 | return datas.size();
93 | }
94 |
95 | @Override
96 | public Object getItem(int position) {
97 | return datas.get(position);
98 | }
99 |
100 | @Override
101 | public long getItemId(int position) {
102 | return position;
103 | }
104 |
105 | @Override
106 | public View getView(int position, View convertView, ViewGroup parent) {
107 | ViewHolder viewHolder=null;
108 | final Friends friends = datas.get(position);
109 | final Integer p_id=idList.get(position);
110 |
111 | if (convertView == null)
112 | {
113 | convertView = LayoutInflater.from(content).inflate(R.layout.friends_item, null);
114 | viewHolder = new ViewHolder();
115 | viewHolder.nameView= (TextView) convertView.findViewById(R.id.name);
116 | viewHolder.catlogView= (TextView) convertView.findViewById(R.id.catalog);
117 | viewHolder.menuView = (TextView) convertView.findViewById(R.id.menu_friends);
118 | viewHolder.profile=(ImageView) convertView.findViewById(R.id.friends_profile);
119 | convertView.setTag(viewHolder);
120 | }else {
121 | viewHolder = (ViewHolder) convertView.getTag();
122 | }
123 | viewHolder.profile.setImageResource(idList.get(position));
124 | viewHolder.nameView.setText(datas.get(position).getName());
125 |
126 |
127 | //根据position获取首字母作为目录catalog
128 | String catalog = list.get(position).getFirstLetter();
129 |
130 | //如果当前位置等于该分类首字母的Char的位置 ,则认为是第一次出现
131 | if(position == getPositionForSection(catalog)){
132 | viewHolder.catlogView.setVisibility(View.VISIBLE);
133 | viewHolder.catlogView.setText(friends.getFirstLetter().toUpperCase());
134 | }else{
135 | viewHolder.catlogView.setVisibility(View.GONE);
136 | }
137 |
138 |
139 | String nickname=viewHolder.nameView.getText().toString();
140 | viewHolder.nameView.setOnClickListener(new View.OnClickListener() {
141 | @Override
142 | public void onClick(View v) {
143 | Toast.makeText(content, "click "+((TextView)v).getText(), Toast.LENGTH_SHORT).show();
144 | Intent intent=new Intent(getActivity(), ChatPage.class);
145 | intent.putExtra("nickname",nickname);
146 | startActivity(intent);
147 | }
148 | });
149 |
150 | viewHolder.menuView.setOnClickListener(new View.OnClickListener() {
151 | @Override
152 | public void onClick(View v) {
153 | FriendsSlideLayout slideLayout = (FriendsSlideLayout) v.getParent();
154 | slideLayout.closeMenu(); //解决删除item后下一个item变成open状态问题
155 | datas.remove(friends);
156 | idList.remove(p_id);
157 | notifyDataSetChanged();
158 | }
159 | });
160 |
161 | FriendsSlideLayout slideLayout = (FriendsSlideLayout) convertView;
162 | slideLayout.setOnStateChangeListener(new MyOnStateChangeListener());
163 |
164 |
165 | return convertView;
166 | }
167 |
168 | public FriendsSlideLayout slideLayout = null;
169 | class MyOnStateChangeListener implements FriendsSlideLayout.OnStateChangeListener
170 | {
171 | /**
172 | * 滑动后每次手势抬起保证只有一个item是open状态,加入sets集合中
173 | **/
174 | @Override
175 | public void onOpen(FriendsSlideLayout layout) {
176 | slideLayout = layout;
177 | if (sets.size() > 0) {
178 | for (FriendsSlideLayout s : sets) {
179 | s.closeMenu();
180 | sets.remove(s);
181 | }
182 | }
183 | sets.add(layout);
184 | }
185 |
186 | @Override
187 | public void onMove(FriendsSlideLayout layout) {
188 | if (slideLayout != null && slideLayout !=layout)
189 | {
190 | slideLayout.closeMenu();
191 | }
192 | }
193 |
194 | @Override
195 | public void onClose(FriendsSlideLayout layout) {
196 | if (sets.size() > 0) {
197 | sets.remove(layout);
198 | }
199 | if(slideLayout ==layout){
200 | slideLayout = null;
201 | }
202 | }
203 | }
204 |
205 | public int getPositionForSection(String catalog) {
206 | for (int i = 0; i < getCount(); i++) {
207 | String sortStr = list.get(i).getFirstLetter();
208 | if (catalog.equalsIgnoreCase(sortStr)) {
209 | return i;
210 | }
211 | }
212 | return -1;
213 | }
214 | }
215 | static class ViewHolder
216 | {
217 | public TextView catlogView;
218 | public TextView menuView;
219 | public TextView nameView;
220 | public ImageView profile;
221 | }
222 |
223 | private void initData() {
224 | list=new ArrayList<>();
225 | list.add(new Friends("四狗子"));
226 | list.add(new Friends("五娃"));
227 | list.add(new Friends("刘富贵"));
228 | list.add(new Friends("七娃"));
229 | list.add(new Friends("梁朝伟"));
230 | list.add(new Friends("亳州"));
231 | list.add(new Friends("杜琪峰"));
232 | list.add(new Friends("白嫖狗"));
233 | list.add(new Friends("大炮"));
234 | list.add(new Friends("二娃"));
235 | list.add(new Friends("饿汉"));
236 | list.add(new Friends("三娃"));
237 | list.add(new Friends("美羊羊"));
238 | list.add(new Friends("蜘蛛侠"));
239 | list.add(new Friends("渣渣辉"));
240 |
241 | if(flag)
242 | list.add(new Friends("张三"));
243 | Collections.sort(list); // 对list进行排序,需要让User实现Comparable接口重写compareTo方法
244 | myAdapter = new MyAdapter(getActivity().getApplicationContext(), list);
245 | listView.setAdapter(myAdapter);
246 |
247 | idList=new ArrayList<>();
248 | idList.add(R.drawable.p1);
249 | idList.add(R.drawable.p2);
250 | idList.add(R.drawable.p3);
251 | idList.add(R.drawable.p4);
252 | idList.add(R.drawable.p5);
253 | idList.add(R.drawable.p6);
254 | idList.add(R.drawable.p7);
255 | idList.add(R.drawable.p8);
256 | idList.add(R.drawable.p9);
257 | idList.add(R.drawable.p10);
258 | idList.add(R.drawable.p11);
259 | idList.add(R.drawable.p12);
260 | idList.add(R.drawable.p13);
261 | if(flag)
262 | idList.add(R.drawable.p17);
263 | idList.add(R.drawable.p18);
264 | idList.add(R.drawable.p17);
265 |
266 | }
267 |
268 | public static void update(){
269 | flag=true;
270 | }
271 |
272 | }
--------------------------------------------------------------------------------