diff --git a/CODE/RommteStory/.gitignore b/CODE/RommteStory/.gitignore new file mode 100644 index 0000000..aa724b7 --- /dev/null +++ b/CODE/RommteStory/.gitignore @@ -0,0 +1,15 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties diff --git a/CODE/RommteStory/.idea/.gitignore b/CODE/RommteStory/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/CODE/RommteStory/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/CODE/RommteStory/.idea/compiler.xml b/CODE/RommteStory/.idea/compiler.xml new file mode 100644 index 0000000..fb7f4a8 --- /dev/null +++ b/CODE/RommteStory/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/.idea/dbnavigator.xml b/CODE/RommteStory/.idea/dbnavigator.xml new file mode 100644 index 0000000..210ee48 --- /dev/null +++ b/CODE/RommteStory/.idea/dbnavigator.xml @@ -0,0 +1,407 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/.idea/deploymentTargetDropDown.xml b/CODE/RommteStory/.idea/deploymentTargetDropDown.xml new file mode 100644 index 0000000..ccacf5f --- /dev/null +++ b/CODE/RommteStory/.idea/deploymentTargetDropDown.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/.idea/gradle.xml b/CODE/RommteStory/.idea/gradle.xml new file mode 100644 index 0000000..0625cbe --- /dev/null +++ b/CODE/RommteStory/.idea/gradle.xml @@ -0,0 +1,21 @@ + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/.idea/misc.xml b/CODE/RommteStory/.idea/misc.xml new file mode 100644 index 0000000..c34d6b7 --- /dev/null +++ b/CODE/RommteStory/.idea/misc.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/.gitignore b/CODE/RommteStory/app/.gitignore new file mode 100644 index 0000000..42afabf --- /dev/null +++ b/CODE/RommteStory/app/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/CODE/RommteStory/app/build.gradle b/CODE/RommteStory/app/build.gradle new file mode 100644 index 0000000..45a406a --- /dev/null +++ b/CODE/RommteStory/app/build.gradle @@ -0,0 +1,58 @@ +plugins { + id 'com.android.application' +} + +android { + compileSdk 32 + + defaultConfig { + applicationId "com.lh.app" + minSdk 21 + targetSdk 32 + versionCode 1 + versionName "1.0" + + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' + } + } + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + buildFeatures { + viewBinding true + } +} + +dependencies { + + implementation 'androidx.appcompat:appcompat:1.3.0' + implementation 'com.google.android.material:material:1.4.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.4' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.3.1' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.1' + implementation 'androidx.navigation:navigation-fragment:2.3.5' + implementation 'androidx.navigation:navigation-ui:2.3.5' + implementation 'com.google.android.gms:play-services-location:18.0.0' + testImplementation 'junit:junit:4.13.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.3' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' + + //noinspection GradleCompatible + implementation 'androidx.recyclerview:recyclerview:1.2.1'//添加RecycleView库依赖 + //图像类库 + implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' + + implementation 'com.google.android.gms:play-services-location:21.0.1' + //图片加载 + implementation 'com.github.bumptech.glide:glide:4.15.1' // 使用最新版本 + annotationProcessor 'com.github.bumptech.glide:compiler:4.15.1' + //高德地图 + implementation 'com.amap.api:3dmap-location-search:latest.integration' +} \ No newline at end of file diff --git a/CODE/RommteStory/app/proguard-rules.pro b/CODE/RommteStory/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/CODE/RommteStory/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/CODE/RommteStory/app/src/androidTest/java/com/lh/app/ExampleInstrumentedTest.java b/CODE/RommteStory/app/src/androidTest/java/com/lh/app/ExampleInstrumentedTest.java new file mode 100644 index 0000000..23ee024 --- /dev/null +++ b/CODE/RommteStory/app/src/androidTest/java/com/lh/app/ExampleInstrumentedTest.java @@ -0,0 +1,26 @@ +package com.lh.app; + +import android.content.Context; + +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.ext.junit.runners.AndroidJUnit4; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import static org.junit.Assert.*; + +/** + * Instrumented test, which will execute on an Android device. + * + * @see Testing documentation + */ +@RunWith(AndroidJUnit4.class) +public class ExampleInstrumentedTest { + @Test + public void useAppContext() { + // Context of the app under test. + Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); + assertEquals("com.lh.app", appContext.getPackageName()); + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/AndroidManifest.xml b/CODE/RommteStory/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..4c57875 --- /dev/null +++ b/CODE/RommteStory/app/src/main/AndroidManifest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/ic_launcher-playstore.png b/CODE/RommteStory/app/src/main/ic_launcher-playstore.png new file mode 100644 index 0000000..17cefac Binary files /dev/null and b/CODE/RommteStory/app/src/main/ic_launcher-playstore.png differ diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/MainActivity.java b/CODE/RommteStory/app/src/main/java/com/lh/app/MainActivity.java new file mode 100644 index 0000000..b69808c --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/MainActivity.java @@ -0,0 +1,182 @@ +package com.lh.app; + +import android.annotation.SuppressLint; +import android.os.Bundle; +import android.util.Log; +import android.view.Menu; +import android.view.MenuItem; + +import com.lh.app.ui.honor.HonorFragment; +import com.lh.app.ui.detail.DetailFragment; +import com.lh.app.ui.memo.MemoFragment; +import com.lh.app.ui.mine.MineFragment; +import com.google.android.material.bottomnavigation.BottomNavigationView; + +import androidx.annotation.NonNull; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentPagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import com.lh.app.databinding.ActivityMainBinding; + +import java.util.ArrayList; + +public class MainActivity extends AppCompatActivity { + + private ActivityMainBinding binding; + BottomNavigationView navView; + private ViewPager mViewPager; + + //设置顶部菜单栏 + ActionBar actionBar; + // + public static boolean isShowViewPage_memo = false; + public static boolean isShowViewPage_honor = false; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + Log.d("MainActivity","onCreate"); + + actionBar = getSupportActionBar(); + assert actionBar != null; + actionBar.setTitle(R.string.title_detail); + + binding = ActivityMainBinding.inflate(getLayoutInflater()); + setContentView(binding.getRoot()); + + addUi(); + addUiListener(); + initPageAdapter(); + } + + @Override + protected void onStart() { + super.onStart(); + if(isShowViewPage_memo){ + mViewPager.setCurrentItem(1); + isShowViewPage_memo = false; + } + if(isShowViewPage_honor){ + mViewPager.setCurrentItem(2); + isShowViewPage_honor = false; + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + Log.d("MainActivity","onDestroy"); + + } + + //添加组件及变量声明 + private void addUi() { + navView = findViewById(R.id.nav_view); + mViewPager = findViewById(R.id.mViewPager); + } + + //初始化页面监听器 + private void initPageAdapter() { + //Fragment列表,将fragment放入列表中,放入mPagerAdapter + final ArrayList fgLists = new ArrayList<>(4); + fgLists.add(new DetailFragment()); + fgLists.add(new MemoFragment()); + fgLists.add(new HonorFragment()); + fgLists.add(new MineFragment()); + FragmentPagerAdapter mPagerAdapter = new FragmentPagerAdapter(getSupportFragmentManager()) { + @Override + public Fragment getItem(int position) { + return fgLists.get(position); + } + + @Override + public int getCount() { + return fgLists.size(); + } + }; + mViewPager.setAdapter(mPagerAdapter); + //设置预加载页面数量的方法 + mViewPager.setOffscreenPageLimit(1); + } + + //添加组件监听器 + private void addUiListener() { + navView.setOnNavigationItemSelectedListener(mOnNavigationItemSelectedListener); + mViewPager.addOnPageChangeListener(onPageChangeListener); + } + + //底部导航栏监听器 + @SuppressLint("NonConstantResourceId") + private final BottomNavigationView.OnNavigationItemSelectedListener mOnNavigationItemSelectedListener = new BottomNavigationView.OnNavigationItemSelectedListener() { + @Override + public boolean onNavigationItemSelected(@NonNull MenuItem item) { + // 清除之前的选中状态 + Menu menu = navView.getMenu(); + for (int i = 0; i < menu.size(); i++) { + MenuItem menuItem = menu.getItem(i); + menuItem.setChecked(false); + } + switch (item.getItemId()) { + case R.id.navigation_detail: + mViewPager.setCurrentItem(0); + item.setChecked(true); + break; + case R.id.navigation_memo: + mViewPager.setCurrentItem(1); + item.setChecked(true); + break; + case R.id.navigation_communicate: + mViewPager.setCurrentItem(2); + item.setChecked(true); + break; + case R.id.navigation_mine: + mViewPager.setCurrentItem(3); + item.setChecked(true); + break; + } + return false; + } + }; + //页面改变监听器 + private final ViewPager.OnPageChangeListener onPageChangeListener = new ViewPager.OnPageChangeListener() { + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + //在滑动中 + + } + + @Override + public void onPageSelected(int position) { + actionBar.setDisplayHomeAsUpEnabled(false); + //写滑动页面后做的事,使每一个fragment与一个page相对应 + switch (position) { + case 0: + navView.setSelectedItemId(R.id.navigation_detail); + actionBar.setTitle(R.string.title_detail); + break; + case 1: + navView.setSelectedItemId(R.id.navigation_memo); + actionBar.setTitle(R.string.title_memo); + break; + case 2: + navView.setSelectedItemId(R.id.navigation_communicate); + actionBar.setTitle(R.string.title_honor); + break; + case 3: + navView.setSelectedItemId(R.id.navigation_mine); + actionBar.setTitle(R.string.title_mine); + break; + } + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + }; + +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/MyApplication.java b/CODE/RommteStory/app/src/main/java/com/lh/app/MyApplication.java new file mode 100644 index 0000000..b3a745f --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/MyApplication.java @@ -0,0 +1,53 @@ +package com.lh.app; + +import android.app.Application; +import android.content.res.Configuration; +import android.util.Log; + +import androidx.annotation.NonNull; + +import java.util.HashMap; + +/** + * Created by on . + */ +public class MyApplication extends Application { + private static MyApplication mApp; + //声明一个公共的信息映射对象,可当全局变量使用 + public HashMap infoMap = new HashMap<>(); + public static RoommateDBHelper mHelper; + //得到Application唯一实例 + public static MyApplication getInstance(){ + return mApp; + } + + //在App启用时调用 + @Override + public void onCreate() { + super.onCreate(); + mApp = this; + Log.d("ning","MyApplication onCreate"); + + mHelper = RoommateDBHelper.getInstance(this); + //打开数据库帮助器读写连接 + mHelper.openWriteLink(); + mHelper.openReadLink(); + + } + + //在App终止时调用 + @Override + public void onTerminate() { + super.onTerminate(); + Log.d("ning","MyApplication onTerminate"); + //关闭数据库连接 + mHelper.closeLink(); + } + + //配置改变时被调用,如:横屏变竖屏 + @Override + public void onConfigurationChanged(@NonNull Configuration newConfig) { + super.onConfigurationChanged(newConfig); + Log.d("ning","MyApplication onConfigurationChanged"); + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/RoommateDBHelper.java b/CODE/RommteStory/app/src/main/java/com/lh/app/RoommateDBHelper.java new file mode 100644 index 0000000..63f6b69 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/RoommateDBHelper.java @@ -0,0 +1,360 @@ +package com.lh.app; + +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.util.Log; + +import com.lh.app.ui.detail.Roommate; +import com.lh.app.ui.honor.Honor; +import com.lh.app.ui.memo.Memo; + +import java.util.ArrayList; +import java.util.List; + +public class RoommateDBHelper extends SQLiteOpenHelper { + private static final String DB_NAME = "roommate.db"; + private static final int DB_VERSION = 1; + private static final String TABLE_NAME_ROOMMATE_INFO = "roommate_info";//舍友信息表 + private static final String TABLE_NAME_ROOMMATE_MEMO = "roommate_memo";//舍友备忘录表 + private static final String TABLE_NAME_ROOMMATE_HONOR = "roommate_honor";//舍友大事记表 + private static RoommateDBHelper mHelper = null; + private SQLiteDatabase mRDB = null;//钥匙,用来读 + private SQLiteDatabase mWDB = null;//钥匙,用来写 + + private RoommateDBHelper(Context context){ + //向父类方法传参,上下文、数据库名、游标、版本号 + super(context,DB_NAME,null,DB_VERSION); + } + + //利用单例模式去获取数据库帮助库的唯一实例 + public static RoommateDBHelper getInstance(Context context){ + if (mHelper==null){ + mHelper = new RoommateDBHelper(context); + } + return mHelper; + } + + public static String getTableNameRoommateInfo() { + return TABLE_NAME_ROOMMATE_INFO; + } + + public static String getTableNameRoommateMemo() { + return TABLE_NAME_ROOMMATE_MEMO; + } + + //打开数据库的读连接 + public SQLiteDatabase openReadLink(){ + if (mRDB==null||!mRDB.isOpen()){ + mRDB = mHelper.getReadableDatabase(); + } + return mRDB; + } + + //打开数据库的写连接 + public SQLiteDatabase openWriteLink(){ + if (mWDB==null||!mWDB.isOpen()){ + mWDB = mHelper.getWritableDatabase(); + } + return mWDB; + } + + //关闭数据库连接 + public void closeLink(){ + //关闭读链接 + if (mRDB!=null&&mRDB.isOpen()){ + mRDB.close(); + mRDB = null; + } + //关闭写连接 + if (mWDB!=null&&mWDB.isOpen()){ + mWDB.close(); + mWDB = null; + } + } + + //创建数据库,执行建表语句 + @Override + public void onCreate(SQLiteDatabase db) { + //建表语句 + String sql_01 = "create table if not exists "+ TABLE_NAME_ROOMMATE_INFO +" (" + + "_id integer primary key autoincrement not null," + + "name varchar not null," + + "id varchar not null,"+ + "height long not null," + + "weight float not null," + + "married integer not null,"+ + "birthday varchar not null,"+ + "hobby varchar not null,"+ + "position integer not null);";//记录在屏幕上位置 + + String sql_02 = "create table if not exists "+ TABLE_NAME_ROOMMATE_MEMO +" (" + + "_id integer primary key autoincrement not null," + + "name varchar not null," + + "title varchar not null," + + "content varchar not null," + + "date varchar not null,"+ + "isDelete int not null,"+//是否是被删除记录(是1,否0) + "isRevise int not null);";//是否是被修改记录(是1,否0) + + String sql_03 = "create table if not exists "+ TABLE_NAME_ROOMMATE_HONOR +" (" + + "_id integer primary key autoincrement not null," + + "imagePath varchar not null," + + "content varchar not null);";//是否是被修改记录(是1,否0) + //建表 + db.execSQL(sql_01); + db.execSQL(sql_02); + db.execSQL(sql_03); + } + + //数据库版本变化时执行 + @Override + public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { + /* String sql = "alter table "+ TABLE_NAME_ROOMMATE_INFO +" add column phone varchar;"; + db.execSQL(sql);*/ + } + + /** + * 添加 + * */ + //向指定表中添加一行数据 + public long insert(String table_name,ContentValues values){ + if (table_name.equals(TABLE_NAME_ROOMMATE_INFO) || table_name.equals(TABLE_NAME_ROOMMATE_MEMO)) + //若第三个参数values不为null,并且元素个数大于0,可以吧第二个参数置为null + //返回行号,若为-1,表示添加失败 + return mWDB.insert(table_name,null,values); + else return -1; + } + + /** + * 删除 + * */ + //通过名字删除舍友信息表数据 + public long deleteByName(String name){ + //返回删除的行数 + return mWDB.delete(TABLE_NAME_ROOMMATE_INFO,"name=?",new String[]{name}); + //mWDB.delete(TABLE_NAME,"name=? and age=?",new String[]{name,age}); + } + //清空指定表内容 + public long deleteAll(String table_name){ + //删除所有,返回删除的行数 + return mWDB.delete(table_name,"1=1",null); + } + //删除舍友备忘录表中指定数据 + public long deleteMemoByType(Memo memo, boolean isDelete, boolean isRevise){ + String name = memo.getName(); + String title = memo.getTitle(); + String content = memo.getContent(); + String date = memo.getDate(); + String INT_isDelete = isDelete?"1":"0"; + String INT_isRevise = isRevise?"1":"0"; + //返回删除的行数 + return mWDB.delete(TABLE_NAME_ROOMMATE_MEMO, + "name=? and title=? and content=? and date=? and isDelete=? and isRevise=?", + new String[]{name,title,content,date,INT_isDelete,INT_isRevise}); + } + //删除舍友备忘录中指定类型全部数据 + public long deleteMemoAllType(boolean isDelete,boolean isRevise){ + String INT_isDelete = isDelete?"1":"0"; + String INT_isRevise = isRevise?"1":"0"; + //返回删除的行数 + return mWDB.delete(TABLE_NAME_ROOMMATE_MEMO, "isDelete=? and isRevise=?", new String[]{INT_isDelete,INT_isRevise}); + } + + /** + * 更新 + * */ + //更新室友表中数据 + public long update_roommateInfo(ContentValues values,String name){ + //返回更改的行数 + return mWDB.update(TABLE_NAME_ROOMMATE_INFO,values,"name=?",new String[]{name}); + } + //更新室友备忘录中显示数据的状态 + public long update_roommateMemo(Memo memo,boolean isDelete,boolean isRevise){ + ContentValues values = new ContentValues(); + values.put("name",memo.getName()); + values.put("title",memo.getTitle()); + values.put("content",memo.getContent()); + values.put("date",memo.getDate()); + values.put("isDelete", isDelete); + values.put("isRevise", isRevise); + //返回更改的行数 + return mWDB.update(TABLE_NAME_ROOMMATE_MEMO,values, + "name=? and title=? and content=? and date=? and isDelete=? and isRevise=?", + new String[]{memo.getName(),memo.getTitle(),memo.getContent(),memo.getDate(),"0","0"}); + } + //更新室友备忘录中显示数据的状态为被删除 + public void update_roommateAllMemoToDelete(){ + //先查询备忘录中显示的数据 + List memoList = query_roommateMemoByType(false,false); + //循环遍历列表,将其类型改为删除 + for (Memo memo:memoList){ + long row = update_roommateMemo(memo,true,false); + Log.d("UpdateMemoTable","删除备忘录"+row+"条"); + } + } + + /** + * 查询 + * */ + //查询室友信息全部数据 + public List query_roommateInfo_All(){ + List list = new ArrayList<>(); + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_INFO,null,null,null,null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + Roommate roommate = new Roommate(); + roommate.setName(cursor.getString(1)); + roommate.setId(cursor.getString(2)); + roommate.setHeight(cursor.getLong(3)); + roommate.setWeight(cursor.getFloat(4)); + //Sqlite没有布尔类型,用0表示false,用1表示true + roommate.setMarried(cursor.getInt(5) != 0); + roommate.setBirthday(cursor.getString(6)); + roommate.setHobby(cursor.getString(7)); + list.add(roommate); + } + cursor.close(); + return list; + } + //返回舍友信息表中所有舍友姓名列表 + public List query_roommateName(){ + List list = new ArrayList<>(); + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_INFO, new String[]{"name"},null,null,null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + String name; + name = cursor.getString(0); + list.add(name); + } + cursor.close(); + return list; + } + //通过名字查询指定室友信息数据 + public Roommate query_roommateInfo_ByName(String name){ + Roommate roommate = new Roommate(); + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_INFO,null, + "name=?",new String[]{name}, + null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + roommate.setName(cursor.getString(1)); + roommate.setId(cursor.getString(2)); + roommate.setHeight(cursor.getLong(3)); + roommate.setWeight(cursor.getFloat(4)); + //Sqlite没有布尔类型,用0表示false,用1表示true + roommate.setMarried(cursor.getInt(5) != 0); + roommate.setBirthday(cursor.getString(6)); + roommate.setHobby(cursor.getString(7)); + } + cursor.close(); + return roommate; + } + //返回室友信息表是否为空 + public Boolean query_roommateInfo_isEmpty(){ + List list = new ArrayList<>(); + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_INFO,null,null,null,null,null,null); + if (cursor.getCount()==0) return true; + + cursor.close(); + return false; + } + //查询室友名在屏幕上位置 + public int query_roommate_position(String name){ + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_INFO,new String[]{"position"}, + "name=?",new String[]{name}, null,null,null); + //使游标移到第一个位置 + cursor.moveToFirst(); + return cursor.getInt(0); + } + + //查询室友备忘录中指定类型数据 + //参数(1,1)表示:查询被修改过的数据;(1,0)表示:查询被删除数据:(0,0)表示:查询要显示的数据;(0,1)表示:查询增加数据 + public List query_roommateMemoByType(boolean isDelete,boolean isRevise){ + List list = new ArrayList<>(); + String INT_isDelete = isDelete?"1":"0"; + String INT_isRevise = isRevise?"1":"0"; + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_MEMO,null,"isDelete=? and isRevise=?",new String[]{INT_isDelete,INT_isRevise},null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + Memo memo = new Memo(cursor.getString(1),cursor.getString(2), + cursor.getString(3),cursor.getString(4)); + list.add(memo); + } + cursor.close(); + return list; + } + //查询室友备忘录指定数据 + public Memo query_roommateMemo_ByDate(String name,String title,String content,String date){ + Memo memo = null; + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_MEMO,null, + "name=? title=? and content=? and date=?",new String[]{name,title,content,date}, + null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + memo = new Memo(cursor.getString(1),cursor.getString(2), + cursor.getString(3),cursor.getString(4)); + } + cursor.close(); + return memo; + } + //查询备忘录指定类型行数 + //参数(1,1)表示:查询被修改过的数据;(1,0)表示:查询被删除数据:(0,0)表示:查询要显示的数据;(0,1)表示:查询增加数据 + public int query_roommateMemo_rowsNumByType(boolean isDelete, boolean isRevise){ + List list = new ArrayList<>(); + String INT_isDelete = isDelete?"1":"0"; + String INT_isRevise = isRevise?"1":"0"; + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_MEMO,null,"isDelete=? and isRevise=?",new String[]{INT_isDelete,INT_isRevise},null,null,null); + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + Memo memo = new Memo(cursor.getString(1),cursor.getString(2), + cursor.getString(3),cursor.getString(4)); + list.add(memo); + } + cursor.close(); + return list.size(); + } + + /** + * 大事记表的操作 + * */ + //插入大事记表数据 + public long insert_honor(Honor honor){ + ContentValues values = new ContentValues(); + values.put("imagePath",honor.getImageLocation()); + values.put("content",honor.getContent()); + //若第三个参数values不为null,并且元素个数大于0,可以吧第二个参数置为null + //返回行号,若为-1,表示添加失败 + return mWDB.insert(TABLE_NAME_ROOMMATE_HONOR,null,values); + } + //查询大事记全部数据 + public List query_honor_All(){ + List honorList = new ArrayList<>(); + //返回结果集的游标 + Cursor cursor = mRDB.query(TABLE_NAME_ROOMMATE_HONOR,null,null,null,null,null,null); + + //循环取出游标指向的每条数据 + while (cursor.moveToNext()){ + Honor honor = new Honor(); + honor.setImageLocation(cursor.getString(1)); + honor.setContent(cursor.getString(2)); + honorList.add(honor); + } + cursor.close(); + return honorList; + } + //删除大事记指定数据 + public long delete_honorByLocation(String imagePath){ + return mWDB.delete(TABLE_NAME_ROOMMATE_HONOR, "imagePath=?", new String[]{imagePath}); + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/tool/CircleImageView.java b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/CircleImageView.java new file mode 100644 index 0000000..8428181 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/CircleImageView.java @@ -0,0 +1,75 @@ +package com.lh.app.tool; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; + +import androidx.annotation.Nullable; +import androidx.appcompat.widget.AppCompatImageView; + +public class CircleImageView extends AppCompatImageView { + + //画笔 + private Paint mPaint; + //圆形图片的半径 + private int mRadius; + //图片的宿放比例 + private float mScale; + + public CircleImageView(Context context) { + super(context); + } + + public CircleImageView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CircleImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + //由于是圆形,宽高应保持一致 + int size = Math.min(getMeasuredWidth(), getMeasuredHeight()); + mRadius = size / 2; + setMeasuredDimension(size, size); + } + + @SuppressLint("DrawAllocation") + @Override + protected void onDraw(Canvas canvas) { + + mPaint = new Paint(); + + Drawable drawable = getDrawable(); + + if (null != drawable) { + Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap(); + + //初始化BitmapShader,传入bitmap对象 + BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + //计算缩放比例 + mScale = (mRadius * 2.0f) / Math.min(bitmap.getHeight(), bitmap.getWidth()); + + Matrix matrix = new Matrix(); + matrix.setScale(mScale, mScale); + bitmapShader.setLocalMatrix(matrix); + mPaint.setShader(bitmapShader); + //画圆形,指定好坐标,半径,画笔 + canvas.drawCircle(mRadius, mRadius, mRadius, mPaint); + } else { + super.onDraw(canvas); + } + } + +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ImageUtils.java b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ImageUtils.java new file mode 100644 index 0000000..da83cf3 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ImageUtils.java @@ -0,0 +1,112 @@ +package com.lh.app.tool; + +import android.content.ContentUris; +import android.content.Context; +import android.database.Cursor; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.provider.MediaStore; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +public class ImageUtils { + //uri转bitmap + public static Bitmap uriToBitmap(Context context, Uri uri){ + if (uri == null) return null; + Bitmap bitmap = null; + try { + // decodeStream()可以将output_image.jpg解析成Bitmap对象。 + bitmap = BitmapFactory.decodeStream(context.getContentResolver().openInputStream(uri)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } + return bitmap; + } + + public static String getRealPathFromUri(Context context, Uri uri) { + if (uri == null) { + return null; + } + + // 检查Uri是否是文件类型的Uri + if ("file".equalsIgnoreCase(uri.getScheme())) { + return uri.getPath(); + } + + // 检查Uri是否是Content类型的Uri + if ("content".equalsIgnoreCase(uri.getScheme())) { + String[] projection = { MediaStore.Images.Media.DATA }; + Cursor cursor = null; + try { + cursor = context.getContentResolver().query(uri, projection, null, null, null); + if (cursor != null && cursor.moveToFirst()) { + int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA); + return cursor.getString(columnIndex); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + if (cursor != null) { + cursor.close(); + } + } + } + + return null; + } + public static Bitmap stringToBitmap(String filePath) { + if (filePath == null || filePath.isEmpty()) { + return null; + } + File file = new File(filePath); + if (!file.exists()) { + return null; + } + return BitmapFactory.decodeFile(filePath); + } + /*** + * 通过文件路径加载 Bitmap 图片 + * @param filePath 路径 + * @return Bitmap 图片 + */ + public static Bitmap loadBitmapFromPath(String filePath) { + // 创建一个文件对象 + File imageFile = new File(filePath); + + // 检查文件是否存在 + if (imageFile.exists()) { + // 从文件路径加载 Bitmap + return BitmapFactory.decodeFile(imageFile.getAbsolutePath()); + } else { + // 文件不存在,返回 null 或者处理错误 + return null; + } + } + // 临时创建图片文件 + public static File createImageFile(Context context) { + String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date()); + String fileName = "JPEG_" + timeStamp + ".jpg"; + File storageDir = context.getExternalCacheDir(); // 使用缓存目录,避免申请存储权限 + File photoFile = new File(storageDir, fileName); + + try { + if (photoFile.createNewFile()) { + return photoFile; + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; + } + //根据路径读取图片 + public static Bitmap getBitmapFromPath(String path){ + Bitmap bitmap = BitmapFactory.decodeFile(path); + return bitmap; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/tool/LineChartManager.java b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/LineChartManager.java new file mode 100644 index 0000000..1e5fc51 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/LineChartManager.java @@ -0,0 +1,263 @@ +package com.lh.app.tool; + +import com.github.mikephil.charting.charts.LineChart; +import com.github.mikephil.charting.components.Description; +import com.github.mikephil.charting.components.Legend; +import com.github.mikephil.charting.components.LimitLine; +import com.github.mikephil.charting.components.XAxis; +import com.github.mikephil.charting.components.YAxis; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.LineData; +import com.github.mikephil.charting.data.LineDataSet; +import com.github.mikephil.charting.interfaces.datasets.ILineDataSet; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +/** + *图像管理类 + */ +public class LineChartManager { + private LineChart lineChart; + private YAxis leftAxis; + private YAxis rightAxis; + private XAxis xAxis; + private LineData lineData; + private LineDataSet lineDataSet; + private List lineDataSets = new ArrayList<>(); + private SimpleDateFormat df = new SimpleDateFormat("HH:mm:ss");//设置日期格式 + private List timeList = new ArrayList<>(); //存储x轴的时间 + + //一条曲线 + public LineChartManager(LineChart mLineChart, String name, int color) { + this.lineChart = mLineChart; + leftAxis = lineChart.getAxisLeft(); + rightAxis = lineChart.getAxisRight(); + xAxis = lineChart.getXAxis(); + initLineChart(); + initLineDataSet(name, color); + } + + //多条曲线 + public LineChartManager(LineChart mLineChart, List names, List colors) { + this.lineChart = mLineChart; + leftAxis = lineChart.getAxisLeft(); + rightAxis = lineChart.getAxisRight(); + xAxis = lineChart.getXAxis(); + initLineChart(); + initLineDataSet(names, colors); + } + + /** + * 初始化LineChar + */ + private void initLineChart() { + + lineChart.setDrawGridBackground(false); + //显示边界 + lineChart.setDrawBorders(true); + //折线图例 标签 设置 + Legend legend = lineChart.getLegend(); + legend.setForm(Legend.LegendForm.LINE); + legend.setTextSize(11f); + //显示位置 + legend.setVerticalAlignment(Legend.LegendVerticalAlignment.BOTTOM); + legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT); + legend.setOrientation(Legend.LegendOrientation.HORIZONTAL); + legend.setDrawInside(false); + + //X轴设置显示位置在底部 + xAxis.setPosition(XAxis.XAxisPosition.BOTTOM); + xAxis.setGranularity(1f); + xAxis.setLabelCount(10); + + + //保证Y轴从0开始,不然会上移一点 + leftAxis.setAxisMinimum(0f); + rightAxis.setAxisMinimum(0f); + } + + /** + * 初始化折线(一条线) + * + * @param name + * @param color + */ + private void initLineDataSet(String name, int color) { + + lineDataSet = new LineDataSet(null, name); + lineDataSet.setLineWidth(1.5f); + lineDataSet.setCircleRadius(1.5f); + lineDataSet.setColor(color); + lineDataSet.setCircleColor(color); + lineDataSet.setHighLightColor(color); + //设置曲线填充 + lineDataSet.setDrawFilled(false); + lineDataSet.setDrawValues(false); + lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); + lineDataSet.setValueTextSize(10f); + lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); + //添加一个空的 LineData + lineData = new LineData(); + lineChart.setData(lineData); + lineChart.invalidate(); + + } + + /** + * 初始化折线(多条线) + * + * @param names + * @param colors + */ + private void initLineDataSet(List names, List colors) { + + for (int i = 0; i < names.size(); i++) { + lineDataSet = new LineDataSet(null, names.get(i)); + lineDataSet.setColor(colors.get(i)); + lineDataSet.setLineWidth(1.5f); + lineDataSet.setCircleRadius(1.5f); + lineDataSet.setColor(colors.get(i)); + + lineDataSet.setDrawFilled(false); + lineDataSet.setDrawValues(false); + lineDataSet.setCircleColor(colors.get(i)); + lineDataSet.setHighLightColor(colors.get(i)); + lineDataSet.setMode(LineDataSet.Mode.CUBIC_BEZIER); + lineDataSet.setAxisDependency(YAxis.AxisDependency.LEFT); + lineDataSet.setValueTextSize(10f); + lineDataSets.add(lineDataSet); + + } + //添加一个空的 LineData + lineData = new LineData(); + lineChart.setData(lineData); + lineChart.invalidate(); + } + + /** + * 动态添加数据(一条折线图) + * + * @param number + */ + public void addEntry(int number) { + + //最开始的时候才添加 lineDataSet(一个lineDataSet 代表一条线) + if (lineDataSet.getEntryCount() == 0) { + lineData.addDataSet(lineDataSet); + } + lineChart.setData(lineData); + //避免集合数据过多,及时清空(做这样的处理,并不知道有没有用,但还是这样做了) + if (timeList.size() > 11) { + timeList.clear(); + } + + timeList.add(df.format(System.currentTimeMillis())); + + Entry entry = new Entry(lineDataSet.getEntryCount(), number); + lineData.addEntry(entry, 0); + //通知数据已经改变 + lineData.notifyDataChanged(); + lineChart.notifyDataSetChanged(); + //设置在曲线图中显示的最大数量 + lineChart.setVisibleXRangeMaximum(10); + //移到某个位置 + lineChart.moveViewToX(lineData.getEntryCount() - 5); + } + + /** + * 动态添加数据(多条折线图) + * + * @param numbers + */ + public void addEntry(List numbers) { + + if (lineDataSets.get(0).getEntryCount() == 0) { + lineData = new LineData(lineDataSets); + lineChart.setData(lineData); + } + if (timeList.size() > 100) { + timeList.clear(); + } + timeList.add(df.format(System.currentTimeMillis())); + for (int i = 0; i < numbers.size(); i++) { + Entry entry = new Entry(lineDataSet.getEntryCount(), numbers.get(i)); + lineData.addEntry(entry, i); + lineData.notifyDataChanged(); + lineChart.notifyDataSetChanged(); + lineChart.setVisibleXRangeMaximum(6); + lineChart.moveViewToX(lineData.getEntryCount() - 5); + } + } + + /** + * 设置Y轴值 + * + * @param max + * @param min + * @param labelCount + */ + public void setYAxis(float max, float min, int labelCount) { + if (max < min) { + return; + } + leftAxis.setAxisMaximum(max); + leftAxis.setAxisMinimum(min); + leftAxis.setLabelCount(labelCount, false); + + rightAxis.setAxisMaximum(max); + rightAxis.setAxisMinimum(min); + rightAxis.setLabelCount(labelCount, false); + lineChart.invalidate(); + } + + /** + * 设置高限制线 + * + * @param high + * @param name + */ + public void setHightLimitLine(float high, String name, int color) { + if (name == null) { + name = "高限制线"; + } + LimitLine hightLimit = new LimitLine(high, name); + hightLimit.setLineWidth(4f); + hightLimit.setTextSize(10f); + hightLimit.setLineColor(color); + hightLimit.setTextColor(color); + leftAxis.addLimitLine(hightLimit); + lineChart.invalidate(); + } + + /** + * 设置低限制线 + * + * @param low + * @param name + */ + public void setLowLimitLine(int low, String name) { + if (name == null) { + name = "低限制线"; + } + LimitLine hightLimit = new LimitLine(low, name); + hightLimit.setLineWidth(4f); + hightLimit.setTextSize(10f); + leftAxis.addLimitLine(hightLimit); + lineChart.invalidate(); + } + + /** + * 设置描述信息 + * + * @param str + */ + public void setDescription(String str) { + Description description = new Description(); + description.setText(str); + lineChart.setDescription(description); + lineChart.invalidate(); + } +} + diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/tool/NotificationUtil.java b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/NotificationUtil.java new file mode 100644 index 0000000..5a554fc --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/NotificationUtil.java @@ -0,0 +1,51 @@ +package com.lh.app.tool; + +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.graphics.Bitmap; +import android.os.Build; + +import androidx.core.app.NotificationCompat; + +/** + * Created by LiShiyao on 2022.11.12. + */ +public class NotificationUtil { + private Context context; + private String contentTitle; + private String contentText; + private int smallIcon; + private Bitmap largeIcon; + + public NotificationUtil(Context context, String contentTitle, String contentText, int smallIcon, Bitmap largeIcon) { + this.context = context; + this.contentTitle = contentTitle; + this.contentText = contentText; + this.smallIcon = smallIcon; + this.largeIcon = largeIcon; + } + + //通知提醒 + public void notification(){ + // + NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); + if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.O){ + String channelId = "whatever"; + String channelName = "whatever content"; + int important = NotificationManager.IMPORTANCE_HIGH; + manager.createNotificationChannel(new NotificationChannel(channelId,channelName,important)); + } + Notification notification; + notification = new NotificationCompat.Builder(context,"whatever") + .setContentTitle(contentTitle) + .setContentText(contentText) + .setWhen(System.currentTimeMillis()) + .setSmallIcon(smallIcon) + .setLargeIcon(largeIcon) + .setAutoCancel(false) + .build(); + manager.notify(1,notification); + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ToastUtil.java b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ToastUtil.java new file mode 100644 index 0000000..f08cb9c --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/tool/ToastUtil.java @@ -0,0 +1,10 @@ +package com.lh.app.tool; + +import android.content.Context; +import android.widget.Toast; + +public class ToastUtil { + public static void show(Context context,String desc){ + Toast.makeText(context, desc, Toast.LENGTH_SHORT).show(); + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DashboardViewModel.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DashboardViewModel.java new file mode 100644 index 0000000..6c2c735 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DashboardViewModel.java @@ -0,0 +1,19 @@ +package com.lh.app.ui.detail; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class DashboardViewModel extends ViewModel { + + private final MutableLiveData mText; + + public DashboardViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is dashboard fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DetailFragment.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DetailFragment.java new file mode 100644 index 0000000..e9907e1 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/DetailFragment.java @@ -0,0 +1,730 @@ +package com.lh.app.ui.detail; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.ContentValues; +import android.content.Context; +import android.content.DialogInterface; +import android.graphics.Color; +import android.os.Bundle; +import android.os.SystemClock; +import android.text.Html; +import android.text.TextUtils; +import android.util.Log; +import android.view.ContextMenu; +import android.view.LayoutInflater; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.TranslateAnimation; +import android.widget.Button; +import android.widget.CheckBox; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.ScrollView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + +import com.github.mikephil.charting.charts.LineChart; +import com.lh.app.MyApplication; +import com.lh.app.R; +import com.lh.app.RoommateDBHelper; +import com.lh.app.tool.LineChartManager; +import com.lh.app.tool.ToastUtil; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; + +public class DetailFragment extends Fragment { + //室友名显示控件 + private TextView tv_roommate1; + private TextView tv_roommate2; + private TextView tv_roommate3; + //室友名默认值 + private final String name1_default="mate1"; + private final String name2_default="mate2"; + private final String name3_default="mate3"; + //室友图片显示控件 + private ImageView img_roma1; + private ImageView img_roma2; + private ImageView img_roma3; + //信息输入控件 + private ScrollView scr_enterInfo;//输入信息布局 + private EditText ed_name; + private EditText ed_sno; + private EditText ed_weight; + private EditText ed_height; + private EditText ed_birthday; + private EditText ed_hobby; + private CheckBox ckb_isMarried; + //其它控件 + private TextView tv_showText; + private Button but_toSource; + private Button but_sure; + private Button but_clear; + private int select_mate=0;//选择的室友(1,2,3) + + //控件双击控制 + private long lastClickTime = 0; + //图像控件 + private LineChart mLineChart; + //数据库帮助器对象实例 + private final RoommateDBHelper mHelper = MyApplication.mHelper; + //活动视图 + private View view; + //上下文 + private Context context; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + //Fragment被创建时,被调用 + super.onCreate(savedInstanceState); + Log.d("fragment_detail"," onCreate"); + + + } + + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + Log.d("fragment_detail"," onCreateView"); + + //创建Fragment视图 + view = inflater.inflate(R.layout.fragment_detail,container,false); + + //获取上下文 + context = getActivity(); + //引入组件 + inductUI(); + //向组件中填充文本 + initUI(); + //设置组件监听器 + addListenerToUI(); + return view; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + Log.d("fragment_detail","onActivityCreated"); + } + + @Override + public void onStart() { + //无焦点但可见时,调用此方法 + super.onStart(); + Log.d("fragment_detail"," onStart"); + } + + @Override + public void onPause() { + //Fragment失去焦点但可见时,调用此方法. + super.onPause(); + Log.d("fragment_detail"," onPause"); + } + + @Override + public void onStop() { + //Fragment不可见时,调用此方法. + super.onStop(); + Log.d("fragment_detail"," onStop"); + } + + @Override + public void onDestroyView() { + //当Fragment被移除时被调用 + super.onDestroyView(); + Log.d("fragment_detail"," onDestroyView"); + + } + + //引入组件 + private void inductUI(){ + //引入标签 + tv_roommate1 = view.findViewById(R.id.roommate1); + tv_roommate2 = view.findViewById(R.id.roommate2); + tv_roommate3 = view.findViewById(R.id.roommate3); + tv_showText = view.findViewById(R.id.text); + + img_roma1 = view.findViewById(R.id.roommate1_img); + img_roma2 = view.findViewById(R.id.roommate2_img); + img_roma3 = view.findViewById(R.id.roommate3_img); + + ed_name = view.findViewById(R.id.ed_name) ; + ed_sno = view.findViewById(R.id.ed_sno) ; + ed_weight = view.findViewById(R.id.ed_weight); + ed_height = view.findViewById(R.id.ed_height); + ed_birthday = view.findViewById(R.id.ed_birthday) ; + ed_hobby = view.findViewById(R.id.ed_hobby) ; + ckb_isMarried = view.findViewById(R.id.ckb_isMarried); + + scr_enterInfo = view.findViewById(R.id.scr_enterIfo) ; + + but_toSource = view.findViewById(R.id.source_button); + but_sure = view.findViewById(R.id.sure_but); + but_clear = view.findViewById(R.id.but_clear); + + mLineChart = view.findViewById(R.id.show_img_curve); + } + /*初始化可见组件的样式*/ + private void initUI() { + //判断舍友信息是否为空 + if (!mHelper.query_roommateInfo_isEmpty()){ + int pos1,pos2,pos3; + //查询数据库中舍友信息表中全部名字 + List list_roommateName = mHelper.query_roommateName(); + //将已录入人数的姓名显示在对应TextView上 + switch (list_roommateName.size()){ + case 1: + pos1 = mHelper.query_roommate_position(list_roommateName.get(0)); + setName(pos1,list_roommateName.get(0)); + break; + case 2: + pos1 = mHelper.query_roommate_position(list_roommateName.get(0)); + pos2 = mHelper.query_roommate_position(list_roommateName.get(1)); + setName(pos1,list_roommateName.get(0)); + setName(pos2,list_roommateName.get(1)); + break; + case 3: + pos1 = mHelper.query_roommate_position(list_roommateName.get(0)); + pos2 = mHelper.query_roommate_position(list_roommateName.get(1)); + pos3 = mHelper.query_roommate_position(list_roommateName.get(2)); + setName(pos1,list_roommateName.get(0)); + setName(pos2,list_roommateName.get(1)); + setName(pos3,list_roommateName.get(2)); + break; + } + + } + } + + @SuppressLint("ClickableViewAccessibility") + private void addListenerToUI(){ + //舍友姓名单击效果 + tv_roommate1.setOnClickListener(this::onClick); + tv_roommate2.setOnClickListener(this::onClick); + tv_roommate3.setOnClickListener(this::onClick); + //舍友图片双击效果 + img_roma1.setOnClickListener(this::onClick); + img_roma2.setOnClickListener(this::onClick); + img_roma3.setOnClickListener(this::onClick); + //添加图片长按效果 + registerForContextMenu(img_roma1); + registerForContextMenu(img_roma2); + registerForContextMenu(img_roma3); + //"打回原型"按钮长按效果 + but_toSource.setOnTouchListener(this::onTouch); + //信息录入“确认”按钮单击效果 + but_sure.setOnClickListener(this::onClick); + //“清空数据”按钮单击效果 + but_clear.setOnClickListener(this::onClick); + } + //组件点击 + @SuppressLint("NonConstantResourceId") + private void onClick(View v){ + switch (v.getId()){ + case R.id.roommate1: + TextView_show(1, (String) tv_roommate1.getText()); + break; + case R.id.roommate2: + TextView_show(2, (String) tv_roommate2.getText()); + break; + case R.id.roommate3: + TextView_show(3, (String) tv_roommate3.getText()); + break; + + case R.id.roommate1_img: + clickImg(1); + break; + case R.id.roommate2_img: + clickImg(2); + break; + case R.id.roommate3_img: + clickImg(3); + break; + case R.id.sure_but: + sure_but_show(); + break; + case R.id.but_clear: + //弹出弹框提示 + showAlertDialog(); + break; + } + + } + //显示对话框提示 + @SuppressLint("DiscouragedPrivateApi") + private void showAlertDialog(){ + AlertDialog dialog = new AlertDialog.Builder(context) + .setIcon(R.drawable.img_delete) + .setTitle(Html.fromHtml("信息提示")) + .setMessage(Html.fromHtml("确认全删除?")) + .setPositiveButton("是", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//确认按钮监听事件 + mHelper.deleteAll(RoommateDBHelper.getTableNameRoommateInfo()); + ToastUtil.show(context,"删除完成"); + switch (select_mate){ + case 1: + tv_roommate1.setText(name1_default); + break; + case 2: + tv_roommate2.setText(name2_default); + break; + case 3: + tv_roommate3.setText(name3_default); + break; + } + dialog.dismiss(); + } + }) + .setNegativeButton("否", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//返回按钮监听事件 + dialog.dismiss(); + } + }) + .create(); + dialog.show(); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextColor(Color.BLACK); + dialog.getButton(AlertDialog.BUTTON_POSITIVE).setTextSize(25); + dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.BLUE); + dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextSize(25); + } + //"打回原型"按钮被按下 + @SuppressLint("UseCompatLoadingForDrawables") + private boolean onTouch(View view, MotionEvent event) { + if(view.getId() == R.id.source_button){ + if (event.getAction() == MotionEvent.ACTION_DOWN){ + if(select_mate==1) img_roma1.setImageDrawable(context.getDrawable(R.drawable.img_dog1)); + else if(select_mate==2) img_roma2.setImageDrawable(context.getDrawable(R.drawable.img_dog3)); + else if(select_mate==3) img_roma3.setImageDrawable(context.getDrawable(R.drawable.img_dog2)); + } + else if(event.getAction() == MotionEvent.ACTION_UP){ + if(select_mate==1) img_roma1.setImageDrawable(context.getDrawable(R.drawable.hyt)); + else if(select_mate==2) img_roma2.setImageDrawable(context.getDrawable(R.drawable.wyz1)); + else if(select_mate==3) img_roma3.setImageDrawable(context.getDrawable(R.drawable.wz)); + } + + } + return false; + } + + //信息录入"确认"按钮点击事件 + private void sure_but_show() { + //判断输入是否有空 + if(TextUtils.isEmpty(ed_name.getText()) || TextUtils.isEmpty(ed_sno.getText()) || + TextUtils.isEmpty(ed_height.getText()) || TextUtils.isEmpty(ed_weight.getText())|| + TextUtils.isEmpty(ed_birthday.getText()) || TextUtils.isEmpty(ed_hobby.getText())) + { + Toast.makeText(context,"输入不能有空!",Toast.LENGTH_SHORT).show(); + } + else{ + //设置舍友信息 + Roommate roommate = new Roommate(); + roommate.setName(String.valueOf(ed_name.getText())); + roommate.setId(String.valueOf(ed_sno.getText())); + roommate.setHeight(Integer.parseInt(String.valueOf(ed_height.getText()))); + roommate.setWeight(Float.parseFloat(String.valueOf(ed_weight.getText()))); + roommate.setBirthday(String.valueOf(ed_birthday.getText())); + roommate.setMarried(ckb_isMarried.isChecked()); + roommate.setHobby(String.valueOf(ed_hobby.getText())); + //保存舍友信息到键值对中 + ContentValues values = new ContentValues(); + values.put("name",roommate.getName()); + values.put("id",roommate.getId()); + values.put("height",roommate.getHeight()); + values.put("weight",roommate.getWeight()); + values.put("married",roommate.isMarried()); + values.put("birthday",roommate.getBirthday()); + values.put("hobby",roommate.getHobby()); + values.put("position",select_mate); + //若是第一次录入内容,添加数据 + if(isFirstInput()) { + //保存键值对到数据库中的舍友信息表中 + mHelper.insert(RoommateDBHelper.getTableNameRoommateInfo(),values); + } + //若非第一次录入内容,修改数据 + else { + String name = getName(); + long row = mHelper.update_roommateInfo(values,name); + Log.d("UpdateMemoTable","修改备忘录"+row+"条"); + } + //设置指定textview的text + setTextToTV(roommate.getName()); + //隐藏输入框 + scr_enterInfo.setVisibility(View.GONE); + } + } + + //舍友名字点击事件 + @SuppressLint("SetTextI18n") + private void TextView_show(int i, String name) { + //选择室友序号 + select_mate = i; + //设置字体颜色 + changeTextColor(); + //隐藏信息录入 + scr_enterInfo.setVisibility(View.GONE); + //曲线显示隐藏 + mLineChart.setVisibility(View.GONE); + //清空文本域 + tv_showText.setText(""); + //室友信息弹出动画 + startAnim(); + //判断舍友姓名是否为空 + if (name.equals("mate"+i)) return; + //读取数据库信息 + Roommate roommate = mHelper.query_roommateInfo_ByName(name); + //写入具体内容 + int[][] bodyRhythm = body_rhythm(roommate.getBirthday()); + tv_showText.setText("姓名:"+roommate.getName()+"\n学号:"+roommate.getId()+"身高:"+roommate.getHeight()+ + "\n体重:"+roommate.getWeight()+"\n生日:"+ roommate.getBirthday()+"\n爱好:"+roommate.getHobby()+ + "\n\n人体生物节律\n 已运行周期数 新周期开始天数"+ + "\n智力: "+bodyRhythm[0][0]+" "+bodyRhythm[1][0]+ + "\n情绪: "+bodyRhythm[0][1]+" "+bodyRhythm[1][1]+ + "\n体力: "+bodyRhythm[0][2]+" "+bodyRhythm[1][2], TextView.BufferType.EDITABLE); + } + //改变文本颜色 + public void changeTextColor() { + //设置字体变换颜色 + int[] color = new int[2]; + color[0] = Color.parseColor("#64E14B"); + color[1] = Color.parseColor("#2B2B2B"); + //改变字体颜色 + if(select_mate == 1){ + tv_roommate1.setTextColor(color[0]); + tv_roommate2.setTextColor(color[1]); + tv_roommate3.setTextColor(color[1]); + }else if(select_mate == 2){ + tv_roommate1.setTextColor(color[1]); + tv_roommate2.setTextColor(color[0]); + tv_roommate3.setTextColor(color[1]); + }else{ + tv_roommate1.setTextColor(color[1]); + tv_roommate2.setTextColor(color[1]); + tv_roommate3.setTextColor(color[0]); + } + } + //文本框弹出效果 + private void startAnim() { + //设置动画,从自身位置的最下端向上滑动了自身的高度,持续时间为500ms + final TranslateAnimation ctrlAnimation = new TranslateAnimation( + TranslateAnimation.RELATIVE_TO_SELF, 0, TranslateAnimation.RELATIVE_TO_SELF, 0, + TranslateAnimation.RELATIVE_TO_SELF, 1, TranslateAnimation.RELATIVE_TO_SELF, 0); + ctrlAnimation.setDuration(500l); //设置动画的过渡时间 + tv_showText.postDelayed(new Runnable() { + @Override + public void run() { + tv_showText.setVisibility(View.VISIBLE); + tv_showText.startAnimation(ctrlAnimation); + } + }, 000); + } + //点击图片事件 + private void clickImg(int i) { + //获取当前系统当前毫秒数 + long currentTimeMills = SystemClock.uptimeMillis(); + //两次间隔小于300ms代表双击 + if(currentTimeMills-lastClickTime<300){ + //改变选择的照片 + select_mate = i; + //改变文字颜色 + changeTextColor(); + //舍友录入信息清空 + setInputTextEmpty(); + //隐藏曲线显示、文本显示 + tv_showText.setVisibility(View.GONE); + mLineChart.setVisibility(View.GONE); + //显示输入框 + scr_enterInfo.setVisibility(View.VISIBLE); + textShow(); + return; + } + //更新最后一次点击时间 + lastClickTime = currentTimeMills; + } + //清空输入文本和显示文本域 + private void setInputTextEmpty() { + tv_showText.setText(""); + ed_name.setText(""); + ed_sno.setText(""); + ed_weight.setText(""); + ed_height.setText(""); + ed_hobby.setText(""); + ed_birthday.setText(""); + ckb_isMarried.setChecked(false); + } + + //设置指定textView的text + private void setTextToTV(String name) { + switch (select_mate){ + case 1: + tv_roommate1.setText(name); + break; + case 2: + tv_roommate2.setText(name); + break; + case 3: + tv_roommate3.setText(name); + break; + } + } + //向信息录入中填充文本信息 + private void textShow() { + //若未给室友录入信息,弹出清空后的输入界面 + if (isFirstInput()) { + setInputTextEmpty(); + return; + } + Roommate roommate = new Roommate(); + //判断点击室友名,从数据库中取出数据 + switch (select_mate){ + case 1: + if ((tv_roommate1.getText()).equals(name1_default)) return; + roommate = mHelper.query_roommateInfo_ByName((String) tv_roommate1.getText()); + break; + case 2: + if ((tv_roommate2.getText()).equals(name2_default)) return; + roommate = mHelper.query_roommateInfo_ByName((String) tv_roommate2.getText()); + break; + case 3: + if ((tv_roommate3.getText()).equals(name3_default)) return; + roommate = mHelper.query_roommateInfo_ByName((String) tv_roommate3.getText()); + break; + } + //填充数据 + ed_name.setText(roommate.getName()); + ed_sno.setText(roommate.getId()); + ed_weight.setText(String.valueOf(roommate.getWeight())); + ed_height.setText(String.valueOf(roommate.getHeight())); + ed_birthday.setText(roommate.getBirthday()); + ed_hobby.setText(roommate.getHobby()); + ckb_isMarried.setChecked(roommate.isMarried()); + } + //是否是第一次为室友录入信息或是否为该室友录入信息 + public boolean isFirstInput() { + switch (select_mate){ + case 1: + if (name1_default.contentEquals(tv_roommate1.getText())) return true; + break; + case 2: + if (name2_default.contentEquals(tv_roommate2.getText())) return true; + break; + case 3: + if (name3_default.contentEquals(tv_roommate3.getText())) return true; + break; + } + return false; + } + //得到指定室友在textView上的名字 + public String getName() { + switch (select_mate){ + case 1: + return (String) tv_roommate1.getText(); + case 2: + return (String) tv_roommate2.getText(); + case 3: + return (String) tv_roommate3.getText(); + } + return "mate"; + } + //填充文本框文本 + private void setName(int pos,String name) { + switch (pos){ + case 1: + tv_roommate1.setText(name); + break; + case 2: + tv_roommate2.setText(name); + break; + case 3: + tv_roommate3.setText(name); + break; + } + } + + //长按显示菜单 + @SuppressLint("NonConstantResourceId") + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + //子菜单部分 + MenuInflater inflater = new MenuInflater(context); + inflater.inflate(R.menu.menu_sub,menu); + switch (v.getId()){ + case R.id.roommate1_img: + select_mate = 1; + changeTextColor(); + break; + case R.id.roommate2_img: + select_mate = 2; + changeTextColor(); + break; + case R.id.roommate3_img: + select_mate = 3; + changeTextColor(); + break; + default: + break; + } + + super.onCreateContextMenu(menu, v, menuInfo); + } + //上下文菜单被点击时触发该方法 + @SuppressLint("NonConstantResourceId") + @Override + public boolean onContextItemSelected(@NonNull MenuItem item) { + switch (item.getItemId()){ + case R.id.item_revise_introduce: + //填充内容,显示输入 + textShow(); + mLineChart.setVisibility(View.GONE); + tv_showText.setVisibility(View.GONE); + scr_enterInfo.setVisibility(View.VISIBLE); + break; + case R.id.item_show_curve: + //判断是否给舍友录入信息 + if(isFirstInput()) { + ToastUtil.show(context, "没有信息!"); + return true; + } + show_body_rhythm_curve(); + mLineChart.setVisibility(View.VISIBLE); + scr_enterInfo.setVisibility(View.GONE); + tv_showText.setVisibility(View.GONE); + break; + default: + break; + } + return true; + } + //显示曲线图 + private void show_body_rhythm_curve() { + Roommate roommate = mHelper.query_roommateInfo_ByName(getName()); + String birthday = roommate.getBirthday(); + int[][] body_rhythm_data = body_rhythm_month(birthday); + List list_name = new ArrayList<>(); + List list_color = new ArrayList<>(); + list_name.add("智力"); + list_name.add("情绪"); + list_name.add("体力"); + list_color.add(Color.BLACK); + list_color.add(Color.GREEN); + list_color.add(Color.BLUE); + LineChartManager manager = new LineChartManager(mLineChart,list_name,list_color); + //设置图像显示内容 + manager.setDescription("月份"); + manager.setYAxis(60,-60,30); + manager.setHightLimitLine(30,"最高",Color.BLACK); + List list_numbers = new ArrayList<>(); + for(int i=0;i<31;i++){ + list_numbers.add((float) body_rhythm_data[1][i]); + list_numbers.add((float) body_rhythm_data[2][i]); + list_numbers.add((float) body_rhythm_data[3][i]); + manager.addEntry(list_numbers); + list_numbers.clear(); + } + } + + /** + * 根据生日计算人体生物节律 + * @param birthday 生日 格式: 2000.08.04 + * @return 人体生命节律值 body_rhythm【【已运行周期天数(智力、情绪、体力)】【开始周期运行天数(智力、情绪、体力)】】 + * */ + private int[][] body_rhythm(String birthday){ + int[][] body_rhythm = new int[2][3]; + String bornYear,bornMonth,bornDay; + //计算生日年-月-日 统一格式 + String[] bornData = birthday.split("\\.+"); + bornYear = bornData[0]; + bornMonth = bornData[1]; + bornDay = bornData[2]; + String endTime = bornYear+"-"+bornMonth+"-"+bornDay; + //计算当前年-月-日 统一格式 + Calendar calendar = Calendar.getInstance(); + int nowYear = calendar.get(Calendar.YEAR); //年 + int nowMonth = calendar.get(Calendar.MONTH)+1; //月 + int nowDay = calendar.get(Calendar.DAY_OF_MONTH); //日 + String startTime = nowYear+"-"+nowMonth+"-"+nowDay; + //计算当前时间与出生相隔天数 + SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); + long nd = 1000*24*60*60;//一天的毫秒数 + long diff = 0; + try { + //getTime()返回毫秒数 + diff = sd.parse(startTime).getTime() - sd.parse(endTime).getTime(); + } catch (ParseException e) { + e.printStackTrace(); + } + long days = diff/nd;//计算相差多少天 + + //使用公式计算智力(IT)、情绪(mood)、体力(HP)节律周期(cycle)天数 + body_rhythm[0][0] = (int) (days/32); + body_rhythm[0][1] = (int) (days/28); + body_rhythm[0][2] = (int) (days/23); + + //使用公式计算智力(IT)、情绪(mood)、体力(HP)节律新周期运行天数 + body_rhythm[1][0] = (int) (days%32); + body_rhythm[1][1] = (int) (days%28); + body_rhythm[1][2] = (int) (days%23); + + return body_rhythm; + } + + /** + * 根据生日计算到当月的人体生物节律 + * @param birthday 生日 格式: 2000.08.04 + * @return 人体生命节律值 body_rhythm【【已运行周期天数(智力、情绪、体力)】【开始周期运行天数(智力、情绪、体力)】】 + * */ + private int[][] body_rhythm_month(String birthday){ + int[][] body_rhythm = new int[4][32]; + String bornYear,bornMonth,bornDay; + //计算生日年-月-日 统一格式 + String[] bornData = birthday.split("\\.+"); + bornYear = bornData[0]; + bornMonth = bornData[1]; + bornDay = bornData[2]; + String endTime = bornYear+"-"+bornMonth+"-"+bornDay; + //计算当前年-月-日 统一格式 + Calendar calendar = Calendar.getInstance(); + int nowYear = calendar.get(Calendar.YEAR); //年 + int nowMonth = calendar.get(Calendar.MONTH)+1; //月 + int nowDay = 1; + String startTime; + while (nowDay<30){ + startTime = nowYear+"-"+nowMonth+"-"+nowDay; + //计算当前时间与出生相隔天数 + SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd"); + long nd = 1000*24*60*60;//一天的毫秒数 + long diff = 0; + try { + //getTime()返回毫秒数 + diff = sd.parse(startTime).getTime() - sd.parse(endTime).getTime(); + } catch (ParseException e) { + e.printStackTrace(); + } + long days = diff/nd;//计算相差多少天 + + //使用公式计算智力(IT)、情绪(mood)、体力(HP)节律周期(cycle)天数 + body_rhythm[0][0] = (int) (days/32); + body_rhythm[0][1] = (int) (days/28); + body_rhythm[0][2] = (int) (days/23); + + //使用公式计算智力(IT)、情绪(mood)、体力(HP)节律新周期运行天数 + body_rhythm[1][nowDay-1] = (int) (days%32); + body_rhythm[2][nowDay-1] = (int) (days%28); + body_rhythm[3][nowDay-1] = (int) (days%23); + + nowDay++; + } + return body_rhythm; + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/Roommate.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/Roommate.java new file mode 100644 index 0000000..2426fdf --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/detail/Roommate.java @@ -0,0 +1,78 @@ +package com.lh.app.ui.detail; + + +public class Roommate { + private String name; + private String id; + private long height;//单位cm + private float weight;//单位kg + private boolean married; + private String birthday; + private String hobby; + public Roommate(){ } + + public Roommate(String name, String id, long height, float weight, boolean married, String birthday, String hobby) { + this.name = name; + this.id = id; + this.height = height; + this.weight = weight; + this.married = married; + this.birthday = birthday; + this.hobby = hobby; + } + + public String getName() { + return name; + } + public String getId() { + return id; + } + public long getHeight() { + return height; + } + public float getWeight() { + return weight; + } + public boolean isMarried() { + return married; + } + public String getHobby() { + return hobby; + } + public String getBirthday() { + return birthday; + } + + public void setName(String name) { + this.name = name; + } + public void setId(String id) { + this.id = id; + } + public void setHeight(long height) { + this.height = height; + } + public void setWeight(float weight) { + this.weight = weight; + } + public void setMarried(boolean married) { + this.married = married; + } + public void setHobby(String hobby) { + this.hobby = hobby; + } + public void setBirthday(String birthday) { + this.birthday = birthday; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", name='" + name + '\'' + + ", height=" + height + + ", weight=" + weight + + ", married=" + married + + '}'; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Honor.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Honor.java new file mode 100644 index 0000000..c5939f7 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Honor.java @@ -0,0 +1,40 @@ +package com.lh.app.ui.honor; + +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; + +import androidx.core.content.FileProvider; + +import java.io.FileNotFoundException; + +/** + * Created by LiShiyao on 2022.11.17 + */ +public class Honor { + private String content; + private String imageLocation; + + public Honor(){} + + public Honor(String content, String imageLocation) { + this.content = content; + this.imageLocation = imageLocation; + } + public String getContent() { + return content; + } + + public String getImageLocation() { + return imageLocation; + } + + + public void setContent(String content) { + this.content = content; + } + + public void setImageLocation(String imageLocation) { + this.imageLocation = imageLocation; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorAdapter.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorAdapter.java new file mode 100644 index 0000000..3ed3ee1 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorAdapter.java @@ -0,0 +1,99 @@ +package com.lh.app.ui.honor; + +import android.content.ContentResolver; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; +import androidx.recyclerview.widget.RecyclerView; + + +import com.bumptech.glide.Glide; +import com.lh.app.R; +import com.lh.app.tool.ImageUtils; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +public class HonorAdapter extends RecyclerView.Adapter { + private List mHonorList; + public static List selectHonor = new ArrayList<>(); + private Context mContext; + + static class ViewHolder extends RecyclerView.ViewHolder{ + View view; + ImageView imageImage; + TextView tv_describe; + CheckBox ckb_honorItem; + public ViewHolder(View view){ + super(view); + this.view = view; + imageImage = (ImageView) view.findViewById(R.id.img_honor); + tv_describe = (TextView) view.findViewById(R.id.tv_describe); + ckb_honorItem = view.findViewById(R.id.ckb_honorItem); + } + } + public HonorAdapter(List honorList,Context context){ + mHonorList = honorList; + mContext = context; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.honor_item,parent,false); + final ViewHolder holder = new ViewHolder(view); + + //list的点击事件 + holder.view.setOnClickListener(view1 -> { + int position = holder.getAdapterPosition(); + Honor honor = mHonorList.get(position); + Toast.makeText(view.getContext(),"you clicked view " +position,Toast.LENGTH_SHORT).show(); + }); + + return holder; + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + Honor honor = mHonorList.get(position); + Uri uri = Uri.parse(honor.getImageLocation()); + Glide.with(mContext) + .load(uri) + .error(R.drawable.ic_no_picture) + .into(holder.imageImage); + + holder.tv_describe.setText(honor.getContent()); + + //设置单选框监听器 + holder.ckb_honorItem.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + if(isChecked) selectHonor.add(honor); + else selectHonor.remove(honor); + } + }); + } + + @Override + public int getItemCount() { + return mHonorList.size(); + } + +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorFragment.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorFragment.java new file mode 100644 index 0000000..103329f --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/HonorFragment.java @@ -0,0 +1,266 @@ +package com.lh.app.ui.honor; + +import static com.lh.app.tool.ImageUtils.uriToBitmap; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Bundle; +import android.text.InputType; +import android.util.Log; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.EditText; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.activity.result.ActivityResult; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.lh.app.MyApplication; +import com.lh.app.R; +import com.lh.app.RoommateDBHelper; + +import java.util.ArrayList; +import java.util.List; + +; + +public class HonorFragment extends Fragment { + private static final int REQUEST_CODE_PERMISSION = 100; + private List mHonorList = new ArrayList<>(); + private RecyclerView recyclerView; + private View view; + private Context context; + private Button but_addHonor; + private ImageView img_imageHonor; + private EditText edt_describe; + private LinearLayout ll_inputHonor; + private Button but_backHonor; + private Button but_sureHonor; + private Button but_deleteHonor; + private TextView tv_emptyHonor; + private ActivityResultLauncher mFromAlumn; + + private Image checkImage = null; + + private HonorAdapter adapter; + //数据库帮助器对象实例 + private RoommateDBHelper mHelper = MyApplication.mHelper; + + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + Log.d("ning","Communicate Fragment onCreate"); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + view = inflater.inflate(R.layout.fragment_honor,container,false); + context = getActivity(); + addUI_Listener(); + text_Control(); + initList(); + setRecycleView(); + return view; + } + + + + @Override + public void onStart() { + //无焦点但可见时,调用此方法 + super.onStart(); + Log.d("HonorActivity","onStart"); + } + + @Override + public void onPause() { + //Fragment失去焦点但可见时,调用此方法. + super.onPause(); + } + + @Override + public void onStop() { + //Fragment不可见时,调用此方法. + super.onStop(); + } + + @Override + public void onDestroyView() { + //当Fragment被移除时被调用 + super.onDestroyView(); + } + + //对文本进行控制 + private void text_Control(){ + edt_describe.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);//多行文本输入 + edt_describe.setGravity(Gravity.TOP);//文本显示在最上方 + edt_describe.setSingleLine(false);//改变默认单行模式 + edt_describe.setHorizontallyScrolling(false);//取消水平滚动 + } + + @SuppressLint("CutPasteId") + private void addUI_Listener() { + but_addHonor = view.findViewById(R.id.but_addHonor); + img_imageHonor = view.findViewById(R.id.img_imgHonor); + edt_describe = view.findViewById(R.id.edt_contentHonor); + ll_inputHonor = view.findViewById(R.id.ll_inputHonor); + but_backHonor = view.findViewById(R.id.but_backHonor); + but_sureHonor = view.findViewById(R.id.but_sureHonor); + but_deleteHonor = view.findViewById(R.id.but_removeHonor); + tv_emptyHonor = view.findViewById(R.id.tv_emptyHonor); + + but_addHonor.setOnClickListener(this::onClick); + img_imageHonor.setOnClickListener(this::onClick); + but_backHonor.setOnClickListener(this::onClick); + but_sureHonor.setOnClickListener(this::onClick); + but_deleteHonor.setOnClickListener(this::onClick); + + //选择图片 + mFromAlumn = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback() { + @Override + public void onActivityResult(ActivityResult result) { + //用户取消选择图片 + if (result.getResultCode() == Activity.RESULT_OK) { + //用户选择了图片 + assert result.getData() != null; + Uri uri = result.getData().getData(); + checkImage = new Image(uriToBitmap(context,uri),uri.toString()); + img_imageHonor.setImageBitmap(checkImage.getImage()); + // 获取持久化权限 + context.getContentResolver().takePersistableUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + } + } + }); + } + + @SuppressLint("NonConstantResourceId") + private void onClick(View view) { + switch (view.getId()){ + case R.id.but_backHonor: + recyclerView.setVisibility(View.VISIBLE); + ll_inputHonor.setVisibility(View.GONE); + break; + case R.id.but_addHonor: + recyclerView.setVisibility(View.GONE); + ll_inputHonor.setVisibility(View.VISIBLE); + img_imageHonor.setImageResource(R.drawable.img_add); + break; + case R.id.but_removeHonor: + remove(); + break; + case R.id.img_imgHonor: + //检查权限 + if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this.getActivity(), + new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, + REQUEST_CODE_PERMISSION); + } + else { + //选择图片 + Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + // 指定显示图片 + intent.setType("image/*"); + mFromAlumn.launch(intent); + } + break; + case R.id.but_sureHonor: + if (edt_describe.getText().toString().trim().equals("")){ + Toast.makeText(context,"描述不能有空!",Toast.LENGTH_SHORT).show(); + } + else { + Honor honor = new Honor(String.valueOf(edt_describe.getText()),checkImage.getLocation()); + //保存到数据库中 + if (mHelper.insert_honor(honor) != -1){ + Toast.makeText(context,"添加成功!",Toast.LENGTH_SHORT).show(); + } + else Toast.makeText(context,"添加失败!",Toast.LENGTH_SHORT).show(); + + ll_inputHonor.setVisibility(View.GONE); + recyclerView.setVisibility(View.VISIBLE); + add(0, honor); + } + break; + } + } + + /*初始化列表*/ + private void initList() { + mHonorList.clear(); + List honorList = mHelper.query_honor_All(); + if (!honorList.isEmpty()){ + mHonorList.addAll(honorList); + //隐藏空提示 + tv_emptyHonor.setVisibility(View.GONE); + } + } + + private void setRecycleView() { + adapter = new HonorAdapter(mHonorList,context); + recyclerView = view.findViewById(R.id.rv_honor); + LinearLayoutManager layoutManager = new LinearLayoutManager(context,LinearLayoutManager.VERTICAL,false); + recyclerView.setLayoutManager(layoutManager); + + recyclerView.setAdapter(adapter); + } + /*添加子项*/ + private void add(int position, Honor honor){ + Log.d("Roommate_activity","添加子项!"); + + //tv_empty.setVisibility(View.GONE); + mHonorList.add(position,honor); + adapter.notifyItemInserted(position); + //隐藏空提示 + tv_emptyHonor.setVisibility(View.GONE); + } + /*删除子项*/ + @SuppressLint("NotifyDataSetChanged") + private void remove(){ + for(Honor honor:HonorAdapter.selectHonor){ + mHonorList.remove(honor); + mHelper.delete_honorByLocation(honor.getImageLocation()); + } + //更新RecycleView + adapter.notifyDataSetChanged(); + //将选中子项列表清空 + HonorAdapter.selectHonor.clear(); + //若子项全被清空,则出现“没有数据”提示 + if(mHonorList.isEmpty()) tv_emptyHonor.setVisibility(View.VISIBLE); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == REQUEST_CODE_PERMISSION) { + if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + // 权限已授予 + onClick(img_imageHonor); + } else { + // 权限被拒绝 + } + } + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Image.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Image.java new file mode 100644 index 0000000..7a1ae20 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/Image.java @@ -0,0 +1,31 @@ +package com.lh.app.ui.honor; + +import android.graphics.Bitmap; + +/** 图像信息类 */ +public class Image { + + private Bitmap image; + private String location; + + public Image(Bitmap image, String location) { + this.image = image; + this.location = location; + } + + public Bitmap getImage() { + return image; + } + + public void setImage(Bitmap image) { + this.image = image; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/ImageTools.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/ImageTools.java new file mode 100644 index 0000000..d1eb666 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/ImageTools.java @@ -0,0 +1,82 @@ +package com.lh.app.ui.honor; + +import android.app.Activity; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.net.Uri; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class ImageTools { + + /** + * 通过uri获取图片并进行压缩 + * + * @param uri + * @param activity + * @return + * @throws IOException + */ + public static Bitmap getBitmapFromUri(Uri uri, Activity activity) throws IOException { + InputStream inputStream = activity.getContentResolver().openInputStream(uri); + BitmapFactory.Options options = new BitmapFactory.Options(); + options.inJustDecodeBounds = true; + options.inDither = true; + options.inPreferredConfig = Bitmap.Config.ARGB_8888; + BitmapFactory.decodeStream(inputStream, null, options); + inputStream.close(); + + int originalWidth = options.outWidth; + int originalHeight = options.outHeight; + if (originalWidth == -1 || originalHeight == -1) { + return null; + } + + float height = 800f; + float width = 480f; + int be = 1; //be=1表示不缩放 + if (originalWidth > originalHeight && originalWidth > width) { + be = (int) (originalWidth / width); + } else if (originalWidth < originalHeight && originalHeight > height) { + be = (int) (originalHeight / height); + } + + if (be <= 0) { + be = 1; + } + BitmapFactory.Options bitmapOptinos = new BitmapFactory.Options(); + bitmapOptinos.inSampleSize = be; + bitmapOptinos.inDither = true; + bitmapOptinos.inPreferredConfig = Bitmap.Config.ARGB_8888; + inputStream = activity.getContentResolver().openInputStream(uri); + + Bitmap bitmap = BitmapFactory.decodeStream(inputStream, null, bitmapOptinos); + inputStream.close(); + + return compressImage(bitmap); + } + + /** + * 质量压缩方法 + * + * @param bitmap + * @return + */ + public static Bitmap compressImage(Bitmap bitmap) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, byteArrayOutputStream); + int options = 100; + while (byteArrayOutputStream.toByteArray().length / 1024 > 100) { + byteArrayOutputStream.reset(); + //第一个参数 :图片格式 ,第二个参数: 图片质量,100为最高,0为最差 ,第三个参数:保存压缩后的数据的流 + bitmap.compress(Bitmap.CompressFormat.JPEG, options, byteArrayOutputStream); + options -= 10; + } + ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray()); + Bitmap bitmapImage = BitmapFactory.decodeStream(byteArrayInputStream, null, null); + return bitmapImage; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/NotificationsViewModel.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/NotificationsViewModel.java new file mode 100644 index 0000000..cbb3ac1 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/honor/NotificationsViewModel.java @@ -0,0 +1,19 @@ +package com.lh.app.ui.honor; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class NotificationsViewModel extends ViewModel { + + private final MutableLiveData mText; + + public NotificationsViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is notifications fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/AddMemo_activity.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/AddMemo_activity.java new file mode 100644 index 0000000..a0b7cca --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/AddMemo_activity.java @@ -0,0 +1,228 @@ +package com.lh.app.ui.memo; + +import android.annotation.SuppressLint; +import android.content.ContentValues; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.text.InputType; +import android.util.Log; +import android.view.Gravity; +import android.view.View; +import android.widget.Button; +import android.widget.EditText; +import android.widget.RadioButton; +import android.widget.RadioGroup; +import android.widget.TextClock; +import android.widget.Toast; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; + +import com.lh.app.MainActivity; +import com.lh.app.MyApplication; +import com.lh.app.R; +import com.lh.app.RoommateDBHelper; +import com.lh.app.tool.NotificationUtil; + +public class AddMemo_activity extends AppCompatActivity { + + private TextClock clock; + private EditText title_edt; + private EditText content_edt; + private Button back_button; + private Button success_button; + private RadioGroup group; + private String select_roommateName = "全部";//选择室友 + + public static boolean is_backData = false;//是否带回数据 + public static Memo jumpMemo = null; //修改前对应的Memo + public static boolean is_revise = false;//是否修改数据 + //数据库帮助器对象实例 + private RoommateDBHelper mHelper = MyApplication.mHelper; + + @SuppressLint("NonConstantResourceId") + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.add_memo_activity_layout); + + addUI(); + //判断点击打开页面来源,以下来自子项的点击,即修改内容 + if(is_revise){ + //获取传入数据 + jumpMemo = Roommate_memo_adapter.jumpMemo; + //对控件文本及状态进行填充 + title_edt.setText(jumpMemo.getTitle()); + content_edt.setText(jumpMemo.getContent()); + switch (jumpMemo.getName()){ + case "全部": + group.check(R.id.btn_all); + break; + case "刘治浩": + group.check(R.id.btn_lzh); + break; + case "谭宗辉": + group.check(R.id.btn_tzh); + break; + case "樊彪": + group.check(R.id.btn_fb); + break; + case "李石尧": + group.check(R.id.btn_lsy); + break; + } + } + else { + title_edt.setText(""); + content_edt.setText(""); + } + text_Control(); + Menu_part(); + } + + /*添加组件*/ + @SuppressLint("NonConstantResourceId") + private void addUI(){ + back_button = (Button) findViewById(R.id.back_button); + success_button = (Button)findViewById(R.id.success_button) ; + title_edt = (EditText)findViewById(R.id.title_edt) ; + content_edt = (EditText) findViewById(R.id.content_edt); + clock = (TextClock) findViewById(R.id.clock); + group = (RadioGroup)findViewById(R.id.radioGroup) ; + + /*对菜单栏按钮点击事件监听*/ + back_button.setOnClickListener(this::onclick); + success_button.setOnClickListener(this::onclick); + group.setOnCheckedChangeListener(radioChangeListener); + } + //RadioGroup监听器 + @SuppressLint("NonConstantResourceId") + private final RadioGroup.OnCheckedChangeListener radioChangeListener = new RadioGroup.OnCheckedChangeListener(){ + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + switch (checkedId) { + case R.id.btn_all: + RadioButton radioButton_01 = AddMemo_activity.this.findViewById(R.id.btn_all); + select_roommateName = radioButton_01.getText().toString(); + break; + case R.id.btn_lzh: + RadioButton radioButton_02 = AddMemo_activity.this.findViewById(R.id.btn_lzh); + select_roommateName = radioButton_02.getText().toString(); + break; + case R.id.btn_tzh: + RadioButton radioButton_03 = AddMemo_activity.this.findViewById(R.id.btn_tzh); + select_roommateName = radioButton_03.getText().toString(); + break; + case R.id.btn_fb: + RadioButton radioButton_04 = AddMemo_activity.this.findViewById(R.id.btn_fb); + select_roommateName = radioButton_04.getText().toString(); + break; + case R.id.btn_lsy: + RadioButton radioButton_05 = AddMemo_activity.this.findViewById(R.id.btn_lsy); + select_roommateName = radioButton_05.getText().toString(); + break; + } + Toast.makeText(AddMemo_activity.this, "name:" + select_roommateName, Toast.LENGTH_SHORT).show(); + } + }; + //按钮点击事件 + @SuppressLint("NonConstantResourceId") + private void onclick(View view){ + switch (view.getId()){ + case R.id.back_button: + is_backData = false; + is_revise = false; + + MainActivity.isShowViewPage_memo = true; + Intent intent = new Intent(AddMemo_activity.this,MainActivity.class); + startActivity(intent); + finish();//销毁当前活动 + break; + case R.id.success_button: + //将数据存入内存 + String name = select_roommateName; + String title = String.valueOf(title_edt.getText()); + String content = String.valueOf(content_edt.getText()); + String now_time = (String)clock.getText(); + //对输入进行判断 + if (!title.equals("") && !content.equals("")) { + //打印存入数据 + String date =String.format(title+" "+content+" "+now_time+" %s", name); + Log.d("Roommate_activity","存入数据:"+date); + Memo memo = new Memo(name,title,content,now_time); + //将增加数据存入数据库 + ContentValues values01 = new ContentValues(); + values01.put("name", select_roommateName); + values01.put("title",title); + values01.put("content",content); + values01.put("date",now_time); + values01.put("isDelete",false); + values01.put("isRevise",false); + mHelper.insert(RoommateDBHelper.getTableNameRoommateMemo(),values01); + if (is_revise){ + mHelper.update_roommateMemo(jumpMemo,true,true); + } + else { + //将增加数据存入数据库 + ContentValues values02 = new ContentValues(); + values02.put("name", select_roommateName); + values02.put("title",title); + values02.put("content",content); + values02.put("date",now_time); + values02.put("isDelete",false); + values02.put("isRevise",true); + mHelper.insert(RoommateDBHelper.getTableNameRoommateMemo(),values02); + } + //通知显示 + notification(memo); + //返回界面 + is_backData = true; + jumpMemo = null; + is_revise = false; + Roommate_memo_adapter.jumpMemo = null; + + Toast.makeText(this, "完成", Toast.LENGTH_SHORT).show(); + Log.d("Roommate_activity","返回!"); + //重新转跳到首界面 + MainActivity.isShowViewPage_memo = true; + intent = new Intent(AddMemo_activity.this,MainActivity.class); + startActivity(intent); + finish(); + } + else Toast.makeText(this, "标题和内容不能为空", Toast.LENGTH_SHORT).show(); + break; + } + + } + //通知提醒 + private void notification(Memo memo){ + // + NotificationUtil notificationUtil; + if(is_revise){ + notificationUtil = new NotificationUtil(this,"修改通知","您在备忘录中修改了一条通知!!!", + R.drawable.add_small_icon, BitmapFactory.decodeResource(getResources(),memo.getImgID() )); + } + else { + notificationUtil = new NotificationUtil(this,"添加通知","您在备忘录中添加了一条通知!!!", + R.drawable.add_small_icon, BitmapFactory.decodeResource(getResources(), memo.getImgID())); + } + notificationUtil.notification(); + } + + //对文本进行控制 + private void text_Control(){ + content_edt.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE);//多行文本输入 + content_edt.setGravity(Gravity.TOP);//文本显示在最上方 + content_edt.setSingleLine(false);//改变默认单行模式 + content_edt.setHorizontallyScrolling(false);//取消水平滚动 + } + /*菜单栏编写*/ + private void Menu_part(){ + /*隐藏菜单栏*/ + ActionBar actionBar = getSupportActionBar(); + if(actionBar != null){ + actionBar.hide(); + } + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/HomeViewModel.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/HomeViewModel.java new file mode 100644 index 0000000..34651d8 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/HomeViewModel.java @@ -0,0 +1,19 @@ +package com.lh.app.ui.memo; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; +import androidx.lifecycle.ViewModel; + +public class HomeViewModel extends ViewModel { + + private final MutableLiveData mText; + + public HomeViewModel() { + mText = new MutableLiveData<>(); + mText.setValue("This is home fragment"); + } + + public LiveData getText() { + return mText; + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Memo.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Memo.java new file mode 100644 index 0000000..b643532 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Memo.java @@ -0,0 +1,45 @@ +package com.lh.app.ui.memo; + +import com.lh.app.R; + +/** + * Created by LiShiyao on 2022/10/5. + */ +public class Memo { + private String name; + private String title; + private String content; + private String date; + + public Memo(){} + public Memo(String name, String title, String content, String time){ + this.name = name; + this.title = title; + this.content = content; + this.date = time; + } + public Memo(String title, String content){ + this.title = title; + this.content = content; + } + + public String getName() { + return name; + } + public String getTitle(){ + return title; + } + public String getContent(){ + return content; + } + public String getDate(){ + return date; + } + public int getImgID(){ + if ("全部".equals(name)) return R.drawable.img_dog1; + else if ("刘治浩".equals(name)) return R.drawable.hyt; + else if ("谭宗辉".equals(name)) return R.drawable.pyy; + else if ("樊彪".equals(name)) return R.drawable.yyqx; + else return R.drawable.dc; + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/MemoFragment.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/MemoFragment.java new file mode 100644 index 0000000..1f09730 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/MemoFragment.java @@ -0,0 +1,307 @@ +package com.lh.app.ui.memo; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.lh.app.MyApplication; +import com.lh.app.R; +import com.lh.app.RoommateDBHelper; +import com.lh.app.tool.NotificationUtil; + +import java.util.ArrayList; +import java.util.List; + +public class MemoFragment extends Fragment { + //数据库帮助器对象实例 + private RoommateDBHelper mHelper = MyApplication.mHelper; + //recycleView中子项列表 + private List memoList = new ArrayList<>(); + private Roommate_memo_adapter adapter; + //空数据文本 + private TextView tv_empty; + //备忘录子项数量 + private int memoNum = 0; + //定义菜单项标识 + private final int REMOVE = 110; + private final int ADD = 111; + private final int REVISE = 112; + //活动视图 + private View view; + //上下文 + private Context context; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + Log.d("fragment_memo","onCreate"); + //Fragment被创建时,被调用 + super.onCreate(savedInstanceState); + //指出fragment愿意添加item到选项菜单 + setHasOptionsMenu(true); + + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + Log.d("fragment_memo","onCreateView"); + //获取活动视图和活动上下文 + view = inflater.inflate(R.layout.fragment_memo,container,false); + context = getActivity(); + //将选中子项列表清空 + Roommate_memo_adapter.checkList.clear(); + //设置recycleView配置 + setRecycleView(); + addUI_and_Listener(); + //初始化备忘录列表和备忘录行数 + initList(); + return view; + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + Log.d("fragment_memo","onActivityCreated"); + } + + @Override + public void onStart() { + //无焦点但可见时,调用此方法 + super.onStart(); + Log.d("fragment_memo","onStart"); + + } + + @Override + public void onPause() { + //Fragment失去焦点但可见时,调用此方法. + super.onPause(); + Log.d("fragment_memo","onPause"); + } + + @Override + public void onStop() { + //Fragment不可见时,调用此方法. + super.onStop(); + Log.d("fragment_memo","onStop"); + } + + @Override + public void onDestroyView() { + //当Fragment被移除时被调用 + super.onDestroyView(); + Log.d("fragment_memo","onDestroyView"); + } + /*添加组件及其监听器*/ + private void addUI_and_Listener(){ + Button but_add = view.findViewById(R.id.add_but); + Button remove_btn = view.findViewById(R.id.remove_btn); + Button clear_btn = view.findViewById(R.id.clear_btn); + tv_empty = view.findViewById(R.id.empty_tv); + + but_add.setOnClickListener(this::onClick); + remove_btn.setOnClickListener(this::onClick); + clear_btn.setOnClickListener(this::onClick); + } + /*设置RecycleView样式*/ + private void setRecycleView() { + //竖直流布局 + RecyclerView recyclerView = view.findViewById(R.id.recycleView_horizontal); + LinearLayoutManager LayoutManager2 = new LinearLayoutManager(context); + //LayoutManager2.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView.setLayoutManager(LayoutManager2); + adapter = new Roommate_memo_adapter(memoList); + recyclerView.setAdapter(adapter); + } + /*初始化recycleView列表*/ + private void initList() { + //更新文件行数 + memoNum = mHelper.query_roommateMemo_rowsNumByType(false,false); + Log.d("Roommate_activity","文件行数:"+ memoNum); + //若备忘录子项不为0,则添加到recycleView中 + if (memoNum !=0){ + //先清空序列 + memoList.clear(); + //取备忘录中被显示数据 + List memoList = mHelper.query_roommateMemoByType(false,false); + for (Memo memo:memoList){ + add(0,memo); + } + } + } + + //点击事件 + @SuppressLint("NonConstantResourceId") + private void onClick(View view) { + switch (view.getId()){ + case R.id.add_but: + Intent intent = new Intent(context, AddMemo_activity.class); + startActivity(intent); + + getActivity().finish(); + + break; + case R.id.remove_btn: + remove(); + break; + case R.id.clear_btn: + //弹出弹框提示 + new AlertDialog.Builder(context) + .setTitle("信息提示") + .setMessage("确认全删除?") + .setPositiveButton("是", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//确认按钮监听事件 + //请空子项、清空备忘录表中数据、弹出通知、更新备忘录子项数 + clear(); + //弹框消失 + dialog.dismiss(); + } + }) + .setNegativeButton("否", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//返回按钮监听事件 + dialog.dismiss(); + } + }).show();//显示弹框 + break; + default: + throw new IllegalStateException("Unexpected value: " + view); + } + } + + /*添加子项*/ + private void add(int position,Memo memo){ + Log.d("Roommate_activity","添加子项!"); + tv_empty.setVisibility(View.GONE); + memoList.add(position,memo); + adapter.notifyItemInserted(position); + } + + /*删除子项*/ + @SuppressLint("NotifyDataSetChanged") + private void remove(){ + //获取要被删除子项列表 + List checklist = Roommate_memo_adapter.checkList; + int remove_num = checklist.size(); + //判断是否有要被删除的子项 + if (remove_num == 0) { + Toast.makeText(context, "请选择数据!!!", Toast.LENGTH_SHORT).show(); + } + else { + //循环删除被选中子项 + while(checklist.size()!=0){ + Memo memo = checklist.get(0); + //删除在子项列表中位置 + memoList.remove(memo); + //修改备忘录表中被删除子项type为删除状态(1,0) + mHelper.update_roommateMemo(memo,true,false); + //删除被选中子项列表位置 + Roommate_memo_adapter.checkList.remove(0); + } + //更新文件行数 + memoNum = mHelper.query_roommateMemo_rowsNumByType(false,false); + //更新RecycleView + adapter.notifyDataSetChanged(); + //将选中子项列表清空 + Roommate_memo_adapter.checkList.clear(); + //若子项全被清空,则出现“没有数据”提示 + if(memoList.size()==0) tv_empty.setVisibility(View.VISIBLE); + //显示删除通知 + show_TypeOfDeleteNotification(remove_num); + } + } + + + /*清空子项*/ + @SuppressLint("NotifyDataSetChanged") + private void clear(){ + if (memoList.size()!=0){ + //清空recycleView中子项 + memoList.clear(); + adapter.notifyDataSetChanged(); + //出现空数据提示 + tv_empty.setVisibility(View.VISIBLE); + + //修改备忘录表中被删除子项type + mHelper.update_roommateAllMemoToDelete(); + + //显示删除通知 + show_TypeOfDeleteNotification(memoNum); + //更新备忘录子项数为0 + memoNum = 0; + } + else Toast.makeText(context, "子项已被清空", Toast.LENGTH_SHORT).show(); + + } + + //显示删除通知 + private void show_TypeOfDeleteNotification(int remove_num){ + NotificationUtil notificationUtil = new NotificationUtil(context,"删除通知", + "您在备忘录中删除了"+remove_num+"条通知!!!",R.drawable.add_small_icon, + BitmapFactory.decodeResource(getResources(),R.drawable.remove_large_icon)); + notificationUtil.notification(); + } + + /*重写顶部菜单栏菜单键*/ + @Override + public boolean onOptionsItemSelected(@NonNull MenuItem item) { + int id = item.getItemId(); + Intent intent = new Intent(context,Story_activity.class); + switch (id){ + case REMOVE: + Toast.makeText(context, "删除记录", Toast.LENGTH_SHORT).show(); + Story_activity.open_type = 1; + startActivity(intent); + break; + case ADD: + Toast.makeText(context, "添加记录", Toast.LENGTH_SHORT).show(); + Story_activity.open_type = 2; + startActivity(intent); + break; + case REVISE: + Toast.makeText(context, "修改记录", Toast.LENGTH_SHORT).show(); + Story_activity.open_type = 3; + startActivity(intent); + break; + case android.R.id.home: + //no + return true; + default: + break; + } + return super.onOptionsItemSelected(item); + } + + /** + * 重写菜单栏中选项,完成菜单初始化 + * 与在activity中添加有区别 + * */ + @Override + public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) { + super.onCreateOptionsMenu(menu, inflater); + menu.add(0,REMOVE,1,"删除记录"); + menu.add(0,ADD,2,"增加记录"); + menu.add(0,REVISE,3,"修改记录"); + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Roommate_memo_adapter.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Roommate_memo_adapter.java new file mode 100644 index 0000000..f1cadf8 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Roommate_memo_adapter.java @@ -0,0 +1,166 @@ +package com.lh.app.ui.memo; + +import android.annotation.SuppressLint; +import android.content.Intent; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.RelativeLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.lh.app.R; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by LiShiyao on 2022.10.5 + */ +public class Roommate_memo_adapter extends RecyclerView.Adapter { + private List mMemoList; + //选中的数据 + public static List checkList = new ArrayList<>(); + //跳转至AddMemo界面携带的Memo + public static Memo jumpMemo = null; + public static int click_type = 1;//默认打开编辑界面 + + /** + * 定义一个内部类,继承自RecyclerView.ViewHolder + * */ + static class ViewHolder extends RecyclerView.ViewHolder{ + View memoView; + ImageView memoImage; + CheckBox isSelect; + RelativeLayout body_rel; + TextView memoTitle; + TextView memoContent; + TextView memoDate; + //修改 + LinearLayout lil_showInfo; + ImageView img_back_showInfo; + TextView tv_title_showInfo; + TextView tv_date_showInfo; + TextView tv_content_showInfo; + TextView tv_roommate_showInfo; + + // 作用:获取布局中的组件实例 + // view参数 最外层布局(小方块) + public ViewHolder(View view){ + super(view); + memoView = view; + memoImage = view.findViewById(R.id.memo_image); + isSelect = view.findViewById(R.id.ck_select); + body_rel = view.findViewById(R.id.body_rel); + memoTitle = view.findViewById(R.id.title_tev); + memoContent = view.findViewById(R.id.content_tev); + memoDate = view.findViewById(R.id.date_tv); + lil_showInfo = view.findViewById(R.id.lil_showInfo); + img_back_showInfo = view.findViewById(R.id.img_back_showInfo); + tv_title_showInfo = view.findViewById(R.id.tv_title_showInfo); + tv_date_showInfo = view.findViewById(R.id.tv_date_showInfo); + tv_content_showInfo = view.findViewById(R.id.tv_content_showInfo); + tv_roommate_showInfo = view.findViewById(R.id.tv_roommate_showInfo); + } + } + + /** + * 构造函数 + * 作用:把要展示的数据源传进来 + * */ + public Roommate_memo_adapter(List memoList){ + mMemoList = memoList; + } + + + //因为继承自RecyclerView.Adapter,必须重写onCreateViewHolder()、onBindViewHolder()、getItemCount() + /** + * onCreateViewHolder()用于创建ViewHolder实例方法 + * onBindViewHolder() 用于对recycleView子项的数据进行赋值(在子项滚入屏幕时执行) + * getItemCount() 告诉recycleView有多少个子项 + * */ + @SuppressLint("NonConstantResourceId") + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view; + //1.加载布局 + view = LayoutInflater.from(parent.getContext()).inflate(R.layout.memo_item,parent,false); + //2.创建ViewHolder实例 + final ViewHolder holder = new ViewHolder(view); + //3.创建点击事件 + //为view (小方块)创建监听事件 + + holder.body_rel.setOnClickListener(view1 -> { + if (click_type==1){//在备忘录界面点击子项 + int position = holder.getAdapterPosition(); + Memo memo = mMemoList.get(position); + jumpMemo = memo;//携带的Memo跳转 + AddMemo_activity.is_revise = true; + //跳转界面 + Intent intent = new Intent(view.getContext(), AddMemo_activity.class); + view.getContext().startActivity(intent); + } + + if (click_type==2){//在增、删、改界面上点击 + holder.lil_showInfo.setVisibility(View.VISIBLE); + int position = holder.getAdapterPosition(); + Memo memo = mMemoList.get(position); + holder.tv_title_showInfo.setText(memo.getTitle()); + holder.tv_date_showInfo.setText(memo.getDate()); + holder.tv_content_showInfo.setText(memo.getContent()); + holder.tv_roommate_showInfo.setText(memo.getName()); + //禁用单选按钮,若被选中,取消选中 + if (holder.isSelect.isChecked()) holder.isSelect.setChecked(false); + holder.isSelect.setEnabled(false); + } + //Toast.makeText(view.getContext(),"you clicked view " +memo.getImageId(),Toast.LENGTH_SHORT).show(); + }); + holder.img_back_showInfo.setOnClickListener(view1 -> { + holder.lil_showInfo.setVisibility(View.GONE); + //启用单选按钮 + holder.isSelect.setEnabled(true); + }); + + //4.返回ViewHolder实例 + return holder; + } + + @SuppressLint("SetTextI18n") + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + //通过position参数 获得当前 Memo 实例 + Memo memo = mMemoList.get(position); + //获得子项数据 + holder.memoImage.setImageResource(memo.getImgID()); + holder.memoTitle.setText(memo.getTitle()); + //防止文本过长 + String content = memo.getContent(); + if (content.length()>14){ + holder.memoContent.setText(content.substring(0,14)+"..."); + } + else holder.memoContent.setText(content); + + holder.memoDate.setText(memo.getDate()); + //为checkBox创建监听事件 + holder.isSelect.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + //单选按钮被选中,将memo加入队列,否则退出队列 + if(isChecked) checkList.add(memo); + if (!isChecked) checkList.remove(memo); + } + }); + } + + @Override + public int getItemCount() { + return mMemoList.size(); + } +} diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Story_activity.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Story_activity.java new file mode 100644 index 0000000..483d47e --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/memo/Story_activity.java @@ -0,0 +1,290 @@ +package com.lh.app.ui.memo; + +import android.annotation.SuppressLint; +import android.app.AlertDialog; +import android.content.DialogInterface; +import android.graphics.BitmapFactory; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import com.lh.app.MyApplication; +import com.lh.app.R; +import com.lh.app.RoommateDBHelper; +import com.lh.app.tool.NotificationUtil; + +import java.util.ArrayList; +import java.util.List; + +public class Story_activity extends AppCompatActivity { + private RecyclerView recyclerView_story; + private Roommate_memo_adapter adapter; + private List memoList = new ArrayList<>(); + + private int memoNum = 0; + + private Button btn_clear_story; + private TextView tv_empty; + private TextView tv_story_type; + private Button btn_back; + private Button but_remove_story; + private LinearLayout lil_showInfo; + + public static int open_type = 0;//1:删除记录、2:增加记录、3:修改记录 + + //数据库帮助器对象实例 + private RoommateDBHelper mHelper = MyApplication.mHelper; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_story); + //将选中子项列表清空 + Roommate_memo_adapter.checkList.clear(); + Roommate_memo_adapter.click_type = 2;//点击子项出现详情1->2 + + addUI_and_listener();//添加UI和监听器 + setTopPart();//顶部菜单隐藏 + setRecycleView(); + initList(); + + } + //添加UI和监听器 + private void addUI_and_listener() { + btn_clear_story = (Button) findViewById(R.id.btn_clear_story); + tv_empty = (TextView) findViewById(R.id.empty_tv_story); + btn_back = (Button) findViewById(R.id.but_back_04) ; + tv_story_type = (TextView) findViewById(R.id.tv_title_04); + but_remove_story = (Button)findViewById(R.id.but_remove_story) ; + + + btn_clear_story.setOnClickListener(this::onclick); + btn_back.setOnClickListener(this::onclick); + but_remove_story.setOnClickListener(this::onclick); + } + @SuppressLint("NonConstantResourceId") + private void onclick(View view){ + switch (view.getId()){ + case R.id.but_back_04: + //将选中子项列表清空 + Roommate_memo_adapter.checkList.clear(); + //恢复点击子项显示编辑界面2->1 + Roommate_memo_adapter.click_type = 1; + finish(); + break; + case R.id.but_remove_story: + remove(); + break; + case R.id.btn_clear_story: + //弹出弹框提示 + new AlertDialog.Builder(Story_activity.this) + .setTitle("信息提示") + .setMessage("确认全删除?") + .setPositiveButton("是", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//确认按钮监听事件 + //请空子项 + clear(); + //弹框消失 + dialog.dismiss(); + } + }) + .setNegativeButton("否", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int i) {//返回按钮监听事件 + dialog.dismiss(); + } + }).show();//显示弹框 + break; + } + } + /*初始化recycleView列表*/ + private void initList() { + //更新文件行数 + updateMemoNum(); + Log.d("Roommate_activity","文件行数:"+ memoNum); + //若备忘录子项不为0,则添加到recycleView中 + if (memoNum !=0){ + //先清空序列 + memoList.clear(); + //取备忘录中被显示数据 + List memoList = getMemoList(); + for (Memo memo:memoList){ + add(0,memo);//向recycleView开头插入子项 + } + } + } + /*添加子项*/ + private void add(int position,Memo memo){ + Log.d("Roommate_activity","添加子项!"); + tv_empty.setVisibility(View.GONE); + memoList.add(position,memo); + adapter.notifyItemInserted(position); + } + + /*删除子项*/ + @SuppressLint("NotifyDataSetChanged") + private void remove(){ + //获取要被删除子项列表 + List checklist = Roommate_memo_adapter.checkList; + int remove_num = checklist.size(); + //判断是否有要被删除的子项 + if (remove_num == 0) { + Toast.makeText(this, "请选择数据!!!", Toast.LENGTH_SHORT).show(); + } + else { + //循环删除被选中子项 + while(checklist.size()!=0){ + Memo memo = checklist.get(0); + //删除在子项列表中位置 + memoList.remove(memo); + //删除在数据库中位置 + deleteMemo(memo); + //删除被选中子项列表位置 + Roommate_memo_adapter.checkList.remove(0); + + } + //更新文件行数 + memoNum = mHelper.query_roommateMemo_rowsNumByType(false,false); + //更新RecycleView + adapter.notifyDataSetChanged(); + //将选中子项列表清空 + Roommate_memo_adapter.checkList.clear(); + //若子项全被清空,则出现“没有数据”提示 + if(memoList.size()==0) tv_empty.setVisibility(View.VISIBLE); + //显示删除通知 + show_TypeOfDeleteNotification(remove_num); + } + } + + + + /*清空子项*/ + @SuppressLint("NotifyDataSetChanged") + private void clear(){ + if (memoList.size()!=0){ + //清空recycleView中子项 + memoList.clear(); + adapter.notifyDataSetChanged(); + //出现空数据提示 + tv_empty.setVisibility(View.VISIBLE); + //清空文件数据 + deleteAllTypeMemo(); + //显示删除通知 + show_TypeOfDeleteNotification(memoNum); + //更新备忘录子项数为0 + memoNum = 0; + } + else Toast.makeText(this, "子项已被清空", Toast.LENGTH_SHORT).show(); + + } + + + //显示删除通知 + private void show_TypeOfDeleteNotification(int remove_num){ + NotificationUtil notificationUtil = new NotificationUtil(this,"删除通知", + "您在备忘录中删除了"+remove_num+"条通知!!!",R.drawable.add_small_icon, + BitmapFactory.decodeResource(getResources(),R.drawable.remove_large_icon)); + notificationUtil.notification(); + } + + /*设置RecycleView样式*/ + private void setRecycleView() { + //竖直流布局 + recyclerView_story = (RecyclerView) findViewById(R.id.recycleView_story); + LinearLayoutManager LayoutManager2 = new LinearLayoutManager(this); + //LayoutManager2.setOrientation(LinearLayoutManager.VERTICAL); + recyclerView_story.setLayoutManager(LayoutManager2); + adapter = new Roommate_memo_adapter(memoList); + recyclerView_story.setAdapter(adapter); + } + + /** + * 隐藏菜单栏和设置菜单标题 + * */ + private void setTopPart(){ + //隐藏菜单栏 + ActionBar actionBar = getSupportActionBar(); + if(actionBar != null){ + actionBar.hide(); + } + //设置菜单标题 + switch (open_type) { + case 1: + tv_story_type.setText("删除记录"); + break; + case 2: + tv_story_type.setText("增加记录"); + break; + case 3: + tv_story_type.setText("修改记录"); + break; + } + } + /*更新文件行数*/ + private void updateMemoNum(){ + switch (open_type) { + case 1: + memoNum = mHelper.query_roommateMemo_rowsNumByType(true,false); + break; + case 2: + memoNum = mHelper.query_roommateMemo_rowsNumByType(false,true); + break; + case 3: + memoNum = mHelper.query_roommateMemo_rowsNumByType(true,true); + break; + } + } + //取备忘录中指定数据 + private List getMemoList(){ + switch (open_type) { + case 1: + return mHelper.query_roommateMemoByType(true,false); + case 2: + return mHelper.query_roommateMemoByType(false,true); + case 3: + return mHelper.query_roommateMemoByType(true,true); + } + return null; + } + //删除数据库备忘录表中指定类型数据 + private void deleteMemo(Memo memo) { + long row = 0; + switch (open_type) { + case 1: + //删除删除子项(1,0) + row = mHelper.deleteMemoByType(memo,true,false); + break; + case 2: + //删除增加子项(1,0) + row = mHelper.deleteMemoByType(memo,false,true); + break; + case 3: + //删除修改子项(1,0) + row = mHelper.deleteMemoByType(memo,true,true); + break; + } + Log.d("delete"+open_type+"型","删除第"+row+"行"); + } + //删除数据库备忘录表中指定类型全部数据 + private void deleteAllTypeMemo() { + switch (open_type) { + case 1: + mHelper.deleteMemoAllType(true,false); + case 2: + mHelper.deleteMemoAllType(false,true); + case 3: + mHelper.deleteMemoAllType(true,true); + } + } + +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/java/com/lh/app/ui/mine/MineFragment.java b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/mine/MineFragment.java new file mode 100644 index 0000000..0f2e7d6 --- /dev/null +++ b/CODE/RommteStory/app/src/main/java/com/lh/app/ui/mine/MineFragment.java @@ -0,0 +1,459 @@ +package com.lh.app.ui.mine; + +import android.Manifest; +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.DialogInterface; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.location.Address; +import android.location.Geocoder; +import android.location.Location; +import android.location.LocationManager; +import android.net.ConnectivityManager; +import android.net.NetworkInfo; +import android.os.Bundle; +import android.os.Looper; +import android.provider.Settings; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AlertDialog; +import androidx.core.app.ActivityCompat; +import androidx.fragment.app.Fragment; + +import com.amap.api.location.AMapLocation; +import com.amap.api.location.AMapLocationClient; +import com.amap.api.location.AMapLocationClientOption; +import com.amap.api.location.AMapLocationListener; +import com.amap.api.maps.AMap; +import com.amap.api.maps.CameraUpdateFactory; +import com.amap.api.maps.LocationSource; +import com.amap.api.maps.MapView; +import com.amap.api.maps.model.LatLng; +import com.amap.api.maps.model.MyLocationStyle; +import com.google.android.gms.location.FusedLocationProviderClient; +import com.google.android.gms.location.LocationCallback; +import com.google.android.gms.location.LocationRequest; +import com.google.android.gms.location.LocationResult; +import com.google.android.gms.location.LocationServices; +import com.google.android.gms.tasks.OnSuccessListener; +import com.lh.app.R; + +import java.io.IOException; +import java.util.List; +import java.util.Locale; + +/** + * 高德地图定位Fragment + * 需要权限: + * - android.permission.ACCESS_FINE_LOCATION + * - android.permission.ACCESS_COARSE_LOCATION + * - android.permission.INTERNET + * - android.permission.ACCESS_NETWORK_STATE + */ +public class MineFragment extends Fragment implements AMapLocationListener, LocationSource { + + private static final int LOCATION_PERMISSION_REQUEST_CODE = 1; + private static final int REQUEST_ENABLE_GPS = 2; + + private FusedLocationProviderClient fusedLocationClient; + + private MapView mapView; + private AMap aMap; + private TextView tvLocation; + private Button btnLocation; + + // 高德定位相关 + private AMapLocationClient locationClient; + private AMapLocationClientOption locationOption; + private OnLocationChangedListener mapLocationListener; + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + // 设置隐私合规接口 + AMapLocationClient.updatePrivacyShow(getContext(), true, true); + AMapLocationClient.updatePrivacyAgree(getContext(), true); + fusedLocationClient = LocationServices.getFusedLocationProviderClient(getContext()); + } + + @Override + public View onCreateView(@NonNull LayoutInflater inflater, + ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.fragment_mine, container, false); + initViews(view); + initMap(savedInstanceState, view); + return view; + } + + private void initViews(View view) { + tvLocation = view.findViewById(R.id.text_location); + btnLocation = view.findViewById(R.id.btn_getLocation); + btnLocation.setOnClickListener(v -> checkLocationAndPermission()); + } + + private void initMap(Bundle savedInstanceState, View view) { + mapView = view.findViewById(R.id.mapView); + mapView.onCreate(savedInstanceState); + + if (aMap == null) { + aMap = mapView.getMap(); + setupMap(); + } + } + + private void setupMap() { + // 设置地图参数 + aMap.getUiSettings().setZoomControlsEnabled(true); + aMap.getUiSettings().setMyLocationButtonEnabled(false); // 使用自定义按钮 + + // 设置定位蓝点样式 + MyLocationStyle myLocationStyle = new MyLocationStyle(); + myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE); + myLocationStyle.interval(5000); // 定位间隔 + myLocationStyle.strokeColor(android.R.color.transparent); + myLocationStyle.radiusFillColor(0x500000FF); + aMap.setMyLocationStyle(myLocationStyle); + + // 设置定位源 + aMap.setLocationSource(this); + aMap.setMyLocationEnabled(true); + } + + private void checkLocationAndPermission() { + if (!isNetworkConnected()) { + showNetworkDisconnectedAlert(); + return; + } + if (!isGpsEnabled()) { + showGpsDisabledAlert(); + return; + } + + if (hasLocationPermission()) { + startLocation(); + } else { + requestLocationPermission(); + } + } + + private boolean isGpsEnabled() { + LocationManager manager = (LocationManager) requireContext() + .getSystemService(Context.LOCATION_SERVICE); + return manager.isProviderEnabled(LocationManager.GPS_PROVIDER); + } + + private void showGpsDisabledAlert() { + new AlertDialog.Builder(requireContext()) + .setTitle("GPS未开启") + .setMessage("需要开启GPS才能获取精确位置") + .setPositiveButton("去设置", (dialog, which) -> { + Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS); + startActivityForResult(intent, REQUEST_ENABLE_GPS); + }) + .setNegativeButton("取消", null) + .show(); + } + + private boolean hasLocationPermission() { + return ActivityCompat.checkSelfPermission(requireContext(), + Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && + ActivityCompat.checkSelfPermission(requireContext(), + Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; + } + + private void requestLocationPermission() { + if (shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_FINE_LOCATION) || + shouldShowRequestPermissionRationale(Manifest.permission.ACCESS_COARSE_LOCATION)) { + new AlertDialog.Builder(requireContext()) + .setTitle("需要位置权限") + .setMessage("应用需要位置权限来提供定位服务") + .setPositiveButton("确定", (dialog, which) -> { + requestPermissions( + new String[]{ + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + }, + LOCATION_PERMISSION_REQUEST_CODE); + }) + .setNegativeButton("取消", null) + .show(); + } else { + requestPermissions( + new String[]{ + Manifest.permission.ACCESS_FINE_LOCATION, + Manifest.permission.ACCESS_COARSE_LOCATION + }, + LOCATION_PERMISSION_REQUEST_CODE); + } + } + + private void startLocation() { + requestLocationUpdates(); + if (locationClient == null) { + initLocationClient(); + } + + if (!locationClient.isStarted()) { + locationClient.startLocation(); + btnLocation.setText("定位中..."); + } + } + + @SuppressLint("MissingPermission") + private void getLastLocation() { + fusedLocationClient.getLastLocation() + .addOnSuccessListener(requireActivity(), new OnSuccessListener() { + @Override + public void onSuccess(Location location) { + if (location != null) { + // 获取到位置信息 + double latitude = location.getLatitude(); + double longitude = location.getLongitude(); + Log.d("Location", "Latitude: " + latitude + ", Longitude: " + longitude); + } else { + // 位置信息为空 + Log.d("Location", "No location found"); + } + } + }); + } + private void requestLocationUpdates() { + LocationRequest locationRequest = LocationRequest.create(); + locationRequest.setInterval(10000); // 更新间隔 + locationRequest.setFastestInterval(5000); // 最快更新间隔 + locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); // 高精度模式 + + LocationCallback locationCallback = new LocationCallback() { + @Override + public void onLocationResult(LocationResult locationResult) { + if (locationResult == null) { + return; + } + for (Location location : locationResult.getLocations()) { + Log.d("Location", "Latitude: " + location.getLatitude() + ", Longitude: " + location.getLongitude()); + getAddressFromLocation(location.getLatitude(),location.getLongitude()); + } + } + }; + + if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { + return; + } + fusedLocationClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper()); + } + + private void getAddressFromLocation(double latitude, double longitude) { + Geocoder geocoder = new Geocoder(getContext(), Locale.getDefault()); + try { + List
addresses = geocoder.getFromLocation(latitude, longitude, 1); + if (addresses != null && addresses.size() > 0) { + Address address = addresses.get(0); + String province = address.getAdminArea(); // 省 + String city = address.getLocality(); // 市 + String district = address.getSubLocality(); // 区 + String fullAddress = String.format("%s,%s,%s", province, city, district); + Log.d("Location", "Full Address: " + fullAddress); + // 更新 UI 或其他逻辑 + getActivity().runOnUiThread(() -> tvLocation.setText(fullAddress)); + } + } catch (IOException e) { + Log.e("Location", "Error getting address", e); + } + } + private void initLocationClient() { + try { + locationClient = new AMapLocationClient(requireContext()); + locationOption = new AMapLocationClientOption(); + + // 修改定位参数 + locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy); + locationOption.setNeedAddress(true); // 确保这个设置为true + locationOption.setOnceLocation(false);//false表示连续定位 + locationOption.setWifiActiveScan(true); + locationOption.setHttpTimeOut(20000); // 设置超时时间 + locationOption.setLocationCacheEnable(false); // 关闭缓存 + locationOption.setInterval(10000); + + locationClient.setLocationOption(locationOption); + locationClient.setLocationListener(this); + } catch (Exception e) { + Log.e("Location", "初始化定位失败", e); + Toast.makeText(requireContext(), "定位初始化失败", Toast.LENGTH_SHORT).show(); + } + } + + @Override + public void onLocationChanged(AMapLocation location) { + if (location == null) { + Log.e("Location", "定位结果为空"); + return; + } + + // 打印完整的定位信息用于调试 + Log.d("Location", "完整定位信息: " + location.toString()); + + if (location.getErrorCode() == 0) { + updateLocationUI(location); + } else { + showLocationError(location); + // 尝试重新启动定位 + if (locationClient != null) { + locationClient.stopLocation(); + locationClient.startLocation(); + } + } + } + + private void updateLocationUI(AMapLocation location) { + // 移动地图到当前位置 + LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); + aMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 16)); + + /* // 获取省、市、区信息 + String province = location.getProvince(); + String city = location.getCity(); + String district = location.getDistrict(); + + // 检查是否为空 + Log.d("Location", "Province: " + province + ", City: " + city + ", District: " + district); + + // 构建显示信息 + StringBuilder locationInfoBuilder = new StringBuilder(); + if (province != null && !province.isEmpty()) { + locationInfoBuilder.append(province).append("省"); + } + if (city != null && !city.isEmpty()) { + locationInfoBuilder.append(city).append("市"); + } + if (district != null && !district.isEmpty()) { + locationInfoBuilder.append(district).append("区"); + } + String locationInfo = locationInfoBuilder.toString(); + if (locationInfo.isEmpty()) { + locationInfo = "未获取到详细地址信息"; + } + + // 更新 UI + if (tvLocation != null) { + String finalLocationInfo = locationInfo; + getActivity().runOnUiThread(() -> tvLocation.setText(finalLocationInfo)); + } else { + Log.e("Location", "tvLocation is null"); + }*/ + + // 通知地图更新蓝点位置 + if (mapLocationListener != null) { + mapLocationListener.onLocationChanged(location); + } + } + + private void showLocationError(AMapLocation location) { + String errorInfo = String.format("定位失败\n错误码: %d\n错误信息: %s", + location.getErrorCode(), + location.getErrorInfo()); + + tvLocation.setText(errorInfo); + Toast.makeText(requireContext(), errorInfo, Toast.LENGTH_SHORT).show(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, + @NonNull int[] grantResults) { + if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) { + if (grantResults.length >= 2 && + grantResults[0] == PackageManager.PERMISSION_GRANTED && + grantResults[1] == PackageManager.PERMISSION_GRANTED) { + startLocation(); + } else { + Toast.makeText(requireContext(), "定位权限被拒绝", Toast.LENGTH_SHORT).show(); + } + } + } + + @Override + public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { + if (requestCode == REQUEST_ENABLE_GPS && isGpsEnabled()) { + startLocation(); + } + } + + // ========== LocationSource 接口实现 ========== + @Override + public void activate(OnLocationChangedListener listener) { + mapLocationListener = listener; + } + + @Override + public void deactivate() { + mapLocationListener = null; + } + + // ========== 生命周期管理 ========== + @Override + public void onResume() { + super.onResume(); + mapView.onResume(); + } + + @Override + public void onPause() { + super.onPause(); + mapView.onPause(); + stopLocation(); + } + + @Override + public void onDestroy() { + super.onDestroy(); + mapView.onDestroy(); + releaseLocation(); + } + + @Override + public void onSaveInstanceState(@NonNull Bundle outState) { + super.onSaveInstanceState(outState); + mapView.onSaveInstanceState(outState); + } + + private void stopLocation() { + if (locationClient != null && locationClient.isStarted()) { + locationClient.stopLocation(); + btnLocation.setText("开始定位"); + } + } + + private void releaseLocation() { + if (locationClient != null) { + locationClient.stopLocation(); + locationClient.onDestroy(); + locationClient = null; + } + } + + private boolean isNetworkConnected() { + Context context = requireContext(); + ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); + NetworkInfo networkInfo = null; + if (connectivityManager != null) { + networkInfo = connectivityManager.getActiveNetworkInfo(); + } + return networkInfo != null && networkInfo.isConnected(); + } + + private void showNetworkDisconnectedAlert() { + new AlertDialog.Builder(requireContext()) + .setTitle("网络连接断开") + .setMessage("请检查网络连接后重试") + .setPositiveButton("确定", null) + .show(); + } +} \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/add_small_icon.png b/CODE/RommteStory/app/src/main/res/drawable-v24/add_small_icon.png new file mode 100644 index 0000000..18fb98e Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/add_small_icon.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/back.png b/CODE/RommteStory/app/src/main/res/drawable-v24/back.png new file mode 100644 index 0000000..f7c2676 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/back.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/dc.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/dc.jpg new file mode 100644 index 0000000..55e20ba Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/dc.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/hyt.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/hyt.jpg new file mode 100644 index 0000000..0a932e0 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/hyt.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher.webp b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher.webp new file mode 100644 index 0000000..28d4b77 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher.webp differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..2b068d1 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_round.webp b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_round.webp new file mode 100644 index 0000000..9287f50 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_launcher_round.webp differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/ic_my_location.png b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_my_location.png new file mode 100644 index 0000000..f1e1be3 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_my_location.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/ic_no_picture.png b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_no_picture.png new file mode 100644 index 0000000..be8316c Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/ic_no_picture.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_add.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_add.png new file mode 100644 index 0000000..35766dd Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_add.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_cat.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_cat.png new file mode 100644 index 0000000..eb6085d Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_cat.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_delete.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_delete.png new file mode 100644 index 0000000..7ec3fce Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_delete.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_detail.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_detail.png new file mode 100644 index 0000000..0b9bd54 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_detail.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog1.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog1.png new file mode 100644 index 0000000..4a1f6a3 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog1.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog2.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog2.png new file mode 100644 index 0000000..2a29c7b Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog2.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog3.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog3.png new file mode 100644 index 0000000..ad66b82 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_dog3.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_honor.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_honor.png new file mode 100644 index 0000000..4d58538 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_honor.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo.png new file mode 100644 index 0000000..41eff7f Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo1.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo1.png new file mode 100644 index 0000000..99c33b9 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_memo1.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_mine.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_mine.png new file mode 100644 index 0000000..9517f6c Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_mine.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_qq.png b/CODE/RommteStory/app/src/main/res/drawable-v24/img_qq.png new file mode 100644 index 0000000..07fd25a Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_qq.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/img_test.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/img_test.jpg new file mode 100644 index 0000000..4e9d280 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/img_test.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/pyy.png b/CODE/RommteStory/app/src/main/res/drawable-v24/pyy.png new file mode 100644 index 0000000..782f8f1 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/pyy.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/remove_large_icon.png b/CODE/RommteStory/app/src/main/res/drawable-v24/remove_large_icon.png new file mode 100644 index 0000000..7ec3fce Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/remove_large_icon.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/success.png b/CODE/RommteStory/app/src/main/res/drawable-v24/success.png new file mode 100644 index 0000000..24e07a2 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/success.png differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/wyz1.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/wyz1.jpg new file mode 100644 index 0000000..d2eb45e Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/wyz1.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/wz.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/wz.jpg new file mode 100644 index 0000000..a41c6b7 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/wz.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable-v24/yyqx.jpg b/CODE/RommteStory/app/src/main/res/drawable-v24/yyqx.jpg new file mode 100644 index 0000000..15717c7 Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/drawable-v24/yyqx.jpg differ diff --git a/CODE/RommteStory/app/src/main/res/drawable/bg_boarder.xml b/CODE/RommteStory/app/src/main/res/drawable/bg_boarder.xml new file mode 100644 index 0000000..8d9459c --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/bg_boarder.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + diff --git a/CODE/RommteStory/app/src/main/res/drawable/button_style.xml b/CODE/RommteStory/app/src/main/res/drawable/button_style.xml new file mode 100644 index 0000000..f3e0934 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/button_style.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/drawable/cursor_style.xml b/CODE/RommteStory/app/src/main/res/drawable/cursor_style.xml new file mode 100644 index 0000000..07c4f67 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/cursor_style.xml @@ -0,0 +1,17 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/drawable/ic_dashboard_black_24dp.xml b/CODE/RommteStory/app/src/main/res/drawable/ic_dashboard_black_24dp.xml new file mode 100644 index 0000000..46fc8de --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/ic_dashboard_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/CODE/RommteStory/app/src/main/res/drawable/ic_home_black_24dp.xml b/CODE/RommteStory/app/src/main/res/drawable/ic_home_black_24dp.xml new file mode 100644 index 0000000..a5b4070 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/ic_home_black_24dp.xml @@ -0,0 +1,10 @@ + + + + diff --git a/CODE/RommteStory/app/src/main/res/drawable/ic_launcher_background.xml b/CODE/RommteStory/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000..ca3826a --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/CODE/RommteStory/app/src/main/res/drawable/ic_notifications_black_24dp.xml b/CODE/RommteStory/app/src/main/res/drawable/ic_notifications_black_24dp.xml new file mode 100644 index 0000000..78b75c3 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/ic_notifications_black_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/CODE/RommteStory/app/src/main/res/drawable/img_honor_style.xml b/CODE/RommteStory/app/src/main/res/drawable/img_honor_style.xml new file mode 100644 index 0000000..1630664 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/img_honor_style.xml @@ -0,0 +1,59 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/drawable/sl_tab_color.xml b/CODE/RommteStory/app/src/main/res/drawable/sl_tab_color.xml new file mode 100644 index 0000000..e4e9a8b --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/drawable/sl_tab_color.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/CODE/RommteStory/app/src/main/res/font/you_light.ttf b/CODE/RommteStory/app/src/main/res/font/you_light.ttf new file mode 100644 index 0000000..a74529c Binary files /dev/null and b/CODE/RommteStory/app/src/main/res/font/you_light.ttf differ diff --git a/CODE/RommteStory/app/src/main/res/layout/activity_main.xml b/CODE/RommteStory/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000..702e609 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,29 @@ + + + + + + + \ No newline at end of file diff --git a/CODE/RommteStory/app/src/main/res/layout/activity_story.xml b/CODE/RommteStory/app/src/main/res/layout/activity_story.xml new file mode 100644 index 0000000..b8ba492 --- /dev/null +++ b/CODE/RommteStory/app/src/main/res/layout/activity_story.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + +