MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package com.example.boostcoursepractice;
 
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
 
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
import com.google.gson.Gson;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
 
public class MainActivity extends AppCompatActivity {
 
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textView = (TextView) findViewById(R.id.textView);
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendRequest();
            }
        });
 
        if(AppHelper.requestQueue == null) AppHelper.requestQueue = Volley.newRequestQueue(getApplicationContext());
 
    }
 
    public void sendRequest()
    {
        //String url = "http://www.google.co.kr";
        String url = "http://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=430156241533f1d058c603178cc3ca0e&targetDt=20120101";
        StringRequest request = new StringRequest(
                Request.Method.GET,
                url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        //println("응답 -> " + response);
 
                        processResponse(response) ;
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        println("에러 -> " + error.getMessage());
                    }
                }
        ){
            @Override
            protected Map<StringString> getParams() throws AuthFailureError {////Post방식으로 파라미터를 전달해주고싶을 때
                Map<StringString> params = new HashMap<StringString>() ;
 
                return params ;
            }
        };
 
        request.setShouldCache(false);
        AppHelper.requestQueue.add(request);
        println("응답 보냄");
    }
 
    public void processResponse(String response)
    {
        Gson gson = new Gson();
        MovieList movieList = gson.fromJson(response, MovieList.class) ;
 
        if(movieList != null)
        {
            int cnt = movieList.boxOfficeResult.dailyBoxOfficeList.size();
            for(int i=0; i<cnt ; i++)
            {
                println(movieList.boxOfficeResult.dailyBoxOfficeList.get(i).movieNm);
            }
        }
    }
 
 
    public void println(String data) {
        textView.append(data + "\n");
    }
 
}
cs

 

AppHelper

...더보기
1
2
3
4
5
6
7
8
9
10
package com.example.boostcoursepractice;
 
import com.android.volley.RequestQueue;
 
public class AppHelper
{
    public static RequestQueue requestQueue;
 
}
 
cs

 

MovieList

...더보기
1
2
3
4
5
6
package com.example.boostcoursepractice;
 
public class MovieList {
    MovieListResult boxOfficeResult ;
}
 
cs

 

MovieListResutlt

...더보기
1
2
3
4
5
6
7
8
9
10
11
package com.example.boostcoursepractice;
 
import java.util.ArrayList;
 
public class MovieListResult {
    String boxofficeType ;
    String showRange;
 
    ArrayList<Movie> dailyBoxOfficeList = new ArrayList<Movie>();
}
 
cs

 

Movie

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.boostcoursepractice;
 
public class Movie {
    String rnum;
    String rank;
    String rankInten;
    String rankOldAndNew;
    String movieCd;
    String movieNm;
    String openD;
    String salesAmt;
    String salesShare;
    String salesInten;
    String salesChange;
    String salesAcc;
    String audiCnt;
    String audiInten;
    String audiChange;
    String audiAcc;
    String scrnCnt;
    String showCnt;
}
 
cs

 

activity_main_xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="요청하기" />
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
 
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18dp" />
        </LinearLayout>
    </ScrollView>
 
</LinearLayout>
 
cs

 

우선 JSON 형식을 자바의 객체로 만들기 위해서는 GSON이라는 외부라이브러리를 써야 한다. 그러기 위하여 gradle에 implementation 'com.google.code.gson:gson:2.8.2' 을 추가해야만 한다. 이렇게 하고 우선 JSON형식에 맞게 클래스를 만들어 주어야한다. 여기서는 영화진흥위원회의 예제 JSON을 썼고 그에 맞게 MovieList, MovieListResult, Movie 이렇게 3개의 클래스를 만들어 주었다. 마지막으로 아래의 코드처럼

 

Gson gson = new Gson();

        MovieList movieList = gson.fromJson(response, MovieList.class) ;

 

이렇게 해주면 우리가 만든 클래스에 gson을 이용하여 json데이터를 객체로 만들어 준다. 그것을 이용하면 된다.

 

 

 

결과화면

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.example.boostcoursepractice;
 
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
 
import com.android.volley.AuthFailureError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.StringRequest;
import com.android.volley.toolbox.Volley;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
 
public class MainActivity extends AppCompatActivity {
 
    TextView textView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textView = (TextView) findViewById(R.id.textView);
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                sendRequest();
            }
        });
 
        if(AppHelper.requestQueue == null) AppHelper.requestQueue = Volley.newRequestQueue(getApplicationContext());
 
    }
 
    public void sendRequest()
    {
        String url = "http://www.google.co.kr";
        StringRequest request = new StringRequest(
                Request.Method.GET,
                url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        println("응답 -> " + response);
                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        println("에러 -> " + error.getMessage());
                    }
                }
        ){
            @Override
            protected Map<StringString> getParams() throws AuthFailureError {////Post방식으로 파라미터를 전달해주고싶을 때
                 Map<StringString> params = new HashMap<StringString>() ;
 
                return params ;
            }
        };
 
        request.setShouldCache(false);
        AppHelper.requestQueue.add(request);
        println("응답 보냄");
    }
 
    public void println(String data) {
        textView.append(data + "\n");
    }
 
}
 
 
 
 
 
cs

AppHelper

...더보기
1
2
3
4
5
6
7
8
9
10
11
package com.example.boostcoursepractice;
 
import com.android.volley.RequestQueue;
 
public class AppHelper
{
    public static RequestQueue requestQueue;
 
    
}
 
cs

 

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?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">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="요청하기" />
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/holo_orange_light">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
 
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:textSize="18dp" />
        </LinearLayout>
    </ScrollView>
 
</LinearLayout>
 
cs

 

우선 Volley는 네트워크연결을 할 때 무조건 스레드를 통해서 해야되고 스레드 안에서 UI를 접근하려면 핸들러를 이용해야 하는 데 이거 모든 과정을 간단히 하기 위한 외부라이브러리이다.(gradel에 implementation

'com.android.volley:volley:1.1.0' 추가) 사용법은 위의 코드와 같고 개념적인 그림은 아래의 그림과 같다.

 

여기서 중요한 것은 Volley를 이용하면 메인스레드의 리퀘스트큐에 리케스트를 보내는 것이고 그 리퀘스트들은 다시 스레드로 작동한다. 이 때 각 리퀘스트들은 아래처럼 

 

new Response.Listener<String>() {

                    @Override

                    public void onResponse(String response) {

                        println("응답 -> " + response);

                    }

                },

                new Response.ErrorListener() {

                    @Override

                    public void onErrorResponse(VolleyError error) {

                        println("에러 -> " + error.getMessage());

                    }

                }

 

리스너를 등록하여 사용하며 실제적으로는 onResponse가 핸들러를 이용하여 동작하게 되는 것이다(UI접근 가능)

 

 

 

결과화면

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package com.example.boostcoursepractice;
 
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
 
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.HttpURLConnection;
import java.net.Socket;
import java.net.URL;
 
public class MainActivity extends AppCompatActivity {
 
    EditText editText;
    TextView textView;
    Handler handler = new Handler() ;
    String urlStr ;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        editText = (EditText) findViewById(R.id.editText);
        textView = (TextView) findViewById(R.id.textView);
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                urlStr = editText.getText().toString();
                RequestThread thread = new RequestThread();
                thread.start();
            }
        });
 
 
    }
 
    class RequestThread extends Thread {
        @Override
        public void run() {
            super.run();
 
            try {
                URL url = new URL(urlStr);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                if (conn != null) {
                    conn.setConnectTimeout(10000);
                    conn.setRequestMethod("GET");
                    conn.setDoInput(true);
                    conn.setDoOutput(true);
 
                    int resCode = conn.getResponseCode();
 
                    BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                    String line = null ;
 
                    while(true)
                    {
                        line = reader.readLine() ;
                        if(line == nullbreak ;
 
                        println(line);
                    }
                }
 
            } catch (Exception e) {
                e.printStackTrace();
            }
 
        }
    }
 
    public void println(final String data) {
 
        handler.post(new Runnable() {
 
            @Override
            public void run() {
                textView.append(data + "\n");
            }
        });
    }
}
 
 
 
 
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?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">
 
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
 
        <Button
            android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="요청하기" />
 
        <EditText
            android:id="@+id/editText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:ems="10"
            android:inputType="textPersonName"
            android:text="http://m.naver.com" />
    </LinearLayout>
 
    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorAccent">
 
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">
 
            <TextView
                android:id="@+id/textView"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />
        </LinearLayout>
    </ScrollView>
 
</LinearLayout>
 
cs

 

웹은 HTTP를 이용해서 통신을 하는 것이다. 위의 코드와 같이 하면 되고 중요한 것은 안드로이드에서는 웹을 요청할 때 스레드를 이용해서 요청한다는 것이다.

 

 

 

 

결과화면

 

Server

 

ChatService

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.example.myserver;
 
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
 
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class ChatService extends Service {
    public ChatService() {
 
    }
 
    @Override
    public void onCreate() {
        super.onCreate();
 
        new ServerThread().start();
    }
 
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return super.onStartCommand(intent, flags, startId);
    }
 
    @Override
    public void onDestroy() {
        super.onDestroy();
    }
 
    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }
 
    class ServerThread extends Thread {
        @Override
        public void run() {
            //super.run();
 
            int port = 5001;
 
            try {
                ServerSocket server = new ServerSocket(port);
                Log.d("ServerThread""서버가 실행됨");
 
                while (true) {
                    Socket socket = server.accept();
 
                    ObjectInputStream instream = new ObjectInputStream(socket.getInputStream());
                    Object input = instream.readObject();
                    Log.d("ServerThread""input : " + input);
 
                    ObjectOutputStream outstream = new ObjectOutputStream(socket.getOutputStream());
                    outstream.writeObject(input + "from server.");
                    outstream.flush();
                    Log.d("ServerThread""output 보냄" + input);
 
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
 
cs

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
package com.example.myserver;
 
import androidx.appcompat.app.AppCompatActivity;
 
import android.content.Intent;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.View;
import android.widget.Button;
 
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //new ServerThread().start();
 
                Intent intent = new Intent(getApplicationContext(), ChatService.class);
                startService(intent);
            }
        });
 
    }
 
    /*class ServerThread extends Thread {
        @Override
        public void run() {
            //super.run();
 
            int port = 5001;
 
            try {
                ServerSocket server = new ServerSocket(port);
                Log.d("ServerThread", "서버가 실행됨");
 
                while (true) {
                    Socket socket = server.accept();
 
                    ObjectInputStream instream = new ObjectInputStream(socket.getInputStream());
                    Object input = instream.readObject();
                    Log.d("ServerThread", "input : " + input);
 
                    ObjectOutputStream outstream = new ObjectOutputStream(socket.getOutputStream());
                    outstream.writeObject(input + "from server.");
                    outstream.flush();
                    Log.d("ServerThread", "output 보냄" + input);
 
                    socket.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
 
 
        }
    }*/
}
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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:text=" 서버 시작"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
 
</androidx.constraintlayout.widget.ConstraintLayout>
cs

 

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

Client

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package com.example.boostcoursepractice;
 
import android.os.AsyncTask;
import android.os.Bundle;
 
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
 
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
 
public class MainActivity extends AppCompatActivity {
 
    Button button;
    TextView textView ;
    Handler handler ;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        handler = new Handler() ;
        textView = (TextView) findViewById(R.id.textView) ;
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                new ClientThread().start();
            }
        });
    }
 
    class ClientThread extends Thread {
 
        @Override
        public void run() {
            //super.run();
            String host = "localhost";
            int port = 5001;
 
            try {
                Socket socket = new Socket(host, port);
 
                ObjectOutputStream outstream = new ObjectOutputStream(socket.getOutputStream());
                outstream.writeObject("안녕!");
                outstream.flush();
                Log.d("ClientThread""서버로 보냄.");
 
                ObjectInputStream instream  = new ObjectInputStream(socket.getInputStream());
                final Object input = instream.readObject() ;
                Log.d("ClientThread""받은 데이터 : " + input);
 
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        textView.setText("받은 데이터 : " + input);
                    }
                }) ;
 
                socket.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
 
        }
    }
 
}
 
 
 
 
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?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">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="받은 데이터 :"
        android:textSize="24dp" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="클라이언트 시작" />
</LinearLayout>
 
cs

 

소켓프로그래밍은 우선 클라이언트가 요청하고 그 요청에 응답하여 서버가 응답을 보내면서 이루어 진다.

서버는 ip를 가지고 있고 포트번호를 가지고 있다. 이에 대해 클라이언트가 서버의 ip와 포트번호를 이용하여 요청을 보내면서 네트워크 통신은 이루어진다. 

 

위 첨부해놓은 코드처럼 보면 클라이언트는 보내기 -> 받기 순이고 서버는 받기->보내기 순이다. 

 

이 예제에서는 또한 서버쪽에서 어플리케이션이 종료 되어도 계속 서버의 기능을 할 수 있도록 서비스를 이용해 구현해 놓았다. 

 

 

 

서버 결과화면

 

클라이언트 결과화면

MainActivity

...더보기
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
package com.example.boostcoursepractice;
 
import android.os.AsyncTask;
import android.os.Bundle;
 
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
 
import androidx.annotation.NonNull;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.Button;
import android.widget.FrameLayout;
import android.widget.TextView;
import android.widget.Toast;
 
public class MainActivity extends AppCompatActivity {
 
    TextView textView;
    ValueHandler valueHandler;
    Handler handler2;
 
    int value = 0;
    boolean running = true;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        valueHandler = new ValueHandler();
 
        handler2 = new Handler();
 
        textView = (TextView) findViewById(R.id.textView);
 
        Button button = (Button) findViewById(R.id.button);
 
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //new BackgroundThread().start();
 
                new Thread(new Runnable() {
 
                    int threadValue = 0;
                    //int value = 0;
 
                    @Override
                    public void run() {
                        running = true;
                        while (running) {
                            //value += 1;
                            threadValue += 1;
                            handler2.post(new Runnable() {
                                @Override
                                public void run() {
                                    value += 1;
                                    textView.setText("현재 값" + value);
                                }
                            });
 
                            try {
                                Thread.sleep(1);
                            } catch (Exception e) {
                            }
                        }
 
                        Log.d("JJH""threadValue 값 : " + threadValue);
                        //Log.d("JJH", "value 값 : " + value);
                    }
                }).start();
            }
        });
 
        Button button2 = (Button) findViewById(R.id.button2);
        button2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //new BackgroundThread().start();
                new AsyncBackground().execute();
            }
        });
 
        Button button3 = (Button) findViewById(R.id.button3);
        button3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                running = false;
            }
        });
 
        Button button4 = (Button) findViewById(R.id.button4);
        button4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //textView.setText("현재 값 : " + value);
            }
        });
    }
 
    class BackgroundThread extends Thread {
 
        int threadValue = 0;
        //int value = 0;
 
        public void run() {
            running = true;
            while (running) {
                //value += 1;
                threadValue += 1;
                Message message = valueHandler.obtainMessage();
                //Bundle bundle = new Bundle();
                //bundle.putInt("value", value);
                //message.setData(bundle);
                valueHandler.sendMessage(message);
                try {
                    Thread.sleep(1);
                } catch (Exception e) {
                }
            }
 
            Log.d("JJH""threadValue 값 : " + threadValue);
            //Log.d("JJH", "value 값 : " + value);
        }
 
 
    }
 
    class ValueHandler extends Handler {
 
        int sum = 0;
 
        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);
 
            value += 1;
            //Bundle bundle = msg.getData();
            //int value = bundle.getInt("value");
 
            textView.setText("현재 값 : " + value);
            //textView.setText("메세지큐의 마지막 값 : " + value);
        }
    }
 
    class AsyncBackground extends AsyncTask<String, Integer, Integer> {
        int threadValue = 0;
 
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            running = true;
        }
 
        @Override
        protected Integer doInBackground(String... strings) {
            while (running) {
                threadValue += 1;
                publishProgress();
                try {
                    Thread.sleep(1);
                } catch (Exception e) {
                }
 
 
            }
            return null;
        }
 
        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
 
            value += 1;
            textView.setText("현재 값 : " + value);
        }
 
        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
 
            Log.d("JJH""threadValue 값 : " + threadValue);
        }
    }
}
 
 
 
 
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?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">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:text="진행값"
        android:textSize="30dp" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="스레드 시작1" />
 
    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="스레드 시작2" />
 
    <Button
        android:id="@+id/button3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="중지" />
 
    <Button
        android:id="@+id/button4"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="진행값 확인" />
</LinearLayout>
 
cs

 

스레드는 우선 따로 클래스를 만들고 Thread를 상속 받아 그안에 run메서드를 오버라이드 하고 완성시킨 다음 그것을 .start() 시키면 실행된다. 우선 이런 스래드를 여러개 만들고 공유 자원을 동시에 사용하면 자바에서와 같이 동기화가 안된다. 여기서는 전역변수 value의 값을 올려주면서 확인 실험 해보았다.

또한 스레드 클래스 내부에서 UI접근이 아예 되지를 않는다. 이 UI접근불가문제를 해결하기 위해서 핸들러를 사용한다. 핸들러는 메인메서드에서 동작하고 받은 메세지를 큐처럼 쌓아놓고 해결하기 때문에 동기화가 된다.(여러 핸들러를 생성해 놓아도 하나의 큐에서 동작하는 것처럼 작동한다. 동기화 걱정 ㄴㄴ) 

핸드러를 쓰는 방법 첫번째(button2에 구현)로는 아래와 같이

 

class BackgroundThread extends Thread {

 

        int threadValue = 0;

        //int value = 0;

 

        public void run() {

            running = true;

            while (running) {

                //value += 1;

                threadValue += 1;

                Message message = valueHandler.obtainMessage();

                //Bundle bundle = new Bundle();

                //bundle.putInt("value", value);

                //message.setData(bundle);

                valueHandler.sendMessage(message);

                try {

                    Thread.sleep(1);

                } catch (Exception e) {

                }

            }

 

            Log.d("JJH","threadValue 값 : " + threadValue );

            //Log.d("JJH", "value 값 : " + value);

        }

 

 

    }

 

 

class ValueHandler extends Handler {

 

        int sum = 0;

 

        @Override

        public void handleMessage(@NonNull Message msg) {

            super.handleMessage(msg);

 

            value+=1 ;

            //Bundle bundle = msg.getData();

            //int value = bundle.getInt("value");

 

            textView.setText("현재 값 : " + value);

            //textView.setText("메세지큐의 마지막 값 : " + value);

        }

    }

 

주석 처리 되어있지만 메세지를 생성하여 그 안에 데이터가 들어있는 번들객체를 넣어 핸들러에 메세지를 전달해주면 받은 핸들러는 큐에 넣어 동작한다. 

 

두번째 방법(Button3 주석으로 구현)으로는 아래와 같이

 

new Thread(new Runnable() {

 

                    int threadValue = 0;

                    //int value = 0;

 

                    @Override

                    public void run() {

                        running = true;

                        while (running) {

                            //value += 1;

                            threadValue += 1;

                            handler2.post(new Runnable() {

                                @Override

                                public void run() {

                                    value+=1;

                                    textView.setText("현재 값" + value);

                                }

                            });

 

                            try {

                                Thread.sleep(1);

                            } catch (Exception e) {

                            }

                        }

 

                        Log.d("JJH","threadValue 값 : " + threadValue);

                        //Log.d("JJH", "value 값 : " + value);

                    }

                }).start();

 

바로 스래드를 생성하여 생성자안에 Runnuable클래스를 넣어주고 그안에 run을 오버라이드 해주고 또 거기서 생성된 오버라이드 하지 않은 일반 핸들러에 .post()라는 메서드를 호출하면서 매개변수로 Runnuable를 넣고 run메서드를 오버라이드 해주면 더 간단하게 구현할 수 있다.

 

어쨌든 이 모든 방식이 메인 메서드 안에 핸들러를 통해서 UI객체 접근이 이루어진다는 것을 잊지 말자.

 

 

 

 

 

마지막으로 AsyncTask를 알아보자

우선 클래스 구성은 아래와 같다.

 

 

class AsyncBackground extends AsyncTask<String, Integer, Integer> {

        int threadValue = 0;

 

        @Override

        protected void onPreExecute() {

            super.onPreExecute();

            running = true;

        }

 

        @Override

        protected Integer doInBackground(String... strings) {

            while (running) {

                threadValue += 1;

                publishProgress();

                try {

                    Thread.sleep(1);

                } catch (Exception e) {

                }

 

 

            }

            return null;

        }

 

        @Override

        protected void onProgressUpdate(Integer... values) {

            super.onProgressUpdate(values);

 

            value += 1;

            textView.setText("현재 값 : " + value);

        }

 

        @Override

        protected void onPostExecute(Integer integer) {

            super.onPostExecute(integer);

 

            Log.d("JJH""threadValue 값 : " + threadValue);

        }

    }

 

위 처럼 첫 실행시 onPreExecute()가 실행되며 doInBackground에는 일반전인 스레드 동작 코드를 넣어주면 되고 그 중간에  publishProgress()를 호출하면 그때마다 onProgressUpdate가 호출되어지는데 이 함수가 바로 핸들러의 역할을 하여 UI의 접근을 가능하게 해준다. 이때도 역시 큐처럼 동작하여 동기화에 신경쓰지 않아도 된다. 마지막에는 onPostExecute가 실행되며 스레드가 끝나게 된다. 

 

 

 

결과화면

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package com.example.boostcoursepractice;
 
import android.os.Bundle;
 
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
 
import android.view.View;
 
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
 
import android.view.MenuItem;
 
import com.google.android.material.navigation.NavigationView;
 
import androidx.drawerlayout.widget.DrawerLayout;
 
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.Fragment;
 
import android.view.Menu;
import android.widget.FrameLayout;
import android.widget.Toast;
 
public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener, FragmentCallback {
 
    Fragment fragment1 ;
    Fragment fragment2;
    Fragment fragment3 ;
    Toolbar toolbar ;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
 
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        NavigationView navigationView = findViewById(R.id.nav_view);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.addDrawerListener(toggle);
        toggle.syncState();
        navigationView.setNavigationItemSelectedListener(this);
 
        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3() ;
 
        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();
    }
 
    @Override
    public void onFragmentSelected(int position, Bundle bundle) {
        Fragment curFragment = null ;
 
        if(position == 0)
        {
            curFragment = fragment1 ;
            toolbar.setTitle("첫번째 화면");
        }
 
        else if(position == 1)
        {
            curFragment = fragment2 ;
            toolbar.setTitle("두번째 화면");
        }
 
        else if(position == 2)
        {
            curFragment = fragment3 ;
            toolbar.setTitle("세번째 화면");
        }
 
        getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();
    }
 
    @Override
    public void onBackPressed() {
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
 
        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }
 
        return super.onOptionsItemSelected(item);
    }
 
    @SuppressWarnings("StatementWithEmptyBody")
    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();
 
        if (id == R.id.nav_0) {
            Toast.makeText(this"첫번째 화면 선택됨", Toast.LENGTH_SHORT).show();
            onFragmentSelected(0null);
        } else if (id == R.id.nav_1) {
            Toast.makeText(this"두번째 화면 선택됨", Toast.LENGTH_SHORT).show();
            onFragmentSelected(1null);
        } else if (id == R.id.nav_2) {
            Toast.makeText(this"세번째 화면 선택됨", Toast.LENGTH_SHORT).show();
            onFragmentSelected(2null);
        }
        DrawerLayout drawer = findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }
}
 
 
 
 
cs

 

FragmentCallBack

...더보기
1
2
3
4
5
6
7
8
9
10
package com.example.boostcoursepractice;
 
import android.os.Bundle;
 
public interface FragmentCallback {
 
    public void onFragmentSelected(int position, Bundle bundle) ;
 
}
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">
 
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        tools:context=".MainActivity">
 
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/AppTheme.AppBarOverlay">
 
            <androidx.appcompat.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                android:background="?attr/colorPrimary"
                app:popupTheme="@style/AppTheme.PopupOverlay" />
 
        </com.google.android.material.appbar.AppBarLayout>
 
        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior">
 
 
        </FrameLayout>
 
 
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
 
    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />
 
</androidx.drawerlayout.widget.DrawerLayout>
 
cs

 

nav_header_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?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"
    android:layout_width="match_parent"
    android:layout_height="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">
 
    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/nav_header_desc"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        app:srcCompat="@mipmap/ic_launcher_round" />
 
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="@string/nav_header_title"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/nav_header_subtitle" />
 
</LinearLayout>
 
cs

 

menu/activity_main_drawer.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="navigation_view">
 
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_0"
            android:icon="@drawable/ic_menu_camera"
            android:title="첫번째 화면" />
        <item
            android:id="@+id/nav_1"
            android:icon="@drawable/ic_menu_gallery"
            android:title="두번째 화면" />
        <item
            android:id="@+id/nav_2"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="세번째 화면" />
        <item
            android:id="@+id/nav_3"
            android:icon="@drawable/ic_menu_manage"
            android:title="네번째 화면" />
    </group>
 
    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/nav_share"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/menu_share" />
            <item
                android:id="@+id/nav_send"
                android:icon="@drawable/ic_menu_send"
                android:title="@string/menu_send" />
        </menu>
    </item>
 
</menu>
 
cs

 

Fragment1

Fragment2

Fragemet3

fragment1.xml

fragment2.xml

fragment3.xml

 

이런 것들은 전글에 있던 것과 아예  같다.

 

 

 

 

우선 바로가기 메뉴를 만들기 위해서는 프로젝트를 생성할 때 Navigation Drawer Activity로 애초에 만드는 것이 편하다. 그러면 여러가지가 생길 텐데 위 예제처럼 app_bar_main.xml, content_main.xml을 activity_main.xml에 합쳐서 한개의 파일로 만드는 것이 편하다. 이제는 저렇게 만들어져 있는 것을 구조를 파악하고 수정하는 것이 중요하다. 위 예제에서는 바로가기 메뉴에 첫번째 두번째 세번째 화면을 클릭하면 해당 프래그먼트를 띄우도록하는 것이다. 

 

 public boolean onNavigationItemSelected(MenuItem item) {

        // Handle navigation view item clicks here.

        int id = item.getItemId();

 

        if (id == R.id.nav_0) {

            Toast.makeText(this"첫번째 화면 선택됨", Toast.LENGTH_SHORT).show();

            onFragmentSelected(0null);

        } else if (id == R.id.nav_1) {

            Toast.makeText(this"두번째 화면 선택됨", Toast.LENGTH_SHORT).show();

            onFragmentSelected(1null);

        } else if (id == R.id.nav_2) {

            Toast.makeText(this"세번째 화면 선택됨", Toast.LENGTH_SHORT).show();

            onFragmentSelected(2null);

        }

        DrawerLayout drawer = findViewById(R.id.drawer_layout);

        drawer.closeDrawer(GravityCompat.START);

        return true;

    }

 

위 처럼 onNavigationItemSelected(MenuItem item)메서드를 오버라이드 해주면 바로가기 메뉴의 어떤 메뉴버튼이 눌렸는지 콜백함수가 작동한다. 버튼이 눌릴 때마다 프래그먼트를 바꿔줘야 하는데 이 때 액티비티의 프래그먼트 매니저를 이용해야 함으로 

 

package com.example.boostcoursepractice;

 

import android.os.Bundle;

 

public interface FragmentCallback {

 

    public void onFragmentSelected(int position, Bundle bundle) ;

 

}

 

위와 같은 FragmentCallback이라는 인터페이스를 만들고 이를 메인 액티비티에서 인터페이스를 implement해준다. 그리고 인터페이스에서 선언된 함수를 

 

@Override

    public void onFragmentSelected(int position, Bundle bundle) {

        Fragment curFragment = null ;

 

        if(position == 0)

        {

            curFragment = fragment1 ;

            toolbar.setTitle("첫번째 화면");

        }

 

        else if(position == 1)

        {

            curFragment = fragment2 ;

            toolbar.setTitle("두번째 화면");

        }

 

        else if(position == 2)

        {

            curFragment = fragment3 ;

            toolbar.setTitle("세번째 화면");

        }

 

        getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();

    }

 

위와 같이 오버라이드 해주고 프래그먼트를 바꿔줄 때마다 위 함수를 호출하면 된다.

 

 

 

 

 

 

 

결과화면1

 

결과화면2

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.example.boostcoursepractice;
 
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentStatePagerAdapter;
import androidx.viewpager.widget.ViewPager;
 
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Toast;
import android.widget.Toolbar;
 
import com.google.android.material.tabs.TabLayout;
 
import java.util.ArrayList;
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
 
ViewPager pager ;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        pager = (ViewPager) findViewById(R.id.pager) ;
        pager.setOffscreenPageLimit(3);
 
        MoviePagerAdapter moviePagerAdapter = new MoviePagerAdapter(getSupportFragmentManager());
 
        Fragment fragment1 = new Fragment1();
        moviePagerAdapter.addItem(fragment1);
 
        Fragment fragment2 = new Fragment2();
        moviePagerAdapter.addItem(fragment2);
 
        Fragment fragment3 = new Fragment3();
        moviePagerAdapter.addItem(fragment3);
 
        pager.setAdapter(moviePagerAdapter);
 
Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
pager.setCurrentItem(1);
}
});
    }
 
    class MoviePagerAdapter extends FragmentStatePagerAdapter
    {
        ArrayList<Fragment> items = new ArrayList<Fragment>();
 
        public MoviePagerAdapter(FragmentManager fm) {
            super(fm);
 
        }
 
        public void addItem(Fragment item)
        {
            items.add(item);
        }
 
        @Override
        public Fragment getItem(int position) {
            return items.get(position);
        }
 
        @Override
        public int getCount() {
            return items.size();
        }
 
@Nullable
@Override
public CharSequence getPageTitle(int position) {
return "페이지" + position;
}
    }
}
 
 
 
 
cs
 
 
 

 

Fragment1

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.boostcoursepractice;
 
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 androidx.viewpager.widget.ViewPager;
 
public class Fragment1 extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment1, container, false);
 
        return rootView;
    }
}
 
cs

 

Fragment2

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.boostcoursepractice;
 
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 androidx.viewpager.widget.ViewPager;
 
public class Fragment2 extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment2, container, false);
 
        return rootView;
    }
}
 
cs

 

Fragment3

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.example.boostcoursepractice;
 
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 androidx.viewpager.widget.ViewPager;
 
public class Fragment3 extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup)inflater.inflate(R.layout.fragment3, container, false);
 
        return rootView;
    }
}
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="0dp"
        android:layout_marginTop="0dp"
        android:text="두 번째 보기" />
 
    <androidx.viewpager.widget.ViewPager
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/button"
        android:layout_alignParentLeft="true"
        android:id="@+id/pager">
 
<androidx.viewpager.widget.PagerTitleStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#55cedf"
android:paddingTop="5dp"
android:paddingBottom="5dp"
></androidx.viewpager.widget.PagerTitleStrip>
 
    </androidx.viewpager.widget.ViewPager>
</RelativeLayout>
 
 
 
cs

 

fragment1.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/design_default_color_primary"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="첫번째"
        android:textSize="40dp" />
 
</LinearLayout>
cs

 

fragment2.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorAccent"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="두번째"
        android:textSize="40dp" />
 
</LinearLayout>
cs

 

fragment3.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_dark"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="세번째"
        android:textSize="40dp" />
 
</LinearLayout>
cs

 

우선 뷰페이저를 만들기 위해서 메인액티비티 xml파일에 뷰페이저 태그를 만들어 추가해주었다.

이제 메인액티비의 자바코드로 가보자. 방금 만든 뷰페이저를 찾아 참조해주어 pager를 만들고 그 페이저에 어댑터를 만들어 줘야 한다.

 

class MoviePagerAdapter extends FragmentStatePagerAdapter

    {

        ArrayList<Fragment> items = new ArrayList<Fragment>();

 

        public MoviePagerAdapter(FragmentManager fm) {

            super(fm);

 

        }

 

        public void addItem(Fragment item)

        {

            items.add(item);

        }

 

        @Override

        public Fragment getItem(int position) {

            return items.get(position);

        }

 

        @Override

        public int getCount() {

            return items.size();

        }

    }

 

위 처럼 FragmentStatePagerAdapter만들어 어댑터를 만들어 줘야 하고 필수로생성자를 만들고 getItem, getCount를 오버라이드 해줘야 된다. 추가로 addItem을 만들어 어댑터의 아이템을 추가할 수 있도록 한다.

 

 MoviePagerAdapter moviePagerAdapter = new MoviePagerAdapter(getSupportFragmentManager());

 

        Fragment fragment1 = new Fragment1();

        moviePagerAdapter.addItem(fragment1);

 

        Fragment fragment2 = new Fragment2();

        moviePagerAdapter.addItem(fragment2);

 

        Fragment fragment3 = new Fragment3();

        moviePagerAdapter.addItem(fragment3);

 

        pager.setAdapter(moviePagerAdapter);

 

 

마지막으로 어댑터를 만들어주고 생성자의 매개변수로 액티비티의 프래그먼트 매니저를 전달해 주고 어댑터의 아이템을 추가해주고 마지막으로 페이저에 어댑터를 설정해주면 끝난다.

 

 

 

 

 

페이지 스트립을 만드는 것은 매우 간다하다. 그냥 아까 만든 뷰페이저 안에 

 

<androidx.viewpager.widget.PagerTitleStrip
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#55cedf"
android:paddingTop="5dp"
android:paddingBottom="5dp"
></androidx.viewpager.widget.PagerTitleStrip>

 

라고 태그만 추가해주고 페이저 어댑터의 

 

@Nullable
@Override
public CharSequence getPageTitle(int position) {
return "페이지" + position;
}

 

이 함수만 추가적으로 오버라이드 해주면 된다.

 

 

 

 

 

결과 화면

 

MainActivity

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.example.boostcoursepractice;
 
import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
 
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.Toast;
import android.widget.Toolbar;
 
import com.google.android.material.tabs.TabLayout;
 
import java.util.List;
 
public class MainActivity extends AppCompatActivity {
 
    Fragment1 fragment1;
    Fragment2 fragment2;
    Fragment3 fragment3;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        androidx.appcompat.widget.Toolbar toolbar = (androidx.appcompat.widget.Toolbar ) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
 
        fragment1 = new Fragment1();
        fragment2 = new Fragment2();
        fragment3 = new Fragment3() ;
 
        getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();
 
        TabLayout tabs= (TabLayout)findViewById(R.id.tabs);
        tabs.addTab(tabs.newTab().setText("친구"));
        tabs.addTab(tabs.newTab().setText("일대일 채팅"));
        tabs.addTab(tabs.newTab().setText("기타"));
 
        tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                int position = tab.getPosition();
 
                Fragment selectedFragment = null ;
                if(position == 0 ) {
                    selectedFragment = fragment1;
                } else  if(position == 1 ) {
                    selectedFragment = fragment2;
                } else  if(position == 2 ) {
                    selectedFragment = fragment3;
                }
 
                getSupportFragmentManager().beginTransaction().replace(R.id.container, selectedFragment).commit();
 
            }
 
            @Override
            public void onTabUnselected(TabLayout.Tab tab) {
 
            }
 
            @Override
            public void onTabReselected(TabLayout.Tab tab) {
 
            }
        });
    }
}
 
 
 
 
cs

 

Fragment1

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.boostcoursepractice;
 
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 {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment1, container, false);
 
        return rootView;
    }
}
 
cs

 

Fragment2

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.boostcoursepractice;
 
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 Fragment2 extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment2, container, false);
 
        return rootView;
    }
}
 
cs

 

Fragment3

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.example.boostcoursepractice;
 
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 Fragment3 extends Fragment {
 
    @Nullable
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
 
        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.fragment3, container, false);
 
        return rootView;
    }
}
 
cs

 

activity_main.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">
 
    <androidx.coordinatorlayout.widget.CoordinatorLayout
        android:layout_height="match_parent"
        android:layout_width="match_parent">
 
        <com.google.android.material.appbar.AppBarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
 
            <androidx.appcompat.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@color/colorPrimaryDark"
                android:theme="@style/ThemeOverlay.AppCompat.Dark"
                android:elevation="1dp"
                android:id="@+id/toolbar"></androidx.appcompat.widget.Toolbar>
 
 
            <com.google.android.material.tabs.TabLayout
                android:id="@+id/tabs"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:background="@android:color/background_light"
                android:elevation="1dp"
                app:tabMode="fixed"
                app:tabGravity="fill"
                app:tabTextColor="@color/colorPrimary"
                app:tabSelectedTextColor="@color/colorAccent"
                ></com.google.android.material.tabs.TabLayout>
 
        </com.google.android.material.appbar.AppBarLayout>
        
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            android:id="@+id/container"></FrameLayout>
 
    </androidx.coordinatorlayout.widget.CoordinatorLayout>
 
</RelativeLayout>
cs

 

fragment1.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_blue_bright"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="첫 번째 화면"
        android:textSize="40dp" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="다음" />
</LinearLayout>
cs

 

fragment2.xml

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
   android:background="@color/design_default_color_primary"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="두 번째 화면"
        android:textSize="40dp" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="다음" />
</LinearLayout>
cs

 

fragment3.xml

 

...더보기
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/holo_green_dark"
    android:orientation="vertical">
 
    <TextView
        android:id="@+id/textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="세 번째 화면"
        android:textSize="40dp" />
 
    <Button
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="다음" />
</LinearLayout>
cs

values/styles.xml

...더보기

<resources>

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

</resources>

 

build.gradle

...더보기

apply plugin: 'com.android.application'

android {
compileSdkVersion 29
buildToolsVersion "29.0.0"
defaultConfig {
applicationId "com.example.boostcoursepractice"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.2.0'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.android.support:design:29.+'
}

 

우선 사용자 정의 액션바를 달고 밑에 탭까지 달기 위해서는 위 처럼 style에서 

 

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">

 

을 설정해줘야 하고 또 gradle에서

 

implementation 'com.android.support:design:29.+'

 

포함시켜야만 한다. 이렇게 하고 나서 acitivity_main을 보자 우선 전체를 CoordinatorLayout로 감싸야 하고 그안에

AppBarLayout가 들어야가하고 또 그안에 Toolbar(액션바) TabLayout(탭) 을 설정해주면 된다. 다 설정해준 후 다시 CoordinatorLayout안에 액션바와 탭을 제외한 진짜 레이아웃을 정의해주면 된다. 여기서는 

 

<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/container"></FrameLayout>

 

이렇게 해주었고 이때 

 

app:layout_behavior="@string/appbar_scrolling_view_behavior"

 

이 속성을 꼭 빼먹지 않아야 잘 작동한다.

 

다시 메인 액티비티로 돌아와 

 

androidx.appcompat.widget.Toolbar toolbar = (androidx.appcompat.widget.Toolbar ) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

 

이렇게 툴바를 찾아주고 그것을 다시 액션바 설정 까지 해줘야 한다. 탭바는

 

TabLayout tabs= (TabLayout)findViewById(R.id.tabs);
tabs.addTab(tabs.newTab().setText("친구"));
tabs.addTab(tabs.newTab().setText("일대일 채팅"));
tabs.addTab(tabs.newTab().setText("기타"));

 

이렇게 찾아주고 addTab 과 newTab 으로 항목을 추가해 주면 된다. 탭 바에 클릭 되었을 때는 

 

tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {

int position = tab.getPosition();

Fragment selectedFragment = null ;
if(position == 0 ) {
selectedFragment = fragment1;
} else if(position == 1 ) {
selectedFragment = fragment2;
} else if(position == 2 ) {
selectedFragment = fragment3;
}

getSupportFragmentManager().beginTransaction().replace(R.id.container, selectedFragment).commit();

}

 

이런식으로 리스너를 등록하여 선택된 탭의 position을 가지고 구별하여 기능의 구현한다.

 

 

 

 

결과화면

 

+ Recent posts