반응형

1.sharedPreferences

-적은양의 원시데이터

-key와 value의 형태

-저장 후 필요할 때 언제든지 가져올 수 있다.

-onPause()에 저장하는 것이 좋다.

 

 

Room

-SQLite에 대한 추상화 레이어를 제공하여 원활한 데이터베이스 액세스를 지원하는 동시에 SQLite를 완벽히 활용한다.

-관련 데이터 캐싱

-사용자가 오프라인 상태인 동안에도 사용자가 여전히 콘텐츠를 탐색할 수 있다.

-기기가 다시 온라인 상태가 되면 사용자가 시작한 콘텐츠 변경사항이 서버에 동기화한다.

 

 

 

 

 

room을 사용한 간단한 어플을 사용 후 직접적으로 개발하는 앱에 넣어볼 계획이다.

반응형
반응형

 

 

데이터베이스 class

package com.gohool.sqiteexample;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import androidx.annotation.Nullable;

import java.util.ArrayList;

//데이터베이스
public class DBHelper extends SQLiteOpenHelper {


    //버전
    private static final int DB_VERSION = 1;
    //db이름
    private static final String DB_NAME = "dw.db";

    //생성자
    public DBHelper(@Nullable Context context) {
        super(context,DB_NAME,null,DB_VERSION);
    }



    @Override
    public void onCreate(SQLiteDatabase db) { //데이터베이스가 생성됐을때 호출/ AUTOINCREMENT: 하나하나씩 값이 올라감 id++
        // 데이터베이스 -> 테이블 -> 컬럼 -> 값
        db.execSQL("CREATE TABLE IF NOT EXISTS ToDoList (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, writeDate TEXT NOT NULL)");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

        onCreate(db);
    }

    //SELECT문 (조회)
    public ArrayList<ToDoItem> getToDoList() { //ArrayList<ToDoItem>데이터형식의 메소드
      ArrayList<ToDoItem> toDoItems = new ArrayList<>();

      SQLiteDatabase db = getReadableDatabase();
      Cursor cursor = db.rawQuery("SELECT * FROM ToDoList ORDER BY writeDate DESC", null); //cursor : 가르키다
      if(cursor.getCount() != 0) { //데이터가 있으면
          while (cursor.moveToNext()){ //다음 데이터가 없을때까지
              int id = cursor.getInt(cursor.getColumnIndex("id")); //cursor가 가르켜 가져옴 / 데이터를 변수에 넣어줄거임
              String title = cursor.getString(cursor.getColumnIndex("title"));
              String content = cursor.getString(cursor.getColumnIndex("content"));
              String writeDate = cursor.getString(cursor.getColumnIndex("writeDate"));


              ToDoItem toDoItem = new ToDoItem();
              toDoItem.setId(id);
              toDoItem.setTitle(title);
              toDoItem.setContent(content);
              toDoItem.setWriteDate(writeDate);
              toDoItems.add(toDoItem); // 리스트에 추가해줌


          }
      }
      cursor.close(); //종료
      return  toDoItems;
    }


    // INSERT문 (삽입) / id값 넣지않음 알아서 입력됨 /
    public void InsertTodo(String _title, String _content, String _writeDate){
        SQLiteDatabase db = getWritableDatabase(); // 쓰기가능
        db.execSQL("INSERT INTO ToDoList (title, content, writeDate) VALUES('" + _title + "', '" + _content + "' , '" + _writeDate + "');"); // sql문
    }

    //UPDATE 문(수정)
    public void UpdateToDo(String _title, String _content, String _writeDate, String _beforeDate){
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("UPDATE ToDoList SET title= '" + _title + "', content = '" + _content + "',  writeDate = '" + _writeDate + "' WHERE writeDate= '" + _beforeDate + "'");
    }

    //DELETE 문(삭제)
    public void DeleteToDo(String _beforeDate){
        SQLiteDatabase db = getWritableDatabase();
        db.execSQL("DELETE FROM ToDoList WHERE writeDate = '" + _beforeDate + "' "); //id만 지우면 됨
    }

}

gradle

dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'com.google.android.material:material:1.2.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

android.defaultConfig.vectorDrawables.useSupportLibrary = true

 

사용할 아이템들 class

 

package com.gohool.sqiteexample;

public class ToDoItem {
    private int id;
    private String title;
    private String content;
    private String writeDate;

    public ToDoItem() {
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getWriteDate() {
        return writeDate;
    }

    public void setWriteDate(String writeDate) {
        this.writeDate = writeDate;
    }
}

manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gohool.sqiteexample">

    <application
        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.AppCompat.Light.NoActionBar"> //테마
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

팝업창 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:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:layout_marginStart="32dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="32dp"
        android:layout_marginBottom="32dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/dialog_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:text="게시글 제목"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <!-- singleLines, maxLines : 초과입력시에도 한줄로 고정 -->

        <TextView
            android:id="@+id/dialog_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:text="게시글 내용"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/edit_title" />

        <EditText
            android:id="@+id/edit_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:ems="10"
            android:inputType="textPersonName"
            android:maxLines="1"
            android:singleLine="true"
            app:layout_constraintStart_toStartOf="@+id/dialog_title"
            app:layout_constraintTop_toBottomOf="@+id/dialog_title" />

        <EditText
            android:id="@+id/edit_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="8dp"
            android:ems="10"
            android:inputType="textPersonName"
            android:maxLines="1"
            android:singleLine="true"
            app:layout_constraintStart_toStartOf="@+id/dialog_content"
            app:layout_constraintTop_toBottomOf="@+id/dialog_content" />

        <Button
            android:id="@+id/dialog_btn"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginEnd="16dp"
            android:layout_marginBottom="8dp"
            android:background="@color/design_default_color_secondary"
            android:text="확인"
            android:textColor="@color/white"
            android:textSize="18sp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

itemlist.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:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:text="제목"
        android:textColor="#070505"
        android:textSize="24dp"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:layout_marginBottom="8dp"
        android:text="내용"
        android:textColor="#070505"
        android:textSize="20dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="@+id/tv_title"
        app:layout_constraintTop_toBottomOf="@+id/tv_title" />

    <TextView
        android:id="@+id/tv_date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:text="작성날짜"
        android:textColor="#070505"
        android:textSize="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/tv_content"
        app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

activitymain. 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/add_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="25dp"
        android:layout_marginBottom="25dp"
        android:clickable="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:srcCompat="@drawable/ic_baseline_add_circle_outline_24" />

        <!--app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"

        tools:listitem="@layout/item_list" : 미리보기
        -->

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/re_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:layout_marginEnd="16dp"
        android:layout_marginBottom="16dp"
        tools:listitem="@layout/item_list"
        app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

CustomAdapter . class

 

package com.gohool.sqiteexample;

import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {

    private ArrayList<ToDoItem> mToDoItems; // m:전역변수
    private Context mcontext;
    private DBHelper mDBhelper;

    public CustomAdapter(ArrayList<ToDoItem> mToDoItems, Context mcontext) {
        this.mToDoItems = mToDoItems;
        this.mcontext = mcontext;
        mDBhelper = new DBHelper(mcontext); //

    }

    @NonNull
    @Override
    public CustomAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View holder = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, parent, false);

        return new ViewHolder(holder);
    }

    @Override
    public void onBindViewHolder(@NonNull CustomAdapter.ViewHolder holder, int position) {

        holder.tv_title.setText(mToDoItems.get(position).getTitle());
        holder.tv_content.setText(mToDoItems.get(position).getContent());
        holder.tv_date.setText(mToDoItems.get(position).getWriteDate());

    }

    @Override
    public int getItemCount() {
        return mToDoItems.size();
    }

    public class ViewHolder extends RecyclerView.ViewHolder {

        //item_list.xml
        private TextView tv_title;
        private TextView tv_content;
        private TextView tv_date;

        public ViewHolder(@NonNull View itemView) {
            super(itemView);

            tv_title = (TextView) itemView.findViewById(R.id.tv_title);
            tv_content = (TextView) itemView.findViewById(R.id.tv_content);
            tv_date = (TextView) itemView.findViewById(R.id.tv_date);


            itemView.setOnClickListener(new View.OnClickListener() { //객체 하나
                @Override
                public void onClick(View v) {
                    int curPos = getAdapterPosition(); //클릭한  위치값 가져오기
                    ToDoItem toDoItem = mToDoItems.get(curPos);


                    String[] strChoiceItems = {"수정하기", "삭제하기"}; //0, 1
                    AlertDialog.Builder builder = new AlertDialog.Builder(mcontext);
                    builder.setTitle("원하는 작업을 선택해주세요");
                    builder.setItems(strChoiceItems, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int position) {
                            if(position == 0) { //수정하기 / 팝업창
                                Dialog dialog = new Dialog(mcontext, android.R.style.Theme_Material_Light_Dialog); //팝업창
                                dialog.setContentView(R.layout.dialog_edit);
                                EditText edit_title = dialog.findViewById(R.id.edit_title);
                                EditText edit_content = dialog.findViewById(R.id.edit_content);
                                Button dialog_btn = dialog.findViewById(R.id.dialog_btn);

                                edit_title.setText(toDoItem.getTitle()); //수정시 내용 가져오기
                                edit_content.setText(toDoItem.getContent());

                                edit_title.setSelection(edit_title.getText().length()); //수정시 커서 마지막에 놓기


                                dialog_btn.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        //db 업데이트
                                        String title = edit_title.getText().toString();
                                        String content = edit_content.getText().toString();
                                        String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); //현재시간 받아오기
                                        String beforeTime = toDoItem.getWriteDate(); //등록되었던 시간

                                        mDBhelper.UpdateToDo(title, content,currentTime,beforeTime); //db에 넣기

                                        //UI 업데이트
                                        toDoItem.setTitle(title);;
                                        toDoItem.setContent(content);
                                        toDoItem.setWriteDate(currentTime);
                                        notifyItemChanged(curPos, toDoItem); //현재 객체, 갱신
                                        dialog.dismiss(); //끔
                                        Toast.makeText(mcontext, "수정이 완료 되었습니다.", Toast.LENGTH_SHORT).show();
                                    }
                                });
                                dialog.show(); //필수

                            } else if(position == 1){ //삭제하기
                                // db 테이블 삭제
                                String beforeTime = toDoItem.getWriteDate(); //등록되었던 시간
                                mDBhelper.DeleteToDo(beforeTime);
                                //UI 삭제
                                mToDoItems.remove(curPos);
                                notifyItemRemoved(curPos);
                                Toast.makeText(mcontext, "삭제가 완료되었습니다.", Toast.LENGTH_SHORT).show();


                            }
                        }
                    });
                    builder.show();
                }
            });
        }
    }
    // 액티비티에서 호출되는 함수이며, 현재 어댑터에 새로운 게시글 아이템을 전달받아 추가하는 목적
    public void addItem(ToDoItem _item){
        mToDoItems.add(0, _item); // 0번째에 추가됨
        notifyItemInserted(0); //새로고침
    }

}

mainactivity , java

package com.gohool.sqiteexample;

import android.app.Dialog;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.floatingactionbutton.FloatingActionButton;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private RecyclerView mrecyclerView;
    private FloatingActionButton madd_btn;
    private ArrayList<ToDoItem> mtoDoItems;
    private DBHelper mdbHelper;
    private CustomAdapter mAdapter;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setInit();

    }

    private void setInit() {
        mdbHelper = new DBHelper(this);
        mrecyclerView = findViewById(R.id.re_view);
        madd_btn = findViewById(R.id.add_btn);
        mtoDoItems = new ArrayList<>();

        loadRecentDB(); //실행시, 이전에 DB가 존재한다면 LOAD해옴


        madd_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Dialog dialog = new Dialog(MainActivity.this, android.R.style.Theme_Material_Light_Dialog); //팝업창
                dialog.setContentView(R.layout.dialog_edit);

                //팝업창 정의
                EditText edit_title = dialog.findViewById(R.id.edit_title);
                EditText edit_content = dialog.findViewById(R.id.edit_content);
                Button dialog_btn = dialog.findViewById(R.id.dialog_btn);
                dialog_btn.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        //데이터베이스에 삽입
                        String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()); //현재시간 받아오기
                        mdbHelper.InsertTodo(edit_title.getText().toString(), edit_content.getText().toString(),currentTime); //db에 넣기

                        //UI에 삽입
                        ToDoItem item = new ToDoItem();
                        item.setTitle(edit_title.getText().toString());
                        item.setContent(edit_content.getText().toString());
                        item.setWriteDate(currentTime);

                        mAdapter.addItem(item); //객체를 넘겨줌(한 세트)
                        mrecyclerView.smoothScrollToPosition(0); //데이터가 올라갈때마다 ListView가 쫒아올라가서 이쁘게 해줌
                        dialog.dismiss();
                        Toast.makeText(MainActivity.this, "정상적으로 추가되었습니다.", Toast.LENGTH_SHORT).show();



                    }
                });
                dialog.show(); //필수

            }
        });

    }

    private void loadRecentDB() {
        //저장된 db가져옴
        mtoDoItems = mdbHelper.getToDoList();
        if(mAdapter == null){
            mAdapter = new CustomAdapter(mtoDoItems, this);
            mrecyclerView.setHasFixedSize(true); //성능 강화
            mrecyclerView.setAdapter(mAdapter);
        }
    }
}









반응형

'개발언어 > JAVA' 카테고리의 다른 글

안드로이드 Room 사용법 (feat.binding)  (0) 2021.01.08
Room이란?  (0) 2021.01.07
안드로이드 상단 분리된 메뉴  (0) 2021.01.01
안드로이드 카메라  (0) 2021.01.01
안드로이드 버튼 애니메이션  (0) 2021.01.01
반응형
dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'com.google.android.material:material:1.2.0-alpha01'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

//implementation 'com.google.android.material:material:1.2.0-alpha01' 추가
// 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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tab_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/const_vp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Monday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Tuesday" />

        <com.google.android.material.tabs.TabItem
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Wednesday" />
    </com.google.android.material.tabs.TabLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/const_vp"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="1.0"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tab_layout"
        app:layout_constraintVertical_bias="0.425">

        <androidx.viewpager.widget.ViewPager
            android:id="@+id/viewPager"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
//fragment 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:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="다원프로젝트 3"
        android:textSize="30sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
// fragment. class



package com.gohool.viewpager;

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;

public class Fragment1 extends Fragment {

    private View view;


    //fragment가 주기적으로 변경됨에 따라 상태저장이 필요함
    public static Fragment1 newInstance(){
        Fragment1 fragment1 = new Fragment1();
        return fragment1;
    }


    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        view = inflater.inflate(R.layout.fragment1,container,false);

        return view;
    }
}
//adapter . class



package com.gohool.viewpager;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentPagerAdapter;

public class PagerAdapter extends FragmentPagerAdapter {
    public PagerAdapter(@NonNull FragmentManager fm) {
        super(fm);
    }


//프래그먼트 교체를 보여주는 처리를 구현한 곳
    @NonNull
    @Override
    public Fragment getItem(int position) {
        switch (position){
            case 0:
                return Fragment1.newInstance(); //화면을 띄어주기 위해 어뎁터에서 인식을 할 수 있게
            case 1:
                return Fragment2.newInstance();
            case 2:
                return Fragment3.newInstance();
            default:
                return null;
        }
    }

    //뷰페이지 개수
    @Override
    public int getCount() {
        return 3;
    }

    //각 뷰페이지의 이름
    @Nullable
    @Override
    public CharSequence getPageTitle(int position) {
        switch (position){
            case 0:
                return "Monday";
            case 1:
                return "tuesday";
            case 2:
                return "friday";
            default:
                return null;
        }
    }
}
// main activity . java



package com.gohool.viewpager;

import android.os.Bundle;

import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentPagerAdapter;
import androidx.viewpager.widget.ViewPager;

import com.google.android.material.tabs.TabLayout;

public class MainActivity extends AppCompatActivity {

    private FragmentPagerAdapter fragmentPagerAdapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);



        //뷰페이저 세팅
        ViewPager viewPager = findViewById(R.id.viewPager);
        PagerAdapter fragmentPagerAdapter = new PagerAdapter(getSupportFragmentManager());

        TabLayout tabLayout = findViewById(R.id.tab_layout);
        viewPager.setAdapter(fragmentPagerAdapter); //연동
        tabLayout.setupWithViewPager(viewPager);
    }
}
반응형
반응형
dependencies {

    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    implementation 'gun0912.ted:tedpermission:2.0.0'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}

특정 상황에서 권한이 필요하기 때문에, tedpermission을 쓰면 쉽게 권한 창을 만들 수 있다.

 

//res. xml. file_paths

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <external-path
        name="my_images"
        path="Android/data/com.com.gohool.cameraexample/files/Pictures"/>

</paths>
//manifest


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.gohool.cameraexample">

    <!--카메라 권한 -->
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>


    <application
        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.CameraExample">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>


        <!--추가 -->
        <provider
            android:authorities="com.gohool.cameraexample"
            android:name="androidx.core.content.FileProvider"
            android:exported="false"
            android:grantUriPermissions="true">

            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/file_paths"/>

        </provider>
    </application>

</manifest>
//activity main . xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
    android:orientation="vertical"
    tools:context=".MainActivity">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

        <ImageView
            android:id="@+id/result"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

    </LinearLayout>

    <LinearLayout
        android:gravity="center"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <Button
            android:id="@+id/btnCapture"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="촬영"/>

    </LinearLayout>



</LinearLayout>
// activity main .java


package com.gohool.cameraexample;

import android.Manifest;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;

import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;

import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

public class MainActivity extends AppCompatActivity {

    private static final int REQUEST_IMAGE_CAPTURE = 672;
    private String imageFilePath;
    private Uri photoUri;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //권한 체크
        TedPermission.with(getApplicationContext())
                .setPermissionListener(permissionListener)
                .setRationaleMessage("카메라 권한이 필요합니다.") //카메라권한 열때 사용자에게 보여주는 메세지
                .setDeniedMessage("카메라 권한을 거부하셨습니다.")
                .setPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE,Manifest.permission.CAMERA) //manifest에 추가한 권한
                .check();

        findViewById(R.id.btnCapture).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
                if(intent.resolveActivity(getPackageManager()) != null){
                    File photoFile = null; //파일쓰기시에는 항상 try catch문 필요
                    try {
                        photoFile = createImageFile();
                    }catch (IOException e){

                    }
                    if(photoFile != null){
                        photoUri = FileProvider.getUriForFile(getApplicationContext(), getPackageName(),photoFile);
                        intent.putExtra(MediaStore.EXTRA_OUTPUT,photoUri);
                        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE);
                    }
                }
            }
        });

    }

    private File createImageFile() throws IOException{ //년원일분초 시간단위로 생성 후 저장
        String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
        String imageFileName = "TEST_" + timeStamp + "_";
        File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
        File image = File.createTempFile(
                imageFileName,
                ".jpg",
                storageDir
        );

        imageFilePath = image.getAbsolutePath();
        return image;

    }

    //forresult
    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == RESULT_OK) {
            Bitmap bitmap = BitmapFactory.decodeFile(imageFilePath);
            ExifInterface exifInterface = null;

            try {
                exifInterface = new ExifInterface(imageFilePath);
            } catch (IOException e) {
                e.printStackTrace();
            }

            int exifOrientation;
            int exifDegree;

            if (exifInterface != null) {
                exifOrientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
                exifDegree = exifOrientationToDegree(exifOrientation);

            } else {
                exifDegree = 0;
            }
            ((ImageView) findViewById(R.id.result)).setImageBitmap(rotate(bitmap, exifDegree));
        }


    }
    private Bitmap rotate(Bitmap bitmap, float degree){
        Matrix matrix = new Matrix();
        matrix.postRotate(degree);
        return Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
    }


    private int exifOrientationToDegree(int exifOrientation) { //촬영중 화면 돌아갈때
        if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_90) {
            return 90;
        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_180) {
            return 180;
        } else if (exifOrientation == ExifInterface.ORIENTATION_ROTATE_270) {
            return 270;
        }
        return 0;
    }

    PermissionListener permissionListener = new PermissionListener() {
        @Override
        public void onPermissionGranted() { //권한 허용에대한 액션
            Toast.makeText(getApplicationContext(), "권한이 허용됨", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(getApplicationContext(), "권한이 거부됨", Toast.LENGTH_SHORT).show();
        }
    };
}
반응형
반응형

버튼, 이미지를 위한 selecter.xml 만든다

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape>
            <solid android:color="#F06292" />
            <corners android:radius="10dp"/>
        </shape>
    </item>
    <item android:state_pressed="false">
        <shape>
            <solid android:color="#64B5F6" />
            <corners android:radius="10dp"/>
        </shape>
    </item>



</selector>

버튼이 눌러진 경우와 버튼이 떼진 경우의 background 칼러를 변경해주기 위함

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@mipmap/ic_launcher_round">

    </item>
    <item android:state_pressed="false" android:drawable="@mipmap/ic_launcher">

    </item>



</selector>

이미지가 눌러진 경우와 이미지를 버튼이 떼진 경우의 background 칼러를 변경해주기 위함

<?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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/selector_btn"
        android:text="다원프로젝트"
        android:textColor="#ffffff"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button2"
        app:layout_constraintVertical_bias="0.304" />

    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="188dp"
        android:background="@drawable/selector_image"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
반응형
반응형

 

package com.gohool.twobackbutton;

import android.os.Bundle;
import android.widget.Toast;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private long backBtnTime = 0; //int보다 긴 자료형 형태

    @Override
    public void onBackPressed() {
        long curTime = System.currentTimeMillis(); //현재시간
        long gapTime = curTime - backBtnTime;

        if(0 <= gapTime && 2000 >= gapTime){ //2초안에 한번 더 누르게 되면 종료
            super.onBackPressed();
        }else {
            backBtnTime = curTime;
            Toast.makeText(this, "한번 더 누르면 종료 됩니다.", Toast.LENGTH_SHORT).show();
        }


    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);



    }
}
반응형

'개발언어 > JAVA' 카테고리의 다른 글

안드로이드 카메라  (0) 2021.01.01
안드로이드 버튼 애니메이션  (0) 2021.01.01
안드로이드 로딩화면  (0) 2021.01.01
안드로이드 클릭 메뉴(spinner)  (0) 2020.12.31
안드로이드 popup창  (0) 2020.12.31
반응형

이번에는 github 라이브러리를 이용한 로딩화면 만들어볼것이다.

 

구글에 android loading animation github라고 검색 후 

여기

 

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:gravity="center"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.github.ybq.android.spinkit.SpinKitView
        android:id="@+id/spin_kit"
        style="@style/SpinKitView.Large.DoubleBounce"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        app:SpinKit_Color="@color/black" />


</LinearLayout>

 

그대로 받아서 넣고, 실행 해보았다.

반응형

'개발언어 > JAVA' 카테고리의 다른 글

안드로이드 버튼 애니메이션  (0) 2021.01.01
안드로이드 뒤로가기 두번 누르면 종료  (0) 2021.01.01
안드로이드 클릭 메뉴(spinner)  (0) 2020.12.31
안드로이드 popup창  (0) 2020.12.31
안드로이드 ListView  (0) 2020.12.31
반응형
package com.gohool.dropdownmenu;

import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Spinner;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {

    private Spinner spinner;
    private TextView result;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);


        spinner = (Spinner) findViewById(R.id.spinner); //드롭다운메뉴
        result = (TextView) findViewById(R.id.result);

        spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            @Override
            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
                result.setText(parent.getItemAtPosition(position).toString()); //포지션에 있는 값을 가져와야하니 string으로 변환
            }

            @Override
            public void onNothingSelected(AdapterView<?> parent) {

            }
        });


    }
}

array.xml이라는 xml파일을 만들어준다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string-array name="text">
        <item>다원프로젝트</item>
        <item>눈</item>
        <item>코</item>
        <item>발</item>
        <item>다리</item>

    </string-array>
</resources>

entries를 사용해 array에 있는 name="text"를 가져와 넣어줄것이다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity">

    <Spinner
        android:id="@+id/spinner"

        android:layout_width="150dp"
        android:layout_height="40dp"
        android:entries="@array/text">
    </Spinner>

    <TextView
        android:id="@+id/result"
        android:text="드롭다운결과"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>
반응형

'개발언어 > JAVA' 카테고리의 다른 글

안드로이드 뒤로가기 두번 누르면 종료  (0) 2021.01.01
안드로이드 로딩화면  (0) 2021.01.01
안드로이드 popup창  (0) 2020.12.31
안드로이드 ListView  (0) 2020.12.31
클래스와 인스턴스 그리고 객체  (0) 2020.12.31

+ Recent posts