학원/ANDROID

01/06 78-1 [Android] Costomview

도원결의 2023. 1. 7. 19:07

 

뷰를 커스텀하기

java > view > CustomView.java

이거 어디있나 한 참 찾았다..

//1.view 클래스 상속
public class CustomView extends View {

    //2.Context를 매개변수로 받은 생성자[자바코드용]
    public CustomView(Context context) {
        super(context);
        Log.i("com.kosmo.customview","뷰 객체로 화면 표시");
    }

    //2-1.context와 AttributeSet를 매개변수로 받는 생성자[xml용]
    public CustomView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        Log.i("com.kosmo.customview","xml로 화면 표시");
    }

    //3.onDraw()메소드 오버라이딩(마우슨 우클릭 Generate - 오버라이딩! )
    @Override
    protected void onDraw(Canvas canvas) {
       //배경색 설정
        canvas.drawColor(Color.CYAN);
        //붓 생성
        Paint paint = new Paint();
        paint.setAntiAlias(true);   //붓을 부드럽게 설정
        //붓 색상 설정
        paint.setColor(Color.RED);
        paint.setStrokeWidth(30); //단위는 픽셀, 붓 두깨
        //점 그리기
        canvas.drawPoint(100,100,paint);
        //선 그리기
        paint.setStrokeWidth(10);
        canvas.drawLine(150,150,500,150,paint);
        //사각형
        paint.setColor(0x88911740);
        canvas.drawRect(150,150,500,350,paint);
        //원그리기
        paint.setColor(Color.argb(255,0,255,0));
        canvas.drawCircle(250,450,100,paint);
        //이미지 그리기
        /*
            paint는 null 지정 그래야 이미지 원래 색대로 그려짐!
            원본크기 그대로 출력
            1.drawBitma(bitmap객체,x,y,pain객체)
        */
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_lock_airplane_mode_alpha);
     //   canvas.drawBitmap(bitmap,250,550,null);
        //2..drawBitma(bitmap객체,null,rect dest,Pain객체-null)
        //null지정시 원본이미지 전체가 선택된 후 확대 축소 가능

     //   canvas.drawBitmap(bitmap,null,new Rect(250,550,250+400,550+400),null);

        //3.drawBitmap(Bitmap객체,Rect src,Rect dest,Paint객체)
        //원본의 특정 부분 선택후 확대 축소
        canvas.drawBitmap(bitmap,new Rect(0,0,100,100),new Rect(250,550,250+400,550+400),null);
    }

stroke은 보더역할

 

기본 제공 이미지는  저기 저 경로로 가면 있음

 

 

activity_main.xml

<!--내가만든 뷰를 xml로 전개 시 -->
<com.kosmo.customview10_1.view.CustomView
    android:layout_width="match_parent"
    android:layout_height="match_parent">

</com.kosmo.customview10_1.view.CustomView>

 

태마도 

AndroidManifest.xml

android:theme="@style/Theme.CustomView10_1"

MainActivity.java

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //레이아웃 xml파일로 뷰 전개
        //setContentView(R.layout으로 시작하는리소스 아이디)
        setContentView(R.layout.activity_main);

        //내가만든 뷰로 전개
       // setContentView(new CustomView(this));
    }
}

 

자바코드로 버튼 제어하기

https://developer.android.com/topic/libraries/view-binding?hl=ko#java

findViewById대신 뷰 결합 사용(쟤는 같은 아이디 사용 시 충돌이 일어날 수 있는 문제가 있음)


뷰 바인딩 활성화 해야 함(설정파일에 설정 )

Gradle Scripts > buil.gradle(Mocule: ) 폴더 에

android{ } 요 안에!!

 

 viewBinding {
            enabled = true
        }

 

넣고 sync now 눌러준다

앱  한 번 실행하고 

좌측 상단 Android 를 Project탭으로 변경 후

app->build->generated->data_binding_~밑에 바인딩 클래스가 생성됨을 확인


ActivityMainBinding(그림참고) 

 

 

그 뒤로는 기억이 잘 안나서 순서가 뒤죽박죽임..... 나중에 시간있으면 

그때 순서 맞춰놔야겠다...

 

activity_main.xml 

<EditText
    android:hint="메시지를 입력하세요!"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/infoMessage"
    android:textSize="20sp"
    />
<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    >
    <Button
        android:id="@+id/btnShort"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="짧은 메시지"
        />
    <Button
        android:id="@+id/btnLong"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="긴 메시지"
        android:layout_marginRight="5dp"
        android:layout_marginLeft="5dp"

        />
    <Button
        android:id="@+id/btnCustom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="커스텀뷰" />
</LinearLayout>

아직 아무 적용 x

 

MainActivity.java

 

rootView는 무조건 있음!  루트 뷰는 최상위 뷰(레이아웃)를 의미함!!

inflate() 가 setContentView 와 같음(전개하는 역할)

private ActivityMainBinding binding;
private ToastLayoutBinding toastLayoutBinding;
private View toastRootView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // setContentView(R.layout.activity_main);
    //activity_main.xml을 추상화한 클래스 얻기
    binding= ActivityMainBinding.inflate(getLayoutInflater());
    toastLayoutBinding = toastLayoutBinding.inflate(getLayoutInflater());

    //최상위 레이아웃(루트 뷰 ! 여기선 LinearLayout 요거 통째로 가져오는 것)을 얻기
    View rootview = binding.getRoot();
    toastRootView=toastLayoutBinding.getRoot();
    //레이아웃 전개
    setContentView(rootview);
    //binding객체로 뷰에 직접 접근
    //리스너 부착
    binding.btnShort.setOnClickListener(handler);
    binding.btnLong.setOnClickListener(handler);
    binding.btnCustom.setOnClickListener(handler);
}////
//이벤트 처리하기(익명클래스로)
private View.OnClickListener handler = view ->{
    String msg = binding.infoMessage.getText().toString();
  if(view.getId()==R.id.btnShort){
      Toast.makeText(view.getContext(), msg, Toast.LENGTH_SHORT).show();
  }
  else if(view.getId()==R.id.btnLong){
      Toast.makeText(view.getContext(), msg, Toast.LENGTH_LONG).show();
  }
  else{
      //사용자 입력값을 토스트용 커스텀뷰의 덱스트뷰에설정
      toastLayoutBinding.textView.setText(msg);
      Toast toast = new Toast(view.getContext());
      //토스트 지속시간설정
      toast.setDuration(Toast.LENGTH_LONG);
      //토스트의 화면전개
      toast.setView(toastRootView);
      //토스트보이기!!!
      toast.show();
  }
};

 

 

토스트용 커스텀 뷰 설정

toast_layout.xml

 

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:padding="10dp"
    android:background="@drawable/layout_rounded"
    >
    <ImageView
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="50dp"
        android:src="@drawable/icon2"
        android:scaleType="fitXY"
        />
    <TextView
        android:layout_width="0dp"
        android:layout_weight="8"
        android:layout_height="50dp"
        android:id="@+id/textView"
        android:gravity="center"
        android:textColor="@color/white"
        android:textSize="18sp"
        android:maxLines="1"
        android:ellipsize="end"

        />
    <!--
            ... 표시하기
            android:singleLine="true" dprecated됨
            android:maxLines="1" :한 줄만 표시
            ellipsize:Text가 TextView를 넘어갔을 때 표시할 방법을 설정
            ellipsize = "end" - 뒷 부분을 ...으로 표시
            아래는 maxLines와 함께쓰면 빨간줄 :tools:ignore="EllipsizeMaxLines" 추가 시 제거됨
            ellipsize = "none" - ... 없이 뒷 부분 잘라서 표시 (기본)
            ellipsize = "start" - 앞 부분을 ...으로 표시
            ellipsize = "middle" - 중간 부분을 ...으로 표시
            ellipsize = "marquee" - 흐르는 텍스트 효과
            아래 세줄과 자바코드에서 textView.setSelected(true)추가하면 marquee가 적용 됨
            android:ellipsize="marquee"
            android:marqueeRepeatLimit="marquee_forever"
            android:singleLine="true"
   -->
</LinearLayout>

 

잘나옴

 



위젯을 배우자

activity_main.xml

버튼의 색상을 #ffffffff등 색생코드로 지정하려면
매니페스트파일의 theme속성을 Theme.AppCompat계열로
바꿔라
예:android:theme="@style/Theme.AppCompat.DayNight.DarkActionBar"


<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linearlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="10dp"
    android:orientation="vertical"
    tools:context=".MainActivity">
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#FF00FF00"
        android:text="기본 버튼"/>
    <!-- android:enabled="false"시 디폴트 버튼이 표시된다-->
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="셀렉터 버튼(이미지)"
        android:background="@drawable/button_image_selector"

        />
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/button_color_selector"
        android:text="셀렉터 버튼(색상)"/>
    <!--입력한 문자열의 길이 출력을 하기위한 텍스트뷰-->
    <!-- 시스템에서 제공하는 기본 에디트 텍스트-->
    <TextView
        android:id="@+id/textview"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_marginTop="20dp"
        android:background="#8BC34A"
        android:text="여기에 문자열 길이 표시" />

    <EditText
        android:id="@+id/basicEditText"
        android:hint="기본 에디트 텍스트"
        android:textColorHint="#00ff00"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <!--내가 만든 커스텀 EditText-->
    <!-- 아래 주석처리후 자바코드에서 직접 new로 생성-->

    <com.kosmo.customview10_3.view.MyEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/myEditText"
        android:hint="내가 만든 에디트 텍스트"
        android:textColorHint="#FF0000"
        />
</LinearLayout>

여러 res 사용할거 

drawable 폴더에 이미지 등 넣어놓기

 

 

MainActivity.java

제어하기 

public class MainActivity extends AppCompatActivity {

    //기본 에디트 텍스트상자로 문자열길이 표시 구현용
    private int textLength;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //위젯 얻기
        TextView textView = findViewById(R.id.textview);
        EditText editText = findViewById(R.id.basicEditText);
        LinearLayout layout = findViewById(R.id.linearlayout);

        //1]내가 만든 EditText를 자바코드로 부착하는 경우
        //MyEditText myEditText= new MyEditText(this);
        //myEditText.setHint("내가 만든 에디트 텍스트");
        //myEditText.setHintTextColor(Color.RED);
        //myEditText.setOnTextLengthListener(txtLength->textView.setText(String.valueOf(txtLength)));
        //레이아웃(루트 뷰)에 부착 :addView(View view)
        //layout.addView(myEditText);
        //2]xml에 내가 만든 EditText를 태그로 등록한 경우
        MyEditText myEditText=findViewById(R.id.myEditText);
        myEditText.setOnTextLengthListener(txtLength->textView.setText(String.valueOf(txtLength)));

        editText.addTextChangedListener(new TextWatcher() {
            //한글자 입력전 혹은 삭제전마다 호출됨
            @Override
            public void beforeTextChanged(CharSequence text, int start, int count, int after) {
                Log.i("com.kosmo.customview","기본 에디트텍스트:[beforeTextChanged]");
            }
            //한글자 입력시 혹은 삭제시마다 호출됨
            @Override
            public void onTextChanged(CharSequence text, int start, int before, int count) {
                /*
                text:에디트 텍스트에 입력된 문자열
                start:새로 추가되거나 삭제된 문자열의 시작 인덱스
                before:삭제된 문자열의 갯수
                count:새로 추가된 문자열의 갯수
                 */
                textLength+=count-before;
                textView.setText(String.valueOf(textLength));
                Log.i("com.kosmo.customview","기본 에디트텍스트:[onTextChanged]");
                Log.i("com.kosmo.customview",String.format("text:%s,start:%s,before:%s,count:%s",text,start,before,count));
            }
            //한글자 입력후 혹은 삭제후마다 호출됨
            @Override
            public void afterTextChanged(Editable editable) {
                Log.i("com.kosmo.customview","기본 에디트텍스트:[afterTextChanged]");
            }
        });

    }///////////////