본문 바로가기

아옳옳의 코딩공부/아옳옳의 안드로이드스튜디오

2021-03-19 안드로이드 스튜디오(레이아웃 인플레이션 , 어플리케이션 구성하기)

반응형

레이아웃 인플레이션

메모리에 올라가서 객체가 되는 과정이다 그렇게 인플레이션 된 레이아웃을 setContentView 메소드로

레이아웃 파일과 매칭 시키는 것이다. 

(보통 메인클래스에 setContentView(R.id.activity_main) 이렇게 되어있다 ) 

 

하지만 보여지는 화면에 하나의 레이아웃 파일만 있으라는 법은 없다 그래서 

한개의 화면에 다른 레이아웃화면을 띄울 때 나머지 레이아웃도 인플레이션 해주어야 하는데

그것을 아래의 코드로 할 수 있다. 

 

getSystemService(Context.LAYOUT_INFLATER_SERVICE) 를 사용하여 해줄수 있다.

(다른 레이아웃.xml 파일을 인플레이션 해주는 기능) 

 

package com.example.chap11;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;

public class MainActivity extends AppCompatActivity {

    CheckBox checkBox;
    LinearLayout layout;

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

        layout = findViewById(R.id.layout);
        Button button = findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {  // 다른 xml 불러와서 나의 화면에 띄워 주는것인데
                //1번 방법 인플레이션 (컨택스트 정보가 있을땐 getLayoutInflater() 이렇게 사용)
                // (컨택스트 정보가 없을땐  getLayoutInflater().from(context) 이렇게 사용 )
                  LayoutInflater inflater = getLayoutInflater();
                //2번 방법 인플레이션 원래사용하던 예전 방법
                // LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
               
                // 인플레이션 속의 inflate 메소드로 인플레이션 해준다
                // 1)해당 레이아웃 2)넣을 곳 3)그냥 true ( 붙이겠다는거에 동의같은 의미 )
                inflater.inflate(R.layout.sub , layout ,true);

                checkBox = layout.findViewById(R.id.checkBox);

                checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
                    @Override
                    public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                        if(isChecked){
                            checkBox.setText("선택되었습니다.");
                        }else{
                            checkBox.setText("");
                        }

                    }
                });
            }
        });
    }
}

아래 주석을 잘 보면 된다 

나의 엑티비티에 다른 엑티비티를 붙있때 인플레이션 하고 붙이는걸 볼수 있다. 

온클릭 위쪽 주석이 중요하다 , 원래 사용하던 방식과 새롭게 생겨난 방법이 있는데 두개다 사용가능하지만 기왕이면 짧고 간결한게 좋겠지? 

 

그리고 context 정보를 아는 곳에서 사용할땐 크게 문제가 되지 않지만 새로운 클래스에서 할때는 .from(contxt) 를 해줘야 한다 

 

그럼 이번엔 자바소스로 하는 방법도 하나 살펴 보도록하자 

 

자바소스 ( 뷰클래스) 

public class Person extends LinearLayout {

    Context context;
    TextView textView;
    ImageView imageView;
    Button button;

    public Person(Context context) {
        //★2 메인에서 객체를 생성하면서 보낸 context를 여기에 설정 생성자실행되면서 init 메소드 실행
        super(context);
        this.context = context;
        init();
    }
    public void init(){
        //★3 생성자에서 이 메소드를 실행 하게 되고 이 클래스자체를 뷰클래스로 변환 하기위한 인플레이터

        //뷰클래스로 변환 시키는 인플레이터
        //LayoutInflater inflater = (LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);

        //★3-1 인플레이터 해줌
        LayoutInflater inflater = LayoutInflater.from(context);
        //pager레이아웃을  , 여기에 (this) , 인플레이터 해주겠다
        inflater.inflate(R.layout.activity_pager, this, true);

        //인플레이터 해주었기 때문에 이 클래스는 뷰 클래스로 변환이 되었고
        // 변환이 되었기 때문에 여기에서 아이디를 참조하여 사용할수 있다.
        textView = findViewById(R.id.textView);
        imageView = findViewById(R.id.imageView);
        button = findViewById(R.id.button);


        button.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            String number = (String)button.getTag();
                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("tel:"+number));
                context.startActivity(intent);
            }
        });

    }
    
    //어댑터에서 이 메소드를 통하여 레이아웃에 그림과 글을 셋팅 해줌 
    public void setName(String name){
        textView.setText(name);
    }
    public void setImage(int id){
        imageView.setImageResource(id);
    }
    public void setCall_Btn(String number){
        button.setText(number);
        button.setTag(number);
    }

}

 

메인클래스

public class MainActivity extends AppCompatActivity {
    // ★4이제 person뷰 클래스에 정보를 담아 뷰페이저에 넣어 줘야하는데
    // 어댑터를 사용하여 정보를 담아줌
    ViewPager viewPager;
    String[] names = {"트와이스" , "여자친구", "레드벨벳", " 블랙핑크"};
    int[] id = {R.drawable.jeju1, R.drawable.jeju2, R.drawable.jeju3 , R.drawable.jeju4};
    String[] call_num = {"010-1000-1000","010-2000-2000","010-3000-3000","010-4000-4000"};


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager = findViewById(R.id.pager);

        // 아래에 우리가 만든 어탭터 ★6어탭서 생성
        ViewPagerAdapter adapter = new ViewPagerAdapter(this);
        //뷰페이저에 만든 어탭터 껴줌
        viewPager.setAdapter(adapter); // ★7생성된 어댑터를 뷰페이저에 셋팅준다
        //이길이 만큼만 화면을 만들겠다는 것 (실수로 내용이 없는 화면이 만들어지는것 방지)
        viewPager.setOffscreenPageLimit(names.length);



    }

    //어댑터 만든거 중간자 역활을 한다 ★5 어댑터 만들고
    class ViewPagerAdapter extends PagerAdapter {
        Context context;

        public ViewPagerAdapter(Context context) {
            this.context = context;
        }

        //아래 두개 임플리먼트로로 가져옴
        @Override
        public int getCount() {
            //1. 현재 PagerAdapter 관리할 페이지의 수
            return names.length;
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object object) {
            //3. instantiateItem메소드에서 생성한 객체가 뷰페이저와 확인 하는 메소드
            return view.equals(object);
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            //2. viewPager에서 사용할 뷰 객체를 생성 및 등록
            Person person = new Person(context); //★1. 여기서 객체 생성할때 context 정보를 보내주면 Person 에서 받는다
            person.setName(names[position]); // 눈에 보이진 않지만 만든만큼 for문처럼 돈다
            person.setImage(id[position]);
            person.setCall_Btn(call_num[position]);
            container.addView(person,position);
            return person;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            //4. 화면에 보이지 않는 View 객체를 삭제해서 관리 (메모리에 보이는 내용만 가지고 있고 나머지는 지움)
            container.removeView((View)object);
        }
    }
}

일단 순서를 보면 메인에 뷰페이저에 다른 xml을 띄울려고 한다 

그런데 뷰페이저를 사용할려면 어댑터를 써야해서 어댑터를 먼저 만들어주었다 

(단순 순서)

그리고 xml을 만들어주고 이 xml을 관리할 person클래스를 만들어주었다. person은 그냥 클래스 이므로 리니어 레이아웃을 상속받고 인플레이션을 통해 이 클래스는 뷰클래스로서 바뀌게 된다 자 뷰클래스로 받아서 이제 메인에 들어갈수는 있는상황이지만 아무런 데이터가 없는상황 데이터는 메인에 있다 

 

자 이제 메인에서 가진 데이터를 어댑터를 통해 넣어주고(어댑터는 나중에 배운다  ) 그 어댑터를 통해 뷰클래스의 정보들을 변경할수 있는 것이다 .

 

보이는것처럼 전체 레이아웃이 있고 그 안에 새로운 레이아웃을 추가한것을 볼수 있다 

반응형