Open ddabi opened 2 years ago
AndroidMainfest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.writediary">
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-feature android:name="android.hardware.camera"
android:required="true" />
<application
android:usesCleartextTraffic="true"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.WriteDiary">
<activity
android:name=".SplashActivity"
android:theme="@style/SplashTheme"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".MainActivity"
android:windowSoftInputMode="adjustPan">
</activity>
<provider
android:name="androidx.core.content.FileProvider"
android:authorities="com.example.writediary.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/external" />
</provider>
</application>
</manifest>
AppConstants.java
package com.example.writediary;
import android.util.Log;
import java.text.SimpleDateFormat;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
public class AppConstants {
public static final int REQ_LOCATION_BY_ADDRESS = 101;
public static final int REQ_WEATHER_BY_GRID = 102;
public static final int REQ_PHOTO_CAPTURE = 103;
public static final int REQ_PHOTO_SELECTION = 104;
public static final int CONTENT_PHOTO = 105;
public static final int CONTENT_PHOTO_EX = 106;
public static String FOLDER_PHOTO;
public static String DATABASE_NAME = "note.db";
public static final int MODE_INSERT = 1;
public static final int MODE_MODIFY = 2;
public static SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmm");
public static SimpleDateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH시");
public static SimpleDateFormat dateFormat3 = new SimpleDateFormat("MM월 dd일");
public static SimpleDateFormat dateFormat4 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public static SimpleDateFormat dateFormat5 = new SimpleDateFormat("yyyy-MM-dd");
public static SimpleDateFormat dateFormat6 = new SimpleDateFormat("yy년 MM월 dd일");
private static final String TAG = "AppConstants";
}
GridUtil.java
package com.example.writediary;
import java.util.HashMap;
import java.util.Map;
public class GridUtil {
public static final double RE = 6371.00877; // 지구 반경(km)
public static final double GRID = 5.0; // 격자 간격(km)
public static final double SLAT1 = 30.0; // 투영 위도1(degree)
public static final double SLAT2 = 60.0; // 투영 위도2(degree)
public static final double OLON = 126.0; // 기준점 경도(degree)
public static final double OLAT = 38.0; // 기준점 위도(degree)
public static final double XO = 43; // 기준점 X좌표(GRID)
public static final double YO = 136; // 기1준점 Y좌표(GRID)
public static Map<String, Double> getGrid(double v1, double v2) {
double DEGRAD = Math.PI / 180.0;
// double RADDEG = 180.0 / Math.PI;
double re = RE / GRID;
double slat1 = SLAT1 * DEGRAD;
double slat2 = SLAT2 * DEGRAD;
double olon = OLON * DEGRAD;
double olat = OLAT * DEGRAD;
double sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5);
sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn);
double sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5);
sf = Math.pow(sf, sn) * Math.cos(slat1) / sn;
double ro = Math.tan(Math.PI * 0.25 + olat * 0.5);
ro = re * sf / Math.pow(ro, sn);
Map<String, Double> map = new HashMap<String, Double>();
map.put("lat", v1);
map.put("lng", v1);
double ra = Math.tan(Math.PI * 0.25 + (v1) * DEGRAD * 0.5);
ra = re * sf / Math.pow(ra, sn);
double theta = v2 * DEGRAD - olon;
if (theta > Math.PI)
theta -= 2.0 * Math.PI;
if (theta < -Math.PI)
theta += 2.0 * Math.PI;
theta *= sn;
map.put("x", Math.floor(ra * Math.sin(theta) + XO + 0.5));
map.put("y", Math.floor(ro - ra * Math.cos(theta) + YO + 0.5));
return map;
}
}
list_fragment.java
package com.example.writediary;
import android.content.Context;
import android.database.Cursor;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Date;
import lib.kingja.switchbutton.SwitchMultiButton;
public class list_fragment extends Fragment {
RecyclerView recyclerView;
NoteAdapter adapter;
Context context;
onTabItemSelectedListener listener;
ArrayList<Note> items=new ArrayList<>();
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context=context;
if(context instanceof onTabItemSelectedListener){
listener=(onTabItemSelectedListener) context;
}
}
@Override
public void onDetach() {
super.onDetach();
if(context!=null){
context=null;
listener=null;
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup rootview=(ViewGroup) inflater.inflate(R.layout.list_fragment,container,false);
initUI(rootview);
loadNoteListData();
return rootview;
}
public int loadNoteListData(){
String sql="select _id, WEATHER, ADDRESS, LOCATION_X, LOCATION_Y, CONTENTS, TITLE, MOOD, " +
"PICTURE, CREATE_DATE, MODIFY_DATE from "+NoteDatabase.TABLE_NOTE+
" order by CREATE_DATE desc";
NoteDatabase DB=NoteDatabase.getInstance(context);
int recordCount=-1;
if(DB!=null){
Cursor outcursor=DB.rawQuery(sql);
ArrayList<Note> items=new ArrayList<>();
for(int i=0;i<outcursor.getCount();i++){
outcursor.moveToNext();
int _id=outcursor.getInt(0);
String _weather= outcursor.getString(1);
String _address= outcursor.getString(2);
String _locationx= outcursor.getString(3);
String _locationy= outcursor.getString(4);
String _contents= outcursor.getString(5);
String _title= outcursor.getString(6);
String _mood= outcursor.getString(7);
String _picture= outcursor.getString(8);
String _create_date= outcursor.getString(9);
String createStr=null;
if(_create_date!=null&&_create_date.length()>10){
try{
Date indate=AppConstants.dateFormat4.parse(_create_date);
createStr=AppConstants.dateFormat3.format(indate);
}catch (ParseException E){
E.printStackTrace();
}
}
else{
createStr="";
}
items.add(new Note(_id, _weather, _address, _locationx,_locationy,_contents,_title,_mood,_picture,createStr));
}
recordCount= outcursor.getCount();
outcursor.close();
adapter.setItems(items);
adapter.notifyDataSetChanged();
}
return recordCount;
}
private void initUI(ViewGroup view) {
recyclerView = view.findViewById(R.id.recycler);
adapter = new NoteAdapter(items,getContext());
recyclerView.setAdapter(adapter);
LinearLayoutManager manager = new LinearLayoutManager(getContext(),LinearLayoutManager.VERTICAL,false);
recyclerView.setLayoutManager(manager);
Button writebutton = view.findViewById(R.id.writeButton);
writebutton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.onTabSelected(1);
}
}
});
SwitchMultiButton switchbutton = view.findViewById(R.id.switchButton);
switchbutton.setOnSwitchListener(new SwitchMultiButton.OnSwitchListener() {
@Override
public void onSwitch(int position, String tabText) {
adapter.switchLayout(position);
adapter.notifyDataSetChanged();
}
});
adapter.setOnItemClickListener(new onNoteItemClickListener(){
@Override
public void onNoteClick(NoteAdapter.ViewHolder holder, View view, int position) {
Note item= adapter.getItem(position);
if(listener!=null){
listener.showWritable(item);
}
}
});
}
}
MainActivity.java
package com.example.writediary;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.location.Address;
import android.location.Geocoder;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.MenuItem;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.pedro.library.AutoPermissions;
import com.pedro.library.AutoPermissionsListener;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class MainActivity extends AppCompatActivity implements
onTabItemSelectedListener, onRequestListener, AutoPermissionsListener{
list_fragment list_frag;
write_fragment write_frag;
statistics_fragment statistic_frag;
BottomNavigationView bottomNavi;
Location currentLoc;
GPSListener gpsListener;
// get weather 변수
Date currentDate;
String currentDateString;
int locationCount=0;
// getaddress 변수
String currentAddress;
// 데이터 베이스
public static NoteDatabase mDatabase = null;
// 아이템 클릭
boolean writetab=true;
@Override
protected void onDestroy() {
super.onDestroy();
if(mDatabase!=null){
mDatabase.close();
mDatabase=null;
}
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list_frag=new list_fragment();
write_frag=new write_fragment();
statistic_frag=new statistics_fragment();
getSupportFragmentManager().beginTransaction().replace(R.id.container,list_frag).commit();
bottomNavi=findViewById(R.id.bottom_navi);
bottomNavi.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.tab1:
getSupportFragmentManager().beginTransaction().replace(R.id.container,list_frag).commit();
return true;
case R.id.tab2:
writetab=false;
getSupportFragmentManager().beginTransaction().replace(R.id.container,write_frag).commit();
return true;
case R.id.tab3:
getSupportFragmentManager().beginTransaction().replace(R.id.container,statistic_frag).commit();
return true;
}
return false;
}
});
AutoPermissions.Companion.loadAllPermissions(this, 1);
setPicturePath();
openDatabase();
}
public void setPicturePath() {
String sdcardPath = Environment.getExternalStorageDirectory().getAbsolutePath();
AppConstants.FOLDER_PHOTO = sdcardPath + File.separator + "photo";
}
public void openDatabase(){
if(mDatabase!=null){
mDatabase.close();
mDatabase=null;
}
mDatabase=NoteDatabase.getInstance(this);
boolean isOpen=mDatabase.open();
if(isOpen){
System.out.println("db is opened");
}
else{
System.out.println("db is not opened");
}
}
public void onTabSelected(int position){
if(position==0){
bottomNavi.setSelectedItemId(R.id.tab1);
}else if(position==1){
writetab=true;
write_frag=new write_fragment();
getSupportFragmentManager().beginTransaction().replace(R.id.container,write_frag).commit();
}
else{
bottomNavi.setSelectedItemId(R.id.tab3);
}
}
@Override
public void showWritable(Note item){
write_frag=new write_fragment();
write_frag.setItem(item);
//bottomNavi.setSelectedItemId(R.id.tab2);
writetab=false;
getSupportFragmentManager().beginTransaction().replace(R.id.container,write_frag).commit();
}
public void onRequest(String command){
if(command!=null){
if(command.equals("getCurrentLocation")&&writetab==true){
writetab=true;
System.out.println("onRequest() 에서 getCurrentLocation 호출됨 and writetab: "+writetab);
getCurrentLocation();
}
}
}
public void getCurrentLocation(){
currentDate=new Date();
currentDateString=AppConstants.dateFormat3.format(currentDate);
if(write_frag!=null){
write_frag.setDateString(currentDateString);
}
LocationManager manager=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
try{
currentLoc=manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if(currentLoc!=null){
double latitude=currentLoc.getLatitude();
double longitude=currentLoc.getLongitude();
String message="latitude: "+latitude+", longitude: "+longitude+"\n";
System.out.println("위치: "+message);
// 현재 위치로 날씨 확인
//getCurrentWeather();
// 현재 위치로 주소 확인
//getCurrentAddress();
}
gpsListener=new GPSListener();
long mintime=10000;
int mindistance=0;
manager.requestLocationUpdates(LocationManager.GPS_PROVIDER,mintime,mindistance,gpsListener);
} catch (SecurityException e){
e.printStackTrace();
System.out.println("getCurrentLocation()에서 SecurityException 발생");
}
}
public void stopLocationService(){
LocationManager manager=(LocationManager) getSystemService(Context.LOCATION_SERVICE);
try{
manager.removeUpdates(gpsListener);
System.out.println("stopLocationService() called");
} catch(SecurityException e){
e.printStackTrace();
}
}
public void getCurrentAddress(){
Geocoder geocoder=new Geocoder(this, Locale.getDefault());
List<Address> addresses=null;
try{
addresses=geocoder.getFromLocation(currentLoc.getLatitude(),currentLoc.getLongitude(),1);
} catch (IOException E){
E.printStackTrace();
}
if(addresses!=null&&addresses.size()>0){
Address address=addresses.get(0);
currentAddress=address.getLocality()+" "+address.getSubLocality();
if(write_frag!=null){
write_frag.setAddress(currentAddress);
}
}
}
public void getCurrentWeather(){
Map<String, Double> gridMap=GridUtil.getGrid(currentLoc.getLatitude(),currentLoc.getLongitude());
double gridX=gridMap.get("x");
double gridY=gridMap.get("y");
System.out.println("getCurrentWeather() called -> ("+gridX+", "+gridY+")\n");
xmlparsing(gridX,gridY);
}
public void xmlparsing(double x, double y){
String url="http://www.kma.go.kr/wid/queryDFS.jsp";
url+="?gridx="+Math.round(x);
url+="&gridy="+Math.round(y);
try{
URL myurl=new URL(url);
WeatherThread task=new WeatherThread();
task.execute(myurl);
}
catch(MalformedURLException e){
e.printStackTrace();
}
}
class GPSListener implements LocationListener{
@Override
public void onLocationChanged(@NonNull Location location) {
currentLoc=location;
locationCount++;
double latitude=currentLoc.getLatitude();
double longitude=currentLoc.getLongitude();
String message="latitude: "+latitude+", longitude: "+longitude+"\n";
System.out.println("위치: "+message);
getCurrentWeather();
getCurrentAddress();
stopLocationService();
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(@NonNull String provider) {
}
@Override
public void onProviderDisabled(@NonNull String provider) {
}
}
class WeatherThread extends AsyncTask<URL, Void, String>{
@Override
protected void onPreExecute() {
super.onPreExecute();
}
@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
System.out.println("parsing 완료: "+s);
}
@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}
@Override
protected String doInBackground(URL... urls) {
URL myUrl=urls[0];
try{
InputStream IS= myUrl.openStream();
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
XmlPullParser parser= factory.newPullParser();
parser.setInput(IS,"UTF8");
int eventType= parser.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
if(eventType==XmlPullParser.START_TAG){
String tagname=parser.getName();
if(tagname.equals("tm")){
parser.next();
try{
Date time=AppConstants.dateFormat.parse(parser.getText());
String message=AppConstants.dateFormat2.format(time);
System.out.println("기준 시간: "+message);
} catch (ParseException e){
System.out.println("doInBackground() 에서 오류 발생 ");
e.printStackTrace();
}
}
else if(tagname.equals("wfKor")){
if(write_frag!=null){
parser.next();
write_frag.setWeather(parser.getText());
break;
}
}
}
eventType=parser.next();
}
IS.close();
} catch (IOException E){
System.out.println("날씨에서 IOException 발생");
E.printStackTrace();
} catch (XmlPullParserException e){
System.out.println("날씨에서 XmlPullParserException 발생");
e.printStackTrace();
}
return " doInBackground() 호출 완료";
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
AutoPermissions.Companion.parsePermissions(this, requestCode, permissions, this);
}
@Override
public void onDenied(int i, String[] strings) {
}
@Override
public void onGranted(int i, String[] strings) {
System.out.println("onGranted() 호출됨: 권한 부여됨");
}
}
Note.java
package com.example.writediary;
public class Note {
int id;
String weather;
String address;
String locationX;
String locationY;
String contents;
String title;
String mood;
String picture;
String CreateDateStr;
public Note(int id, String weather, String address, String locationX, String locationY,
String contents,String title, String mood, String picture, String createDateStr) {
this.id = id;
this.weather = weather;
this.address = address;
this.title=title;
this.locationX = locationX;
this.locationY = locationY;
this.contents = contents;
this.mood = mood;
this.picture = picture;
CreateDateStr = createDateStr;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getWeather() {
return weather;
}
public void setWeather(String weather) {
this.weather = weather;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getLocationX() {
return locationX;
}
public void setLocationX(String locationX) {
this.locationX = locationX;
}
public String getLocationY() {
return locationY;
}
public void setLocationY(String locationY) {
this.locationY = locationY;
}
public String getContents() {
return contents;
}
public void setContents(String contents) {
this.contents = contents;
}
public String getMood() {
return mood;
}
public void setMood(String mood) {
this.mood = mood;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
public String getCreateDateStr() {
return CreateDateStr;
}
public void setCreateDateStr(String createDateStr) {
CreateDateStr = createDateStr;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
NotaAdpter.java
package com.example.writediary;
import android.content.Context;
import android.media.Image;
import android.net.Uri;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
public class NoteAdapter extends RecyclerView.Adapter<NoteAdapter.ViewHolder>
implements onNoteItemClickListener{
ArrayList<Note> items=new ArrayList<Note>();
onNoteItemClickListener listener;
int layoutType=0;
Context context;
public NoteAdapter(ArrayList<Note> items, Context context) {
this.items = items;
this.context = context;
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater=LayoutInflater.from(parent.getContext());
ViewGroup view=(ViewGroup) inflater.inflate(R.layout.note_item,parent,false);
return new ViewHolder(view,this,layoutType);
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
Note item=items.get(position);
holder.setItem(item);
holder.setLayoutType(layoutType);
}
@Override
public int getItemCount() {
return items.size();
}
public void addItem(Note item){
items.add(item);
}
public void setItems(ArrayList<Note> items){
this.items=items;
}
public Note getItem(int position){
return items.get(position);
}
public void setOnItemClickListener(onNoteItemClickListener listener){
this.listener=listener;
}
@Override
public void onNoteClick(ViewHolder holder, View view, int position) {
if(listener!=null){
listener.onNoteClick(holder,view,position);
}
}
public void switchLayout(int type){
layoutType=type;
}
static class ViewHolder extends RecyclerView.ViewHolder{
LinearLayout layout1;
LinearLayout layout2;
ImageView moodImg1;
ImageView moodImg2;
ImageView userImg1;
ImageView userImg2;
ImageView weatherImg1;
ImageView weatherImg2;
TextView title1;
TextView title2;
TextView location1;
TextView location2;
TextView date1;
TextView date2;
public ViewHolder(@NonNull View itemView, final onNoteItemClickListener listener, int type) {
super(itemView);
layout1=itemView.findViewById(R.id.layout1);
layout2=itemView.findViewById(R.id.layout2);
moodImg1=itemView.findViewById(R.id.mood_img);
moodImg2=itemView.findViewById(R.id.mood_img2);
userImg1=itemView.findViewById(R.id.user_img);
userImg2=itemView.findViewById(R.id.user_img2);
weatherImg1=itemView.findViewById(R.id.weather_img);
weatherImg2=itemView.findViewById(R.id.weather_img2);
title1=itemView.findViewById(R.id.content);
title2=itemView.findViewById(R.id.content2);
location1=itemView.findViewById(R.id.location);
location2=itemView.findViewById(R.id.location2);
date1=itemView.findViewById(R.id.date);
date2=itemView.findViewById(R.id.date2);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int position=getAdapterPosition();
if(listener!=null){
listener.onNoteClick(ViewHolder.this,view,position);
}
}
});
setLayoutType(type);
}
public void setItem(Note item){
String mood=item.getMood();
int moodIndex=Integer.parseInt(mood);
setMoodImg(moodIndex);
String picPath=item.getPicture();
if(picPath!=null&&!picPath.equals("")){
userImg1.setVisibility(View.VISIBLE);
userImg2.setVisibility(View.VISIBLE);
userImg2.setImageURI(Uri.parse("file://"+picPath));
}
else{
userImg1.setVisibility(View.GONE);
userImg2.setVisibility(View.GONE);
userImg2.setImageResource(R.drawable.noimagefound);
}
String weather=item.getWeather();
int weatherIdx=Integer.parseInt(weather);
setWeatherImg(weatherIdx);
title1.setText(item.getTitle());
title2.setText(item.getTitle());
location1.setText(item.getAddress());
location2.setText(item.getAddress());
date1.setText(item.getCreateDateStr());
date2.setText(item.getCreateDateStr());
}
public void setMoodImg(int idx){
switch (idx){
case 0:
moodImg1.setImageResource(R.drawable.smile1_48);
moodImg2.setImageResource(R.drawable.smile1_48);
break;
case 1:
moodImg1.setImageResource(R.drawable.smile2_48);
moodImg2.setImageResource(R.drawable.smile2_48);
break;
case 2:
moodImg1.setImageResource(R.drawable.smile3_48);
moodImg2.setImageResource(R.drawable.smile3_48);
break;
case 3:
moodImg1.setImageResource(R.drawable.smile4_48);
moodImg2.setImageResource(R.drawable.smile4_48);
break;
case 4:
moodImg1.setImageResource(R.drawable.smile5_48);
moodImg2.setImageResource(R.drawable.smile5_48);
break;
default:
moodImg1.setImageResource(R.drawable.smile3_48);
moodImg2.setImageResource(R.drawable.smile3_48);
break;
}
}
public void setWeatherImg(int idx){
switch (idx){
case 0:
weatherImg1.setImageResource(R.drawable.weather_icon_1);
weatherImg2.setImageResource(R.drawable.weather_icon_1);
break;
case 1:
weatherImg1.setImageResource(R.drawable.weather_icon_2);
weatherImg2.setImageResource(R.drawable.weather_icon_2);
break;
case 2:
weatherImg1.setImageResource(R.drawable.weather_icon_3);
weatherImg2.setImageResource(R.drawable.weather_icon_3);
break;
case 3:
weatherImg1.setImageResource(R.drawable.weather_icon_4);
weatherImg2.setImageResource(R.drawable.weather_icon_4);
break;
case 4:
weatherImg1.setImageResource(R.drawable.weather_icon_5);
weatherImg2.setImageResource(R.drawable.weather_icon_5);
break;
case 5:
weatherImg1.setImageResource(R.drawable.weather_icon_6);
weatherImg2.setImageResource(R.drawable.weather_icon_6);
break;
case 6:
weatherImg1.setImageResource(R.drawable.weather_icon_7);
weatherImg2.setImageResource(R.drawable.weather_icon_7);
break;
default:
weatherImg1.setImageResource(R.drawable.weather_icon_1);
weatherImg2.setImageResource(R.drawable.weather_icon_1);
break;
}
}
public void setLayoutType(int type){
if(type==0){
layout1.setVisibility(View.VISIBLE);
layout2.setVisibility(View.GONE);
}
else if(type==1){
layout1.setVisibility(View.GONE);
layout2.setVisibility(View.VISIBLE);
}
}
}
}
NoteDatabase.java
package com.example.writediary;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import androidx.annotation.Nullable;
public class NoteDatabase {
private static final String TAG="NoteDatabase";
private static NoteDatabase database;
public static String TABLE_NOTE="NOTE";
public static int DATABASE_VERSION=1;
private DatabaseHelper dbhelper;
private SQLiteDatabase db;
private Context context;
public NoteDatabase(Context context) {
this.context = context;
}
public static NoteDatabase getInstance(Context context){
if(database==null){
database=new NoteDatabase(context);
}
return database;
}
public boolean open(){
dbhelper=new DatabaseHelper(context);
db=dbhelper.getWritableDatabase();
return true;
}
public void close(){
db.close();
database=null;
}
public Cursor rawQuery(String sql){
Cursor cursor=null;
try{
cursor=db.rawQuery(sql,null);
} catch (Exception e){
e.printStackTrace();
System.out.println("rawQuery() 에서 예외 발생");
}
return cursor;
}
public boolean execSQL(String sql){
try{
db.execSQL(sql);
} catch (Exception e){
e.printStackTrace();
return false;
}
return true;
}
private class DatabaseHelper extends SQLiteOpenHelper{
public DatabaseHelper(@Nullable Context context) {
super(context, AppConstants.DATABASE_NAME, null, DATABASE_VERSION);
}
public void onCreate(SQLiteDatabase DB){
try{
DB.execSQL("drop table if exists "+TABLE_NOTE);
} catch (Exception e){
System.out.println("onCreate()에서 droptable이 실패함");
}
String CREATE_SQL="create table "+TABLE_NOTE+"( _id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, WEATHER TEXT DEFAULT'', " +
" ADDRESS TEXT DEFAULT '', " +
" LOCATION_X TEXT DEFAULT ''," +
" LOCATION_Y TEXT DEFAULT ''," +
" CONTENTS TEXT DEFAULT ''," +
" TITLE TEXT DEFAULT '', "+
" MOOD TEXT, " +
" PICTURE TEXT DEFAULT ''," +
" CREATE_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP, " +
" MODIFY_DATE TIMESTAMP DEFAULT CURRENT_TIMESTAMP )";
try{
DB.execSQL(CREATE_SQL);
}catch (Exception e){
System.out.println("onCreate()에서 create table이 실패함");
}
String CREATE_INDEX_SQL="create index "+TABLE_NOTE+"_IDX ON "+TABLE_NOTE+"(" +
"CREATE_DATE" +
")";
try{
DB.execSQL(CREATE_INDEX_SQL);
}catch (Exception e){
System.out.println("onCreate()에서 create index가 실패함");
}
}
public void onOpen(SQLiteDatabase DB){
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
}
onNoteitemClickListener.java
package com.example.writediary;
import android.view.View;
public interface onNoteItemClickListener {
public void onNoteClick(NoteAdapter.ViewHolder holder, View view, int position);
}
onRequestListener.java
package com.example.writediary;
public interface onRequestListener {
public void onRequest(String command);
}
onTabltemSelectedListener.java
package com.example.writediary;
public interface onTabItemSelectedListener {
public void onTabSelected(int position);
public void showWritable(Note item);
}
SplashActivity.java
package com.example.writediary;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
public class SplashActivity extends AppCompatActivity {
Handler handler=new Handler();
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash_back);
handler.postDelayed(new Runnable(){
@Override
public void run() {
Intent intent=new Intent(getApplicationContext(),MainActivity.class);
startActivity(intent);
finish();
}
},1000);
}
@Override
public void onBackPressed() {
// 뒤로 가기 버튼을 눌러도 splash에서는 반응 없음
}
}
statistics_fragment.java
package com.example.writediary;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import com.github.mikephil.charting.charts.BarChart;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
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.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointF;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
public class statistics_fragment extends Fragment {
PieChart chart1;
BarChart chart2;
LineChart chart3;
Context context;
int recordCount=0;
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context=context;
}
@Override
public void onDetach() {
super.onDetach();
if(context!=null){
context=null;
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup rootview=(ViewGroup) inflater.inflate(R.layout.statistic_fragment,container,false);
initUI(rootview);
loadStatData();
return rootview;
}
public void loadStatData(){
NoteDatabase database=NoteDatabase.getInstance(context);
// 기분 별 비율
String sql="select MOOD , count(MOOD) from "+NoteDatabase.TABLE_NOTE+
" where create_date > '"+getMonthBefore(1)+"' and create_date < '"+getTomorrow()+"' group by mood";
Cursor cursor=database.rawQuery(sql);
recordCount=cursor.getCount();
HashMap<String, Integer> hashMap1=new HashMap<>();
for(int i=0;i<recordCount;i++) {
cursor.moveToNext();
String moodName=cursor.getString(0);
int moodCount=cursor.getInt(1);
hashMap1.put(moodName, moodCount);
}
setData1(hashMap1);
// 요일 별 기분
sql="select strftime('%w', create_date) , avg(mood) from "+NoteDatabase.TABLE_NOTE+
" where create_date > '"+getMonthBefore(1)+"' and create_date < '"+getTomorrow()+"' group by strftime('%w', create_date)";
cursor=database.rawQuery(sql);
recordCount=cursor.getCount();
HashMap<String, Integer> hashMap2=new HashMap<>();
for(int i=0;i<recordCount;i++) {
cursor.moveToNext();
String weekDay=cursor.getString(0);
int moodAvg=cursor.getInt(1);
hashMap2.put(weekDay, moodAvg);
}
setData2(hashMap2);
// 기분 변화
sql="select strftime('%Y-%m-%d', create_date) , avg(cast(mood as real)) from "+NoteDatabase.TABLE_NOTE+
" where create_date > '"+getMonthBefore(4)+"' and create_date < '"+getTomorrow()+"' group by strftime('%Y-%m-%d', create_date)";
cursor=database.rawQuery(sql);
recordCount=cursor.getCount();
HashMap<String, Integer> hashMap3=new HashMap<>();
for(int i=0;i<recordCount;i++) {
cursor.moveToNext();
String monthDate=cursor.getString(0);
int moodAvg=cursor.getInt(1);
hashMap3.put(monthDate, moodAvg);
}
ArrayList<Float> dataKeys3=new ArrayList<>();
ArrayList<Integer> dataValues3=new ArrayList<>();
Date todayDate=new Date();
Calendar cal=Calendar.getInstance();
cal.setTime(todayDate);
cal.add(Calendar.DAY_OF_MONTH,-7);
for(int i=0;i<7;i++){
cal.add(Calendar.DAY_OF_MONTH,1);
String monthDate=AppConstants.dateFormat5.format(cal.getTime());
Object moodCount=hashMap3.get(monthDate);
dataKeys3.add((i-6)*24.f);
if (moodCount == null) {
dataValues3.add(0);
} else {
dataValues3.add((Integer)moodCount);
}
}
setData3(dataKeys3, dataValues3);
}
private void initUI(ViewGroup rootView){
chart1=rootView.findViewById(R.id.chart1);
chart1.setUsePercentValues(true);
chart1.getDescription().setEnabled(false);
chart1.setCenterText(getResources().getString(R.string.graph1_title));
chart1.setTransparentCircleColor(Color.WHITE);
chart1.setTransparentCircleAlpha(110);
chart1.setHoleRadius(58f);
chart1.setTransparentCircleRadius(61f);
chart1.setDrawCenterText(true);
chart1.setHighlightPerTapEnabled(true);
Legend legent1=chart1.getLegend();
legent1.setEnabled(false);
chart1.setEntryLabelColor(Color.WHITE);
chart1.setEntryLabelTextSize(12f);
chart2 = rootView.findViewById(R.id.chart2);
chart2.setDrawValueAboveBar(true);
chart2.getDescription().setEnabled(false);
chart2.setDrawGridBackground(false);
XAxis xAxis = chart2.getXAxis();
xAxis.setEnabled(false);
YAxis leftAxis = chart2.getAxisLeft();
leftAxis.setLabelCount(6, false);
leftAxis.setAxisMinimum(0.0f);
leftAxis.setGranularityEnabled(true);
leftAxis.setGranularity(1f);
YAxis rightAxis = chart2.getAxisRight();
rightAxis.setEnabled(false);
Legend legend2 = chart2.getLegend();
legend2.setEnabled(false);
chart2.animateXY(1500, 1500);
chart3 = rootView.findViewById(R.id.chart3);
chart3.getDescription().setEnabled(false);
chart3.setDrawGridBackground(false);
// set an alternative background color
chart3.setBackgroundColor(Color.WHITE);
chart3.setViewPortOffsets(0, 0, 0, 0);
// get the legend (only possible after setting data)
Legend legend3 = chart3.getLegend();
legend3.setEnabled(false);
XAxis xAxis3 = chart3.getXAxis();
xAxis3.setPosition(XAxis.XAxisPosition.BOTTOM_INSIDE);
xAxis3.setTextSize(10f);
xAxis3.setTextColor(Color.WHITE);
xAxis3.setDrawAxisLine(false);
xAxis3.setDrawGridLines(true);
xAxis3.setTextColor(Color.rgb(255, 192, 56));
xAxis3.setCenterAxisLabels(true);
xAxis3.setGranularity(1f);
xAxis3.setValueFormatter(new ValueFormatter() {
private final SimpleDateFormat mFormat = new SimpleDateFormat("MM-DD", Locale.KOREA);
@Override
public String getFormattedValue(float value) {
long millis = TimeUnit.HOURS.toMillis((long) value);
return mFormat.format(new Date(millis));
}
});
YAxis leftAxis3 = chart3.getAxisLeft();
leftAxis3.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);
leftAxis3.setTextColor(ColorTemplate.getHoloBlue());
leftAxis3.setDrawGridLines(true);
leftAxis3.setGranularityEnabled(true);
leftAxis3.setAxisMinimum(0f);
leftAxis3.setAxisMaximum(170f);
leftAxis3.setYOffset(-9f);
leftAxis3.setTextColor(Color.rgb(255, 192, 56));
YAxis rightAxis3 = chart3.getAxisRight();
rightAxis3.setEnabled(false);
}
private void setData1(HashMap<String,Integer> dataHash1) {
ArrayList<PieEntry> entries = new ArrayList<>();
String[] keys = {"0", "1", "2", "3", "4"};
int[] icons = {R.drawable.smile1_24, R.drawable.smile2_24,
R.drawable.smile3_24, R.drawable.smile4_24,
R.drawable.smile5_24};
for (int i = 0; i < keys.length; i++) {
int value = 0;
Integer outValue = dataHash1.get(keys[i]);
if (outValue != null) {
value = outValue.intValue();
}
if (value > 0) {
entries.add(new PieEntry(value, "",
getResources().getDrawable(icons[i])));
}
}
PieDataSet dataSet = new PieDataSet(entries, getResources().getString(R.string.graph1_title));
dataSet.setDrawIcons(true);
dataSet.setSliceSpace(3f);
dataSet.setIconsOffset(new MPPointF(0, -40));
dataSet.setSelectionShift(5f);
ArrayList<Integer> colors = new ArrayList<>();
for (int c : ColorTemplate.JOYFUL_COLORS) {
colors.add(c);
}
dataSet.setColors(colors);
PieData data = new PieData(dataSet);
data.setValueTextSize(22.0f);
data.setValueTextColor(Color.WHITE);
chart1.setData(data);
chart1.invalidate();
}
private void setData2(HashMap<String,Integer> dataHash2) {
ArrayList<BarEntry> entries = new ArrayList<>();
String[] keys = {"0", "1", "2", "3", "4", "5", "6"};
int[] icons = {R.drawable.smile1_24, R.drawable.smile2_24,
R.drawable.smile3_24, R.drawable.smile4_24,
R.drawable.smile5_24};
for (int i = 0; i < keys.length; i++) {
float value = 0.0f;
Integer outValue = dataHash2.get(keys[i]);
if (outValue != null) {
value = outValue.floatValue();
}
Drawable drawable = null;
if (value <= 1.0f) {
drawable = getResources().getDrawable(icons[0]);
} else if (value <= 2.0f) {
drawable = getResources().getDrawable(icons[1]);
} else if (value <= 3.0f) {
drawable = getResources().getDrawable(icons[2]);
} else if (value <= 4.0f) {
drawable = getResources().getDrawable(icons[3]);
} else if (value <= 5.0f) {
drawable = getResources().getDrawable(icons[4]);
}
entries.add(new BarEntry(Float.valueOf(String.valueOf(i+1)), value, drawable));
}
BarDataSet dataSet2 = new BarDataSet(entries, getResources().getString(R.string.graph2_title));
dataSet2.setColor(Color.rgb(240, 120, 124));
ArrayList<Integer> colors = new ArrayList<>();
for (int c : ColorTemplate.JOYFUL_COLORS) {
colors.add(c);
}
dataSet2.setColors(colors);
dataSet2.setIconsOffset(new MPPointF(0, -10));
BarData data = new BarData(dataSet2);
data.setValueTextSize(10f);
data.setDrawValues(false);
data.setBarWidth(0.8f);
chart2.setData(data);
chart2.invalidate();
}
private void setData3(ArrayList<Float> dataKeys3, ArrayList<Integer> dataValues3) {
ArrayList<Entry> entries = new ArrayList<>();
for (int i = 0; i < dataKeys3.size(); i++) {
try {
float outKey = dataKeys3.get(i);
Integer outValue = dataValues3.get(i);
entries.add(new Entry(outKey, new Float(outValue)));
} catch(Exception e) {
e.printStackTrace();
}
}
LineDataSet set1 = new LineDataSet(entries, getResources().getString(R.string.graph3_title));
set1.setAxisDependency(YAxis.AxisDependency.LEFT);
set1.setColor(ColorTemplate.getHoloBlue());
set1.setValueTextColor(ColorTemplate.getHoloBlue());
set1.setLineWidth(1.5f);
set1.setDrawCircles(true);
set1.setDrawValues(false);
set1.setFillAlpha(65);
set1.setFillColor(ColorTemplate.getHoloBlue());
set1.setHighLightColor(Color.rgb(244, 117, 117));
set1.setDrawCircleHole(false);
LineData data = new LineData(set1);
data.setValueTextColor(Color.WHITE);
data.setValueTextSize(9f);
chart3.setData(data);
chart3.invalidate();
}
public String getToday() {
Date todayDate = new Date();
return AppConstants.dateFormat5.format(todayDate);
}
public String getTomorrow() {
Date todayDate = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(todayDate);
cal.add(Calendar.DAY_OF_MONTH, 1);
return AppConstants.dateFormat5.format(cal.getTime());
}
public String getDayBefore(int amount) {
Date todayDate = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(todayDate);
cal.add(Calendar.DAY_OF_MONTH, (amount * -1));
return AppConstants.dateFormat5.format(cal.getTime());
}
public String getMonthBefore(int amount) {
Date todayDate = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(todayDate);
cal.add(Calendar.MONTH, (amount * -1));
return AppConstants.dateFormat5.format(cal.getTime());
}
}
ValueFomatter.java
package com.example.writediary;
import com.github.mikephil.charting.components.AxisBase;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.BubbleEntry;
import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.PieEntry;
import com.github.mikephil.charting.data.RadarEntry;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.ViewPortHandler;
public abstract class ValueFormatter implements IAxisValueFormatter, IValueFormatter {
/**
* <b>DO NOT USE</b>, only for backwards compatibility and will be removed in future versions.
*
* @param value the value to be formatted
* @param axis the axis the value belongs to
* @return formatted string label
*/
@Override
@Deprecated
public String getFormattedValue(float value, AxisBase axis) {
return getFormattedValue(value);
}
/**
* <b>DO NOT USE</b>, only for backwards compatibility and will be removed in future versions.
* @param value the value to be formatted
* @param entry the entry the value belongs to - in e.g. BarChart, this is of class BarEntry
* @param dataSetIndex the index of the DataSet the entry in focus belongs to
* @param viewPortHandler provides information about the current chart state (scale, translation, ...)
* @return formatted string label
*/
@Override
@Deprecated
public String getFormattedValue(float value, Entry entry, int dataSetIndex, ViewPortHandler viewPortHandler) {
return getFormattedValue(value);
}
/**
* Called when drawing any label, used to change numbers into formatted strings.
*
* @param value float to be formatted
* @return formatted string label
*/
public String getFormattedValue(float value) {
return String.valueOf(value);
}
/**
* Used to draw axis labels, calls {@link #getFormattedValue(float)} by default.
*
* @param value float to be formatted
* @param axis axis being labeled
* @return formatted string label
*/
public String getAxisLabel(float value, AxisBase axis) {
return getFormattedValue(value);
}
/**
* Used to draw bar labels, calls {@link #getFormattedValue(float)} by default.
*
* @param barEntry bar being labeled
* @return formatted string label
*/
public String getBarLabel(BarEntry barEntry) {
return getFormattedValue(barEntry.getY());
}
/**
* Used to draw stacked bar labels, calls {@link #getFormattedValue(float)} by default.
*
* @param value current value to be formatted
* @param stackedEntry stacked entry being labeled, contains all Y values
* @return formatted string label
*/
public String getBarStackedLabel(float value, BarEntry stackedEntry) {
return getFormattedValue(value);
}
/**
* Used to draw line and scatter labels, calls {@link #getFormattedValue(float)} by default.
*
* @param entry point being labeled, contains X value
* @return formatted string label
*/
public String getPointLabel(Entry entry) {
return getFormattedValue(entry.getY());
}
/**
* Used to draw pie value labels, calls {@link #getFormattedValue(float)} by default.
*
* @param value float to be formatted, may have been converted to percentage
* @param pieEntry slice being labeled, contains original, non-percentage Y value
* @return formatted string label
*/
public String getPieLabel(float value, PieEntry pieEntry) {
return getFormattedValue(value);
}
/**
* Used to draw radar value labels, calls {@link #getFormattedValue(float)} by default.
*
* @param radarEntry entry being labeled
* @return formatted string label
*/
public String getRadarLabel(RadarEntry radarEntry) {
return getFormattedValue(radarEntry.getY());
}
/**
* Used to draw bubble size labels, calls {@link #getFormattedValue(float)} by default.
*
* @param bubbleEntry bubble being labeled, also contains X and Y values
* @return formatted string label
*/
public String getBubbleLabel(BubbleEntry bubbleEntry) {
return getFormattedValue(bubbleEntry.getSize());
}
/**
* Used to draw high labels, calls {@link #getFormattedValue(float)} by default.
*
* @param candleEntry candlestick being labeled
* @return formatted string label
*/
public String getCandleLabel(CandleEntry candleEntry) {
return getFormattedValue(candleEntry.getHigh());
}
}
write_fragment.java
package com.example.writediary;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
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.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.FileProvider;
import androidx.fragment.app.Fragment;
import com.github.channguyen.rsv.RangeSliderView;
import com.google.android.material.slider.RangeSlider;
import java.io.File;
import java.io.FileOutputStream;
import java.util.Date;
public class write_fragment extends Fragment {
Context context;
onTabItemSelectedListener listener;
onRequestListener requestListener;
// 뷰 아이템 id
ImageView weatherIcon;
ImageView imagetoset;
int weatherIndex=0;
int moodIndex=2;
TextView locationTextView;
TextView datetext;
EditText contentsInput;
EditText titleInput;
Note item;
RangeSliderView moodSlider;
// 사진 찍기 기능
boolean isphotoCaptured;
boolean isPhotoCanceled;
boolean isphotoFileSaved;
int selectedPhotoMenu;
// 사진 파일
File file;
Bitmap resultPhotoBitmap;
// 밑의 버튼 3개
int mMode=AppConstants.MODE_INSERT;
public void setTitle(String s){
titleInput.setText(s);
}
public void setContent(String s){ contentsInput.setText(s);}
public void setDateString(String s){
datetext.setText(s);
}
public void setAddress(String s){
locationTextView.setText(s);
}
public void setContents(String data) {
contentsInput.setText(data);
}
public void setWeather(String data){
if (data != null) {
if (data.equals("맑음")) {
weatherIcon.setImageResource(R.drawable.weather_icon_1);
weatherIndex = 0;
} else if (data.equals("구름 조금")) {
weatherIcon.setImageResource(R.drawable.weather_icon_2);
weatherIndex = 1;
} else if (data.equals("구름 많음")) {
weatherIcon.setImageResource(R.drawable.weather_icon_3);
weatherIndex = 2;
} else if (data.equals("흐림")) {
weatherIcon.setImageResource(R.drawable.weather_icon_4);
weatherIndex = 3;
} else if (data.equals("비")) {
weatherIcon.setImageResource(R.drawable.weather_icon_5);
weatherIndex = 4;
} else if (data.equals("눈/비")) {
weatherIcon.setImageResource(R.drawable.weather_icon_6);
weatherIndex = 5;
} else if (data.equals("눈")) {
weatherIcon.setImageResource(R.drawable.weather_icon_7);
weatherIndex = 6;
} else {
System.out.println("setWeather() 오류 : " + data);
}
}
}
public void setWeatherIndex(int index) {
if (index == 0) {
weatherIcon.setImageResource(R.drawable.weather_icon_1);
weatherIndex = 0;
} else if (index == 1) {
weatherIcon.setImageResource(R.drawable.weather_icon_2);
weatherIndex = 1;
} else if (index == 2) {
weatherIcon.setImageResource(R.drawable.weather_icon_3);
weatherIndex = 2;
} else if (index == 3) {
weatherIcon.setImageResource(R.drawable.weather_icon_4);
weatherIndex = 3;
} else if (index == 4) {
weatherIcon.setImageResource(R.drawable.weather_icon_5);
weatherIndex = 4;
} else if (index == 5) {
weatherIcon.setImageResource(R.drawable.weather_icon_6);
weatherIndex = 5;
} else if (index == 6) {
weatherIcon.setImageResource(R.drawable.weather_icon_7);
weatherIndex = 6;
} else {
System.out.println("setWeatherIndex() 오류 : " + index);
}
}
@Override
public void onAttach(@NonNull Context context) {
super.onAttach(context);
this.context=context;
if(context instanceof onTabItemSelectedListener){
this.listener=(onTabItemSelectedListener) context;
}
if(context instanceof onRequestListener){
this.requestListener=(onRequestListener) context;
}
}
@Override
public void onDetach() {
super.onDetach();
if(context!=null){
context=null;
listener=null;
}
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
ViewGroup rootview=(ViewGroup) inflater.inflate(R.layout.write_fragment,container,false);
initUI(rootview);
if(requestListener!=null){
requestListener.onRequest("getCurrentLocation");
}
applyItem();
return rootview;
}
public void applyItem() {
if (item != null) {
mMode = AppConstants.MODE_MODIFY;
setWeatherIndex(Integer.parseInt(item.getWeather()));
setAddress(item.getAddress());
setDateString(item.getCreateDateStr());
setTitle(item.getTitle());
setContents(item.getContents());
String picturePath = item.getPicture();
if (picturePath == null || picturePath.equals("")) {
imagetoset.setImageResource(R.drawable.noimagefound);
} else {
setPicture(item.getPicture(), 1);
}
setMood(item.getMood());
} else {
mMode = AppConstants.MODE_INSERT;
setWeatherIndex(0);
setAddress("");
Date currentDate = new Date();
String currentDateString = AppConstants.dateFormat6.format(currentDate);
setDateString(currentDateString);
contentsInput.setText("");
imagetoset.setImageResource(R.drawable.noimagefound);
setMood("2");
}
}
public void setPicture(String picturePath, int sampleSize) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = sampleSize;
resultPhotoBitmap = BitmapFactory.decodeFile(picturePath, options);
imagetoset.setImageBitmap(resultPhotoBitmap);
}
public void setMood(String mood) {
try {
moodIndex = Integer.parseInt(mood);
moodSlider.setInitialIndex(moodIndex);
} catch(Exception e) {
e.printStackTrace();
}
}
public void showDialog(int command){
AlertDialog.Builder builder=null;
switch (command){
case AppConstants.CONTENT_PHOTO:
builder=new AlertDialog.Builder(context);
builder.setTitle("사진 메뉴 선택");
builder.setSingleChoiceItems(R.array.array_photo,0, new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialogs, int whichButton){
selectedPhotoMenu=whichButton;
}
});
builder.setPositiveButton("선택", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if(selectedPhotoMenu==0){
showPhotoCaptureActivity();
}
else if(selectedPhotoMenu==1){
showPhotoSelectionActivity();
}
}
});
builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// 취소 시 동작 안함
}
});
break;
case AppConstants.CONTENT_PHOTO_EX:
builder=new AlertDialog.Builder(context);
builder.setTitle("사진 메뉴 선택");
builder.setSingleChoiceItems(R.array.array_photo_EX, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
selectedPhotoMenu=i;
}
});
builder.setPositiveButton("선택", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
if(selectedPhotoMenu==0){
showPhotoCaptureActivity();
}
else if(selectedPhotoMenu==1){
showPhotoSelectionActivity();
}
else if(selectedPhotoMenu==2){
isPhotoCanceled=true;
isphotoCaptured=false;
imagetoset.setImageResource(R.drawable.picture1);
}
}
});
builder.setNegativeButton("취소", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
// do nothing
}
});
break;
default:
break;
}
AlertDialog dialog=builder.create();
dialog.show();
}
public void showPhotoCaptureActivity(){
if(file==null){
file=createFile();
}
Uri fileUri= FileProvider.getUriForFile(context,"com.example.writediary.fileprovider",file);
Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);
if(intent.resolveActivity(context.getPackageManager())!=null){
startActivityForResult(intent,AppConstants.REQ_PHOTO_CAPTURE);
}
}
public void showPhotoSelectionActivity(){
Intent intent=new Intent(Intent.ACTION_PICK,MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(intent,AppConstants.REQ_PHOTO_SELECTION);
}
private File createFile(){
String filename="capture.jpg";
File storageDR= Environment.getExternalStorageDirectory();
File outFile=new File(storageDR,filename);
return outFile;
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(intent!=null){
switch (requestCode){
case AppConstants.REQ_PHOTO_CAPTURE:
resultPhotoBitmap=decodeSampledBitmapFromResource(file,imagetoset.getWidth(),
imagetoset.getHeight());
imagetoset.setImageBitmap(resultPhotoBitmap);
break;
case AppConstants.REQ_PHOTO_SELECTION:
Uri selectedImg=intent.getData();
String[] filepathColumn={MediaStore.Images.Media.DATA};
Cursor cursor=context.getContentResolver().query(selectedImg,filepathColumn,null,null,null);
cursor.moveToFirst();
int columnindex=cursor.getColumnIndex(filepathColumn[0]);
String filepath= cursor.getString(columnindex);
cursor.close();
resultPhotoBitmap=decodeSampledBitmapFromResource(new File(filepath),
imagetoset.getWidth(), imagetoset.getHeight());
imagetoset.setImageBitmap(resultPhotoBitmap);
isphotoCaptured=true;
break;
}
}
}
public static Bitmap decodeSampledBitmapFromResource(File res, int width, int height){
final BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds=true;
BitmapFactory.decodeFile(res.getAbsolutePath(),options);
options.inSampleSize=calculateInSamplesize(options,width,height);
options.inJustDecodeBounds=false;
return BitmapFactory.decodeFile(res.getAbsolutePath(),options);
}
public static int calculateInSamplesize(BitmapFactory.Options options,int width, int height){
final int _height= options.outHeight;
final int _width= options.outWidth;
int sampleSize=1;
if(_height>height||_width>width){
final int halfH=height;
final int halfW=width;
while((halfH/sampleSize)>=height&&(halfW/sampleSize)>=width){
sampleSize*=2;
}
}
return sampleSize;
}
private String createFilename(){
Date curDate=new Date();
String curDateStr=String.valueOf(curDate.getTime());
return curDateStr;
}
private void initUI(ViewGroup view){
datetext=view.findViewById(R.id.dateView);
weatherIcon=view.findViewById(R.id.weather_icon);
locationTextView=view.findViewById(R.id.locationView);
contentsInput=view.findViewById(R.id.edit_content);
titleInput=view.findViewById(R.id.edit_title);
imagetoset=view.findViewById(R.id.imageToSet);
imagetoset.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(isphotoCaptured||isphotoFileSaved){
showDialog(AppConstants.CONTENT_PHOTO_EX);
}
else{
showDialog(AppConstants.CONTENT_PHOTO);
}
}
});
moodSlider=view.findViewById(R.id.sliderVew);
Button saveButton=view.findViewById(R.id.saveButton);
saveButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mMode==AppConstants.MODE_INSERT){
saveNote();
}
else if(mMode==AppConstants.MODE_MODIFY){
ModifyNote();
}
if(listener!=null){
listener.onTabSelected(0);
}
}
});
Button deleteButton=view.findViewById(R.id.deleteButton);
deleteButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
deleteNote();
if(listener!=null){
listener.onTabSelected(0);
}
}
});
Button closeButton=view.findViewById(R.id.closeButton);
closeButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(listener!=null){
listener.onTabSelected(0);
}
}
});
RangeSliderView sliderView=view.findViewById(R.id.sliderVew);
final RangeSliderView.OnSlideListener listener=new RangeSliderView.OnSlideListener() {
@Override
public void onSlide(int index) {
moodIndex=index;
}
};
sliderView.setOnSlideListener(listener);
sliderView.setInitialIndex(2);
}
private void saveNote(){
String address=locationTextView.getText().toString();
String contents=contentsInput.getText().toString();
String title=titleInput.getText().toString();
String picPath=savePicture();
String sql="insert into "+NoteDatabase.TABLE_NOTE+"(WEATHER, ADDRESS, LOCATION_X, LOCATION_Y, CONTENTS, TITLE, MOOD, PICTURE) values("+
"'"+weatherIndex+"', "+
"'"+address+"', "+
"'"+""+"', "+
"'"+""+"', "+
"'"+contents+"', "+
"'"+title+"', "+
"'"+moodIndex+"', "+
"'"+picPath+"')";
NoteDatabase database=NoteDatabase.getInstance(context);
database.execSQL(sql);
}
private void ModifyNote(){
if(item!=null){
String address=locationTextView.getText().toString();
String contents=contentsInput.getText().toString();
String title=titleInput.getText().toString();
String picPath=savePicture();
String sql = "update " + NoteDatabase.TABLE_NOTE +
" set " +
" WEATHER = '" + weatherIndex + "'" +
" ,ADDRESS = '" + address + "'" +
" ,LOCATION_X = '" + "" + "'" +
" ,LOCATION_Y = '" + "" + "'" +
" ,CONTENTS = '" + contents + "'" +
" ,TITLE = '" + title + "'" +
" ,MOOD = '" + moodIndex + "'" +
" ,PICTURE = '" + picPath + "'" +
" where " +
" _id = " + item.id;
NoteDatabase database=NoteDatabase.getInstance(context);
database.execSQL(sql);
}
}
private void deleteNote(){
if(item!=null){
String sql="delete from "+NoteDatabase.TABLE_NOTE+" where _id = "+item.id;
NoteDatabase database=NoteDatabase.getInstance(context);
database.execSQL(sql);
}
}
private String savePicture(){
if(resultPhotoBitmap==null){
return "";
}
File photoFolder=new File(AppConstants.FOLDER_PHOTO);
if(!photoFolder.isDirectory()){
photoFolder.mkdirs();
}
String photoFilename=createFilename();
String picPath=photoFolder+File.separator+photoFilename;
try{
FileOutputStream outstream=new FileOutputStream(picPath);
resultPhotoBitmap.compress(Bitmap.CompressFormat.PNG,100,outstream);
outstream.close();
} catch (Exception e){
e.printStackTrace();
}
return picPath;
}
public void setItem(Note _item){
this.item=_item;
}
}
ExampleInstrumentedTest.java
package com.example.writediary;
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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
assertEquals("com.example.writediary", appContext.getPackageName());
}
}
ExampleUnitTest.java
package com.example.writediary;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Example local unit test, which will execute on the development machine (host).
*
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}
drawable에 사용되는 사진이 많은 관계로 메일로 첨부하겠다.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="@drawable/back"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navi"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="10dp"
app:itemBackground="@color/back"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:menu="@menu/menu_bottom">
</com.google.android.material.bottomnavigation.BottomNavigationView>
</androidx.constraintlayout.widget.ConstraintLayout>
list_fragment.xaml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
tools:context=".list_fragment">
<RelativeLayout
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<lib.kingja.switchbutton.SwitchMultiButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/switchButton"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginTop="20dp"
android:layout_marginLeft="20dp"
android:padding="8dp"
app:strokeRadius="5dp"
app:strokeWidth="2dp"
app:selectedTab="0"
app:selectedColor="#eb7b00"
app:switchTabs="@array/switch_tabs"
app:textSize="14sp"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/writeButton"
android:layout_margin="10dp"
android:layout_alignParentRight="true"
android:text="작성하기"
android:background="@drawable/select_button"
android:textColor="@color/white"/>
</RelativeLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="8dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"/>
</LinearLayout>
note_item.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
app:cardElevation="20dp"
android:layout_margin="15dp"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="10dp"
android:layout_height="wrap_content">
<LinearLayout
android:id="@+id/layout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:orientation="horizontal">
<ImageView
android:layout_marginLeft="10sp"
android:id="@+id/mood_img"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:padding="5dp"
app:srcCompat="@drawable/smile5_48" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/content"
android:layout_width="271dp"
android:layout_height="wrap_content"
android:layout_marginLeft="15sp"
android:layout_marginTop="10dp"
android:fontFamily="serif-monospace"
android:gravity="center"
android:maxLines="1"
android:text="내용"
android:textColor="@color/black"
android:textSize="24sp"
android:textStyle="bold" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp">
<ImageView
android:id="@+id/weather_img"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:layout_margin="5dp"
app:srcCompat="@drawable/weather_1" />
<ImageView
android:id="@+id/user_img"
android:layout_width="32dp"
android:layout_height="32dp"
app:srcCompat="@drawable/picture_128"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/weather_img"/>
<TextView
android:id="@+id/location"
android:layout_width="134dp"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:layout_centerInParent="true"
android:gravity="left"
android:fontFamily="serif-monospace"
android:text="강남구"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="italic|bold" />
<TextView
android:id="@+id/date"
android:layout_marginRight="15sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:textSize="16sp"
android:textColor="@color/black"
android:fontFamily="serif-monospace"
android:textStyle="bold"
android:text="02/10" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/layout2"
android:visibility="visible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/user_img2"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_margin="10dp"
android:layout_gravity="center_vertical"
android:padding="10dp"
app:srcCompat="@drawable/picture1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_marginTop="5dp"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:id="@+id/content2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:text="제목"
android:gravity="center"
android:ellipsize="none"
android:layout_marginLeft="10dp"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="@color/black"
android:fontFamily="serif-monospace"
android:maxLines="1"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="10dp">
<ImageView
android:id="@+id/mood_img2"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_alignParentLeft="true"
android:padding="5dp"
app:srcCompat="@drawable/smile5_48" />
<ImageView
android:id="@+id/weather_img2"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_toRightOf="@+id/mood_img2"
android:layout_marginLeft="10dp"
app:srcCompat="@drawable/weather_icon_1" />
<TextView
android:id="@+id/location2"
android:layout_width="200sp"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:fontFamily="serif-monospace"
android:gravity="left"
android:maxLines="1"
android:text="TextView"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="italic|bold" />
<TextView
android:id="@+id/date2"
android:textStyle="bold"
android:fontFamily="serif-monospace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" android:padding="10dp"
android:text="02/10" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
splash_back.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:background="@drawable/back"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:src="@drawable/sample46"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
statistic_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginBottom="5dp"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="20dp"
app:cardElevation="15dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:layout_margin="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="24sp"
android:textColor="@color/gray"
android:fontFamily="serif-monospace"
android:text="@string/graph1_title" />
<com.github.mikephil.charting.charts.PieChart
android:layout_width="250dp"
android:layout_height="250dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:id="@+id/chart1"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="20dp"
app:cardElevation="15dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:textColor="@color/gray"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="24sp"
android:layout_margin="20dp"
android:fontFamily="serif-monospace"
android:text="@string/graph2_title" />
<com.github.mikephil.charting.charts.BarChart
android:layout_width="250dp"
android:layout_height="250dp"
android:id="@+id/chart2"
android:layout_marginTop="10dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="20dp"
app:cardElevation="15dp"
android:layout_marginRight="20dp"
android:layout_marginLeft="20dp"
android:layout_marginBottom="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:textStyle="bold"
android:textSize="24sp"
android:textColor="@color/gray"
android:fontFamily="serif-monospace"
android:text="@string/graph3_title" />
<com.github.mikephil.charting.charts.LineChart
android:layout_width="250dp"
android:layout_height="250dp"
android:id="@+id/chart3"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:layout_gravity="center_horizontal"/>
</LinearLayout>
</androidx.cardview.widget.CardView>
</LinearLayout>
</ScrollView>
write_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".write_fragment">
<RelativeLayout
android:id="@+id/TopLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:elevation="10dp"
android:padding="4dp">
<ImageView
android:id="@+id/weather_icon"
android:layout_width="45dp"
android:layout_height="45dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="15dp"
android:background="#CCFFFFFF"
android:backgroundTint="@color/white"
android:src="@drawable/weather_icon_1" />
<TextView
android:id="@+id/dateView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:gravity="left"
android:layout_marginEnd="15dp"
android:layout_marginBottom="15dp"
android:fontFamily="serif-monospace"
android:text="yy/MM/DD"
android:textSize="26sp"
android:textStyle="bold" />
<TextView
android:id="@+id/locationView"
android:layout_width="100sp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:layout_marginTop="15dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="15dp"
android:ellipsize="end"
android:fontFamily="serif-monospace"
android:gravity="center"
android:text="삼성동"
android:textSize="13sp"
android:textStyle="bold|italic" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/ContentsLayout"
android:layout_width="match_parent"
android:layout_below="@+id/TopLayout"
android:layout_above="@+id/MoodLayout"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_marginTop="5dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_alignParentTop="true"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="10dp"
android:elevation="10dp"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<EditText
android:id="@+id/edit_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:layout_marginTop="20dp"
android:layout_marginRight="20dp"
android:layout_marginBottom="10dp"
android:fontFamily="serif-monospace"
android:hint="@string/Title"
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:inputType="textPersonName"
android:maxLines="1"
android:singleLine="false"
android:textSize="32sp" />
<EditText
android:textColor="@color/black"
android:textColorHint="@color/gray"
android:id="@+id/edit_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:inputType="textPersonName"
android:hint="How was your day today?"
android:fontFamily="serif-monospace"/>
<ImageView
android:id="@+id/imageToSet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
android:src="@drawable/imagetoset" />
</LinearLayout>
</androidx.cardview.widget.CardView>
</RelativeLayout>
<androidx.cardview.widget.CardView
android:id="@+id/MoodLayout"
android:layout_marginLeft="10dp"
android:layout_above="@+id/BottomLayout"
android:layout_marginTop="8dp"
android:layout_marginBottom="4dp"
android:layout_marginRight="10dp"
android:layout_width="match_parent"
app:cardBackgroundColor="#FFFFFFFF"
app:cardCornerRadius="20dp"
app:cardElevation="20dp"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.github.channguyen.rsv.RangeSliderView
android:id="@+id/sliderVew"
android:layout_width="match_parent"
android:layout_height="40dp"
android:layout_marginTop="20dp"
app:filledColor="#FF6600"
app:emptyColor="#a8aeb8"
app:rangeCount="5"
app:sliderRadiusPercent="0.5"
app:barHeightPercent="0.1"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:layout_marginBottom="10dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:orientation="horizontal">
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/smile1_48" />
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/smile2_48" />
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/smile3_48" />
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/smile4_48" />
<ImageView
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="1"
android:src="@drawable/smile5_48" />
</LinearLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<RelativeLayout
android:id="@+id/BottomLayout"
android:layout_marginBottom="60dp"
android:padding="10dp"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/saveButton"
android:layout_alignParentLeft="true"
android:layout_marginLeft="30dp"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="serif-monospace"
android:background="@drawable/select_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="저장" />
<Button
android:id="@+id/deleteButton"
android:layout_centerInParent="true"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="serif-monospace"
android:background="@drawable/select_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="삭제" />
<Button
android:id="@+id/closeButton"
android:layout_alignParentRight="true"
android:layout_marginRight="30dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/white"
android:textSize="16sp"
android:textStyle="bold"
android:fontFamily="serif-monospace"
android:background="@drawable/select_button"
android:text="닫기" />
</RelativeLayout>
</RelativeLayout>
menu_button.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/tab1"
app:showAsAction="ifRoom"
android:enabled="true"
android:icon="@drawable/list_48"
android:iconTint="@color/white"
android:title=" "/>
<item
android:id="@+id/tab2"
app:showAsAction="ifRoom"
android:enabled="true"
android:iconTint="@color/white"
android:icon="@drawable/write_48"
android:title=" "/>
<item
android:id="@+id/tab3"
app:showAsAction="ifRoom"
android:enabled="true"
android:iconTint="@color/white"
android:icon="@drawable/graph_48"
android:title=" "/>
</menu>
array.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="switch_tabs">
<item>내용</item>
<item>사진</item>
</string-array>
<string-array name="switch_days">
<item>월</item>
<item>화</item>
<item>수</item>
<item>목</item>
<item>금</item>
<item>토</item>
<item>일</item>
</string-array>
<string-array name="array_photo">
<item>사진 찍기</item>
<item>앨범에서 선택하기</item>
</string-array>
<string-array name="array_photo_EX">
<item>사진 찍기</item>
<item>앨범에서 선택하기</item>
<item>사진 삭제하기</item>
</string-array>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="back">#283048</color>
<color name="gray">#708090</color>
</resources>
strings.xml
<resources>
<string name="app_name">TODAY WRITE</string>
<string name="graph1_title">기분 별 비율</string>
<string name="graph2_title">요일 별 기분</string>
<string name="graph3_title">기분 변화</string>
<string name="Title">TITLE</string>
</resources>
values\themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.WriteDiary" parent="Theme.AppCompat.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
<style name="SplashTheme" parent="Theme.AppCompat.NoActionBar">
</style>
</resources>
night\themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.WriteDiary" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
external.xml
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path
name="sdcard"
path="."/>
</paths>
build.gradle (:app)
plugins {
id 'com.android.application'
}
android {
compileSdk 31
defaultConfig {
applicationId "com.example.writediary"
minSdk 30
targetSdk 31
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
debug{
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.0'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation 'lib.kingja.switchbutton:switchbutton:1.1.8'
implementation 'com.github.channguyen:rsv:1.0.1'
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0-alpha'
implementation 'com.github.pedroSG94:AutoPermissions:1.0.3'
}
구성형태
일기 기능 개발을 완료 하였다.
https://user-images.githubusercontent.com/115603720/203324102-5b7a4196-54cd-41e0-a7a0-c84d84d21e95.mp4