Skip to content

๐Ÿท๐Ÿง‘๐Ÿปโ€๐Ÿ’ป We-Are-Heroid ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป๐Ÿท

Notifications You must be signed in to change notification settings

placepic/placepic_android

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿท placepic_Android : Heroid

placepic_bedge android_bedge


  • SOPT 26th APPJAM - Team placepic

  • ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„: 2020.06.28 ~ 2020.07.18


๐Ÿ“ placepic service

์šฐ๋ฆฌ๋“ค๋ผ๋ฆฌ ๊ณต์œ ํ•˜๋Š” ์ตœ์•  ์žฅ์†Œ, ํ”Œ๋ ˆ์ด์Šคํ”ฝ

ํ”Œ๋ ˆ์ด์Šคํ”ฝ์€ ์‹ ๋ขฐ์žˆ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ ๊ธฐ๋ฐ˜์˜ ์žฅ์†Œ ์ •๋ณด ๊ณต์œ  ํ”Œ๋žซํผ์ž…๋‹ˆ๋‹ค.

Service key Feature

  • Exploration - ์‰ฝ๊ณ , ๋น ๋ฅด๊ฒŒ ์›ํ•˜๋Š” ์žฅ์†Œ๋ฅผ ํƒ์ƒ‰

  • Discovery - ๊ฐ€๋ณด๊ณ  ์‹ถ์€ ์žฅ์†Œ๋ฅผ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•จ

  • Interaction - ์ƒํ˜ธ์ž‘์šฉ, ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ณต๊ฐ„


โœ Core value

๐Ÿ” App Jam Goal

  • ์šฐ๋ฆฌ๊ฐ€ ์“ธ ์ˆ˜ ์žˆ๊ณ , ์“ฐ๊ณ  ์‹ถ์€ ์„œ๋น„์Šค๋ฅผ ๋งŒ๋“ค์–ด๋‚ผ ๊ฒƒ์ด๋‹ค.

๐Ÿ‘ฅ์šฐ๋ฆฌ๊ฐ€ ์ถ”๊ตฌํ•˜๋Š” ๊ฐ€์น˜

  • ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ๋Œ€ํ•œ ์ง‘์ฐฉ
  • ์ž๊ธฐ์ฃผ๋„์„ฑ
  • ๋ฆฐ ์Šคํƒ€ํŠธ์—… ์ •์‹ 
  • PRIDEโœจ

๐Ÿ–ฅ Code convention

  • git branch

์ด์Šˆ ๋ณ„๋กœ branch ๊ตฌ์„ฑ

  • git commit message rule
[Feat] ๊ธฐ๋Šฅ ์ถ”๊ฐ€
[Fix] ๋ฒ„๊ทธ ์ˆ˜์ •
[Refactor] ๋ฆฌํŒฉํ† ๋ง
[Chore] ๊ฐ„๋‹จํ•œ ์ˆ˜์ •
[Delete] ๊ธฐ๋Šฅ ์‚ญ์ œ
[Docs] ๋ฌธ์„œ

๐Ÿ‘ช Communication

Notion, SLACK


๐Ÿค Role

ํ˜

   - ์žฅ์†Œ๋ฆฌ์ŠคํŠธ  
   - ์ง€ํ•˜์ฒ ๊ฒ€์ƒ‰  
   - ์ตœ์• ์žฅ์†Œ ์—…๋กœ๋“œ View  
   - ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ๊ตฌํ˜„  
   - ์ธ์•ฑ๋ธŒ๋ผ์šฐ์ € ๊ตฌํ˜„
   - ์ €์žฅ ํŽ˜์ด์ง€
   - custom ํ™•์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ
   - kotlin collection ํ™•์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ 

์ง„์ˆ˜

    - ๋กœ๊ทธ์ธ, ๋กœ๊ทธ์ธ ํŽ˜์ด์ง€ View Layout 
    - ๋‚ด ๊ทธ๋ฃน, ์Šน์ธ๋Œ€๊ธฐ ํŽ˜์ด์ง€
    - ๊ทธ๋ฃน ์‹ ์ฒญ ํŽ˜์ด์ง€, ๊ทธ๋ฃน ์‹ ์ฒญ ์™„๋ฃŒ
    - ๊ด€๋ฆฌ์ž ํŽ˜์ด์ง€  
    - ๋””ํ…Œ์ผ ํŽ˜์ด์ง€  
    - kotlin collection ํ™•์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ : Let, forEach
    - ์‹ฑ๊ธ€ํ„ด SharedPreference ๊ตฌํ˜„
    - custom enqueue ์ž‘์„ฑ

๋‹คํ˜œ

    - ์žฅ์†Œ๊ฒ€์ƒ‰ ํŽ˜์ด์ง€  
    - ํƒœ๊ทธ์„ ํƒ ํŽ˜์ด์ง€
    - Chip ๊ตฌํ˜„  
    - PlacePicService ๊ตฌํ˜„ 
    - ์ˆœ์œ„ ํŽ˜์ด์ง€ 

์ˆ˜์ •

    - ๋กœ๊ทธ์ธ, ๋กœ๊ทธ์ธ ๋ฉ”์ธ, ํšŒ์›๊ฐ€์ž… ํŽ˜์ด์ง€ 
    - ์ตœ์• ์žฅ์†Œ ์—…๋กœ๋“œ View Layout  
    - ์ด๋ฏธ์ง€ ์—…๋กœ๋“œ ์ดˆ๊ธฐ ๊ตฌํ˜„  
    - Bottom Navigation ์ปค์Šคํ…€  
    - ๋กœ๊ทธ์•„์›ƒ 
    - ๋งˆ์ดํŽ˜์ด์ง€
    - ์Šคํ”Œ๋ž˜์‰ฌ ํ™”๋ฉด  


๐Ÿ“ˆ Work Flow



๐Ÿ“ ConstraintLayout

  • ์ ˆ๋Œ€ ํฌ๊ธฐ ์ง€์ •

์„œ๋ฒ„์— ์—…๋กœ๋“œ๋  ์‚ฌ์ง„์˜ ํฌ๊ธฐ๊ฐ€ ์ผ์ •ํ•˜์ง€ ์•Š์œผ๋ฏ€๋กœ ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ฃผ๋Š” ์‚ฌ์ง„์€ ์ ˆ๋Œ€ ํฌ๊ธฐ๋กœ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

- activity_detail_view.xml
- activity_end_group_join.xml
- activity_join_group.xml
- item_group_list.xml
- item_photo.xml
- item_get_image_button.xml
- item_image_to_upload.xml
- item_place.xml
- item_subway_line.xml
- fragment_my_page.xml
- item_group_list.xml
- item_like_user_list.xml
- item_place.xml

๋ทฐ์—์„œ ํŠน์ • ๊ตฌ์—ญ์„ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด height ์†์„ฑ ์ง€์ •

- item_member.xml

  • ๋ชจ๋“  ๋ทฐ์˜ ์ƒ๋‹จ ๋ฐ”

์ƒ๋‹จ๋ฐ”์˜ ๋†’์ด๋ฅผ 56dp๋กœ ์ผ์ •ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ’์„ ์คŒ height์— ๊ฐ’์„ ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

- activity_upload_place.xml
- fragment_places.xml
- item_place.xml
- item_place_search.xml
- item_search_subway.xml
- activity_user_info.xml
- activity_web.xml
- fragment_admin_page.xml
- item_group_list.xml

  • ๋””์ž์ธ๋œ line์„ ๋„ฃ๊ธฐ ์œ„ํ•ด height ์†์„ฑ ์ง€์ •

bottom navigation์„ ์ปค์Šคํ…€ํ•˜์—ฌ ๊ฐ€์šด๋ฐ๋ฅผ ๋ฒ„ํŠผ์œผ๋กœ ๋ฐ”๊พธ๊ธฐ ์œ„ํ•ด ์ž„์˜๋กœ width, height ๊ฐ’ ์ง€์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

- activity_main.xml

  • match_constraint ์‚ฌ์šฉ ๋ทฐ
- activity_detail_view.xml
- activity_keword_tag.xml 
- activity_login.xml
- activity_place_search.xml
- activity_search_subway.xml
- activity_sign_up.xml
- activiy_sign_up_second.xml
- activity_upload_place.xml
- activivty_useful_tag.xml
- fragment_places.xml
- item_place.xml
- activity_upload_place.xml
- activity_useful_tag.xml
- acticity_user_info.xml
...

  • layout ์‚ฌ์šฉ

๋ฐ์ดํ„ฐ ๋ฐ”์ธ๋”ฉ์œผ๋กœ ์ธํ•ด layout์•ˆ์— ConstraintLayout์„ ์‚ฌ์šฉํ•จ

- activity_detail_veiw.xml
- activity_search_subway.xml
- activity_upload_place.xml
- fragment_loading.xml
- fragment_place_items.xml
- fragment_places.xml
- item_get_image_button.xml
- item_image_to_upload.xml
- item_keyword_tag.xml
- item_place.xml
- item_place_filter.xml
- item_searched_subway.xml
- item_subway.xml
- item_subway_line.xml

์ด์™ธ์—๋Š” ๋ชจ๋‘ Constraintlayout์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.



๐Ÿ“Œ Function

kotlin collection์˜ ํ™•์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ

  1. map

    ImageUriExtractor.kt

    KeywordChips.kt

    PlacesPagerAdapter.kt

    FeatureChips.kt

    PlacesRequest.kt

    UploadPlaceRequest.kt

    PlaceItemResponse.kt

    PlaceTypeDetailsResponse.kt

    SubwayRespons.kt

    BasicBindingAdapter.kt

    PlacesViewModel.kt

    PlacesAdapter.kt

  2. filter

    SubwaySearchViewModel.kt

  3. run

    PlacesRequest.kt

    PlaceItemViewModel.kt

    UploadPlaceViewModel.kt

  4. also

    PlacesAdapter.kt

  5. Let

    SignUpGroupActivity.kt

    PlacesRequest.kt

    UploadPlaceRequest.kt

    GroupListActivity.kt

    JoinGroupActivity.kt

    WaitGroupActivity.kt

    WaitUserListActivity.kt

  6. forEach

    KeywordChips.kt

    FeatureChips.kt

    DetailViewActivity.kt

  7. first

    PlacesPagerAdapter.kt

    Place.kt

    Subway.kt

  8. sortedBy

    PlacesPagerAdapter.kt

  9. getOrElse

    PlaceItemResponse.kt


custom ํ™•์žฅ ํ•จ์ˆ˜ ์‚ฌ์šฉ

  • hasSingleImage()

์ด๋ฏธ์ง€ ํ”ผ์ปค์—์„œ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ 1๊ฐœ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ์™€ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ ์ ‘๊ทผํ•ด์•ผ ํ•  ํ•„๋“œ๊ฐ€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

๊ทธ๋ ‡๊ธฐ์— ํ•œ์žฅ์งœ๋ฆฌ ์ด๋ฏธ์ง€๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ๋Š” intent์ธ์ง€, ์—ฌ๋Ÿฌ์žฅ์„ ๊ฐ€์ง€๊ณ ์žˆ๋Š” intent์ธ์ง€ ํŒ๋‹จ์„ ์œ„ํ•ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

๋‚ด์žฅ ํ™•์žฅ ํ•จ์ˆ˜ map์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ์จ ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต์˜ ๊ฐ€๋…์„ฑ์„ ๋†’ํ˜”์Šต๋‹ˆ๋‹ค.

<ImageUriExtractor.kt>

...

fun from(intent: Intent?): List<ImageUri> {
            if (intent == null) return emptyList()
            if (intent.hasSingleImage()) return getSingleImage(intent)
            return getMultipleImages(intent)
        }

        private fun Intent.hasSingleImage(): Boolean {
            return this.data != null
        }

... 


๐Ÿ”ง Libraries Used

Name Gradle
View androidx.constraintlayout:constraintlayout:1.1.3
androidx.legacy:legacy-support-v4:1.0.0
androidx.recyclerview:recyclerview:1.1.0
group: 'de.hdodenhof', name: 'circleimageview', version: '3.1.0'
LiveData androidx.lifecycle:lifecycle-livedata-ktx:2.2.0
Material Design com.google.android.material:material:1.3.0-alpha01
glide com.github.bumptech.glide:glide:4.11.0
com.github.bumptech.glide:compiler:4.10.0
Circle Imageview Custom de.hdodenhof:circleimageview:3.1.0
com.android.support:design:29.0.0
Circle Indicator me.relex:circleindicator:1.2.2
Toggle Button Custom me.rishabhkhanna:CustomToggle:1.0.0
Gson com.google.code.gson:gson:2.8.6
retrofit com.squareup.retrofit2:retrofit:2.7.1
com.squareup.retrofit2:converter-gson:2.7.1
com.squareup.retrofit2:retrofit-mock:2.6.2
com.squareup.okhttp3:logging-interceptor:4.2.1


๐Ÿฐ Project Structure



โœ”๏ธ Core function Iplementation


  1. Image ์ถ”์ถœ ์œ ํ‹ธ ํด๋ž˜์Šค

Intent๋ฅผ ๋„ฃ๊ธฐ๋งŒํ•˜๋ฉด Image VO์˜ List์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์œ ํ‹ธ์„ฑ ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

์ •์ ํŒฉํ† ๋ฆฌ๋ฉ”์„œ๋“œ ํŒจํ„ด์„ ์ด์šฉํ•˜์—ฌ ์˜์กด์„ฑ๊ณผ ์ ‘๊ทผ์„ฑ์„ ๋‚ฎ์ถ”์—ˆ์Šต๋‹ˆ๋‹ค.

<ImageUriExtractor.kt>

package place.pic.ui.upload

import android.content.Intent

/**
 * Created By Hyeok
 */

class ImageUriExtractor {

    companion object {
        fun from(intent: Intent?): List<ImageUri> {
            if (intent == null) return emptyList()
            if (intent.hasSingleImage()) return getSingleImage(intent)
            return getMultipleImages(intent)
        }
    
        private fun Intent.hasSingleImage(): Boolean {
            return this.data != null
        }
    
        private fun getSingleImage(intent: Intent): List<ImageUri> {
            val imageUri = intent.data
                ?: throw IllegalArgumentException("getSingleImage should not be called when multiple images loaded")
            return listOf(ImageUri(imageUri))
        }
    
        private fun getMultipleImages(intent: Intent): List<ImageUri> {
            val clipData = intent.clipData
                ?: throw IllegalArgumentException("getMultipleImages should not be called when single image loaded")
    
            return IntRange(0, clipData.itemCount - 1)
                .map { clipData.getItemAt(it).uri }
                .map { ImageUri(it) }
        }
    
    }
}

  1. Chip

์—ฌ๋Ÿฌ ๊ณณ์—์„œ Chip์„ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์— ChipFactory๋ผ๋Š” ์œ ํ‹ธ์„ฑ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ด์„œ

์นฉ์ด ํ•„์š”ํ•œ ์ˆœ๊ฐ„์— ์–ธ์ œ๋“ ์ง€ ํ•จ์ˆ˜ ํ˜ธ์ถœ์„ ํ†ตํ•ด Chip์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

<ChipFactory>

package place.pic.ui.tag

import android.view.LayoutInflater
import com.google.android.material.chip.Chip
import place.pic.R

/**
 * Created By kimdahyee
 */

class ChipFactory {

    //๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์ง€์•Š๊ณ  ํ•จ์ˆ˜ ํ˜ธ์ถœ๋งŒ์œผ๋กœ๋„ ์นฉ์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์œ ํ‹ธ์„ฑ method ๋งŒ๋“ค์–ด๋ณด๊ธฐ
    //factory pattern
    //factory.keyword.chip
    //newInstance()
    companion object {
        fun newInstance(layoutInflater: LayoutInflater): Chip {
            return layoutInflater.inflate(R.layout.chip_tag, null, false) as Chip
        }
    
        fun createSmallChip(layoutInflater: LayoutInflater): Chip {
            return layoutInflater.inflate(R.layout.chip_tag_small, null, false) as Chip
        }
    
        fun createDetailChip(layoutInflater: LayoutInflater): Chip {
            return layoutInflater.inflate(R.layout.chip_detail_tag,null,false) as Chip
        }
    }

}

์—์„œ ์‚ฌ์šฉ


  1. Singleton Shared Preference

Shared Preference๋ฅผ ์‹ฑ๊ธ€ํ„ด์œผ๋กœ ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋“œ ํ™˜๊ฒฝ์„ ๊ณ ๋ คํ•˜์—ฌ ํ•œ๋ฒˆ๋งŒ ๊ฐ์ฒด๊ฐ€ ์ƒ์„ฑ๋˜๋„๋ก ํด๋ž˜์Šค๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

<PlacepicAuthRepository.kt>

package place.pic.data

import android.app.Activity
import android.content.Context

/**
 * Created By Jinsu
 */

class PlacepicAuthRepository private constructor(context: Context) {

    private val sharedPreferences = context.getSharedPreferences(context.packageName,Activity.MODE_PRIVATE)
    
    private var editor = sharedPreferences.edit()
    
    val userToken : String?
        get() = sharedPreferences.getString(PLACEPIC_AUTH+"token","")

   val groupId : Int?
        get() = sharedPreferences.getInt(PLACEPIC_AUTH+"groupId",0)

    fun saveUserToken(token:String){
        editor.putString(PLACEPIC_AUTH+"token",token).apply()
    }
    
    fun saveGroupId(groupId: Int) {
        editor.putInt(PLACEPIC_AUTH+"groupId",groupId).apply()
    }
    
    fun removeUserToken(){
        editor.remove(PLACEPIC_AUTH+"token")
    }
    
    fun removeGroupId(){
        editor.remove(PLACEPIC_AUTH+"groupId")
    }
    
    companion object {
        private const val PLACEPIC_AUTH = "placepic_auth_"
    
        @Volatile
        private var instance: PlacepicAuthRepository? = null
    
        @JvmStatic
        fun getInstance(context:Context) = instance ?: synchronized(this) {
            instance ?: PlacepicAuthRepository(context).apply {
                instance = this
            }
        }
    }
}


VIEW VIDIEO



๐Ÿ’ป place pig's android developer

๐Ÿ™‹ [ํ˜] https://github.com/nightmare73

๐Ÿ™‹โ€ [์ง„์ˆ˜] https://github.com/jinsu4755

๐Ÿ™‹โ€ [๋‹คํ˜œ] https://github.com/kimdahyee

๐Ÿ™‹โ€ [์ˆ˜์ •] https://github.com/LeeSuJung-dodung

About

๐Ÿท๐Ÿง‘๐Ÿปโ€๐Ÿ’ป We-Are-Heroid ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป๐Ÿท

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages