- ✔하단바 만들기 (BottomNavigationBar)
- ✔마이페이지 생성하기
- 게시글 작성, 삭제, 조회에 따른 SharedPoint 기능 구현하기
- 교훈 메세지 하나🌱 : 실행 로그 말고 빌드 에러 로그도 잘 보자
예전에 하단바 만든다고 BottomNavigationBar 코드를 구현해놨었는데 그때 정말 알 수 없는 오류가 나서,, 코드가 잘못된 줄 알고 다 뜯어 고치려고 했더니만 오늘 보니까 dependency만 하나 수정해줬더니 바로 코드가 잘 돌아갔다..😭🥰 이거로 애먹을 각오하고 있었는데 너무 행복하다.
하지만 그렇기 때문에 하단바 생성하는 과정을 기록하지 못했다,, 원래 어느정도 진행되고 기록을 몰아서 그날그날 하는 스타일이라 뭐 하나 코드 구현할 때마다 기록하는게 아니라서,,,, 기록 데이터도 없고 머리에 남아있는 것도 없다.
그래도 기억상으로 하단바 구현이 어렵거나 복잡하지는 않았던 것 같다. 그냥 어느 잘 정리된 링크 보고 따라서 하면 금방 다시 할 수 있을거라고,, 믿어.....
implementation 'com.android.support:design:28.0.0'
build.gradle(module:app)
설정 파일의 의존성에 위의 코드를 추가해줬더니 에러는 해결되었다.
그 당시에 에러가 너무 원인을 종잡을 수 없게 나서 도저히 손델 수 없다고 생각했는데 오늘 보니까 바로 build 에러가 나서 바로 찾아낼 수 있었다.
그때는 왜 build 에러가 똑같이 안났을까,, 내가 못찾았나...? 정말 알 수가 없다.
하단바를 구현할 때 이미 구현한 코드이지만 어차피 지금 다시 보면서 이해가 필요해서 겸사겸사 정리한다.
먼저 MainActivity
를 아래 코드와 같이 작성했다. 이제 기존의 Activity의 역할은 fragment가 대신 해주고 이 Activity는 fragment들을 올릴 용도로만 사용한다. 따라서 내용 변동 없이 앞으로 고정될 것이다. (아마도)
이 Activity에서는 하단바에 해당하는 내용만 구현해주면 된다.
package org.techtown.knockknock;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MenuItem;
import android.widget.LinearLayout;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import org.techtown.knockknock.message.MessageFragment;
import org.techtown.knockknock.user.MypageFragment;
public class MainActivity extends AppCompatActivity {
final String TAG = this.getClass().getSimpleName();
LinearLayout home_ly;
BottomNavigationView bottomNavigationView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigationbar);
init(); // 객체 정의
SettingListener(); // 객체등록
//맨처음 시작할 탭 설정
bottomNavigationView.setSelectedItemId(R.id.tab_home);
}
private void init(){
home_ly = findViewById(R.id.home_ly);
bottomNavigationView = findViewById(R.id.bottomNavigationView);
}
private void SettingListener(){
bottomNavigationView.setOnNavigationItemSelectedListener(new TabSelectedListener());
}
class TabSelectedListener implements BottomNavigationView.OnNavigationItemSelectedListener{
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch(item.getItemId()){
case R.id.tab_home:{
getSupportFragmentManager().beginTransaction()
.replace(R.id.home_ly,new HomeFragment())
.commit();
return true;
}
case R.id.tab_message:{
getSupportFragmentManager().beginTransaction()
.replace(R.id.home_ly,new MessageFragment())
.commit();
return true;
}
case R.id.tab_mypage:{
getSupportFragmentManager().beginTransaction()
.replace(R.id.home_ly,new MypageFragment())
.commit();
return true;
}
}
return false;
}
}
}
public class MypageFragment extends Fragment {
TextView tv_nickname;
TextView tv_userId;
TextView tv_sharedPoint;
LinearLayout ly_mypost;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View mView = inflater.inflate(R.layout.fragment_mypage,null); //📌올릴 frgament layout
SharedPreferences sharedPreferences = this.getActivity().getSharedPreferences("UserInfo",MODE_PRIVATE);
String nickname = sharedPreferences.getString("nickname","");
String id = sharedPreferences.getString("userId","");
int point = sharedPreferences.getInt("point",0);
if(mView != null) {tv_nickname = (TextView)mView.findViewById(R.id.tv_mypage_nickname);
tv_userId = (TextView)mView.findViewById(R.id.tv_mypage_id);
tv_sharedPoint = (TextView)mView.findViewById(R.id.tv_mypage_point);
ly_mypost = (LinearLayout)mView.findViewById(R.id.ly_button_mypost);}
tv_nickname.setText(nickname);
tv_userId.setText(id);
tv_sharedPoint.setText(Integer.toString(point)+"point");
return mView; //📌설정을 모두 마친 fragment 올리기
}
}
fragment 개념을 잘 몰라서,, 그런지 한참 헤맸다.
일단 📌핀 꽂아있는 부분을 자동완성이나 복붙으로 해결하려 하다 보니까 막 이상한 layout 설정해놓거나,, return 에서 아예 새로운 초기화된 layout을 return 해버려서 textview 변경이 반영이 안되거나.. 대환장이였다.
fragment 개념은 개발하면서 차차 익혀가겠지,, 몰라유
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="false" android:state_pressed="false">
<shape>
<solid android:color="@android:color/holo_green_light"/>
<!-- <stroke android:color="@android:color/holo_green_dark"-->
<!-- android:width="1dp"/>-->
<corners android:radius="30dp" />
</shape>
</item>
</selector>
요런식으로 drawable
폴더에다가 만들고 싶은 모양을 추가한다.
android:background="@drawable/bg_custom_button_pay"
android:clickable="true"
android:focusable="true"
android:foreground="?android:attr/selectableItemBackground"
그리고 xml의 textView에서
위에서 만든 drawable 을 background로 설정하고 클릭을 활성화 시키기 위해 아래 세 줄을 추가한다.
MainActivity
혹은 fragment가 올라가는 Activity에 다음 코드를 추가한다.public void replaceFragment(Fragment fragment){
getSupportFragmentManager().beginTransaction().replace(R.id.home_ly,fragment).commit(); //home_ly는 fragment가 올라갈 MainActivity의 layout 아이디
}
이 코드는 입력값으로 들어온 fragment를 home_ly에 띄워주는 코드이다.
2. 각 fragment(혹은 이동할 fragment) 마다 newInstance()
함수 생성하기
public static UserPostFragment newInstance() {
Bundle args = new Bundle();
UserPostFragment fragment = new UserPostFragment();
fragment.setArguments(args);
return fragment;
}
replaceFragment
함수를 쓰려면 input 값으로 새로운 fragment가 들어와야 하기 때문에 newInstance 함수로 새로운 fragment를 만들어서 return 해주도록 한다.
ly_mypost.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((MainActivity)getActivity()).replaceFragment(UserPostFragment.newInstance());
}
});
이런식으로 써주면 된다.