English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
졸업 프로젝트에서 많이 사용된 사용자 정의 컨트롤러에 대해 언제나 요약하려고 했지만, 오늘 이야기합니다. 이전에 구림 대신에 관련 블로그에 대해 몇 가지 글을 읽었고, 많은 도움이 되었습니다. 이 글에서는 그 중 일부 내용을 참고했습니다.
결론적으로, 사용자 정의 컨트롤러의 구현 방법은 세 가지입니다. 그것은 컴보너트, 드로잉 컨트롤러, 상속 컨트롤러입니다. 아래에서 이 세 가지 방법에 대해 각각 설명하겠습니다.
(1) 컴보너트
컴보너트는 그 이름에서 알 수 있듯이 작은 컨트롤러를 하나의 새로운 컨트롤러로 결합하는 것입니다. 이 작은 컨트롤러들은 대부분 시스템이 제공하는 컨트롤러들입니다. 예를 들어, 많은 애플리케이션에서 일반적으로 사용되는 타이틀 바 컨트롤러는 실제로는 컴보너트를 사용하고 있습니다. 그래서 아래에서 간단한 타이틀 바 사용자 정의 컨트롤러를 통해 컴보너트의 사용법에 대해 설명하겠습니다.
1、Android 프로젝트를 새로 만들고, 사용자 정의 타이틀 바 레이아웃 파일 title_bar.xml을 생성하세요:
<?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="wrap_content" android:background="#0000ff" > <Button android:id="@"+id/left_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="5dp" android:background="@drawable/back1_64" /> <TextView android:id="@"+id/title_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:text="이는 타이틀입니다" android:textColor="#ffffff" android:textSize="20sp" /> </RelativeLayout>
이 타이틀 바 컨트롤은 상대적으로 간단하게 보입니다. 왼쪽에는 돌아가기 버튼이 있으며, 배경은 사전에 준비된 이미지 back입니다1_64.png, 타이틀 바 중앙에는 타이틀 텍스트가 있습니다。
2TitleView 클래스를 생성하고, RelativeLayout을 상속합니다:
public class TitleView extends RelativeLayout { // 돌아가기 버튼 컨트롤 private Button mLeftBtn; // 타이틀 Tv private TextView mTitleTv; public TitleView(Context context, AttributeSet attrs) { super(context, attrs); // 레이아웃 로드 LayoutInflater.from(context).inflate(R.layout.title_bar, this); // 컨트롤을 가져옵니다 mLeftBtn = (Button) findViewById(R.id.left_btn); mTitleTv = (TextView) findViewById(R.id.title_tv); } // 왼쪽 돌아가기 버튼에 사용자 정의 클릭 이벤트를 추가합니다 public void setLeftButtonListener(OnClickListener listener) { mLeftBtn.setOnClickListener(listener); } // 타이틀 설정 메서드 public void setTitleText(String title) { mTitleTv.setText(title); } }
TitleView에서는 사용자 정의 타이틀 바에 레이아웃을 로드하고, 돌아가기 버튼에 이벤트 리스너를 추가하며, 타이틀 텍스트를 설정하는 메서드를 제공합니다。
3activity_main.xml에서 사용자 정의 타이틀 바를 포함하도록 합니다:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.TitleView android:id="@"+id/title_bar" android:layout_width="match_parent" android:layout_height="wrap_content" > </com.example.test.TitleView> </LinearLayout>
4MainActivity에서 사용자 정의 타이틀 바를 가져오고, 돌아가기 버튼에 사용자 정의 클릭 이벤트를 추가합니다:
private TitleView mTitleBar; mTitleBar = (TitleView) findViewById(R.id.title_bar); mTitleBar.setLeftButtonListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(MainActivity.this, "뒤로 가기 버튼을 클릭했습니다", Toast.LENGTH_SHORT) .show(); finish(); } });
5실행 결과는 다음과 같습니다:
이렇게 조합을 통해 사용자 정의 타이틀 바를 구현했습니다. 더 많은 조합을 통해 더 복잡한 사용자 정의 컨트롤을 생성할 수 있습니다. 예를 들어, 사용자 정의 검색 표시줄 등.
(2) 자체 그리기 컨트롤
자체 그리기 컨트롤의 내용은 모두 자체로 그려집니다. View의 onDraw 메서드에서 그리기가 완료됩니다. 아래는 간단한 카운터를 구현하여, 이 컨트롤을 클릭할 때마다 카운트 값이 증가합니다.1그리고 표시합니다.
1CounterView 클래스를 생성하여 View를 상속하고 OnClickListener 인터페이스를 구현합니다:
public class CounterView extends View implements OnClickListener { // 페인트 정의 private Paint mPaint; // 문자의 너비와 높이를 얻기 위함 private Rect mBounds; // 카운트 값, 이 컨트롤을 클릭할 때마다 값이 증가합니다1 private int mCount; public CounterView(Context context, AttributeSet attrs) { super(context, attrs); // 페인트와 Rect 초기화 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mBounds = new Rect(); // 이 컨트롤의 클릭 이벤트 setOnClickListener(this); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setColor(Color.BLUE); // 파란색 채우기로된 사각형을 그립니다 canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); mPaint.setColor(Color.YELLOW); mPaint.setTextSize(50); String text = String.valueOf(mCount); // 문자의 너비와 높이를 가져옵니다 mPaint.getTextBounds(text, 0, text.length(), mBounds); float textWidth = mBounds.width(); float textHeight = mBounds.height(); // 문자열 그리기 canvas.drawText(text, getWidth(), / 2 - textWidth / 2, getHeight() / 2 + textHeight / 2, mPaint); } @Override public void onClick(View v) { mCount ++; // 다시 그리기 invalidate(); } }
2activity_main.xml에서 이 커스텀 레이아웃을 포함합니다:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.CounterView android:id="@"+id/counter_view" android:layout_width="100dp" android:layout_height="100dp" android:layout_gravity="center_horizontal|top" android:layout_margin="20dp" /> </LinearLayout>
3실행 결과는 다음과 같습니다:
(3)컨트롤 상속
기존 컨트롤을 상속하고 새 컨트롤을 생성하여 상속된 부모 컨트롤의 특성을 유지하며 새로운 특성을 도입할 수 있습니다. 아래에서는 수평 슬라이딩으로 목록 항목을 삭제할 수 있는 커스텀 ListView의 구현을 설명합니다.
1삭제 버튼 레이아웃 delete_btn.xml을 생성합니다. 이 레이아웃은 수평 슬라이딩 후에 표시됩니다:
<?xml version="1.0" encoding="utf-8"?> <Button xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#FF0000" android:padding="5dp" android:text="삭제" android:textColor="#FFFFFF" android:textSize="16sp" > </Button>
2CustomListView 클래스를 생성하여 ListView를 상속하고 OnTouchListener 및 OnGestureListener 인터페이스를 구현합니다:
public class CustomListView extends ListView implements OnTouchListener, OnGestureListener { // 손가락 이동 감지기 private GestureDetector mGestureDetector; // 지우기 이벤트 리스너 public interface OnDeleteListener { void onDelete(int index); } private OnDeleteListener mOnDeleteListener; // 지우기 버튼 private View mDeleteBtn; // 목록 항목 레이아웃 private ViewGroup mItemLayout; // 선택된 목록 항목 private int mSelectedItem; // 현재 지우기 버튼이 표시되었는지 private boolean isDeleteShown; public CustomListView(Context context, AttributeSet attrs) { super(context, attrs); // 갑수 리스너 객체 생성 mGestureDetector = new GestureDetector(getContext(), this); // onTouch 이벤트를 리스닝 setOnTouchListener(this); } // 지우기 리스너 이벤트 설정 public void setOnDeleteListener(OnDeleteListener listener) { mOnDeleteListener = listener; } // 터치 리스너 이벤트 @Override public boolean onTouch(View v, MotionEvent event) { if (isDeleteShown) { hideDelete(); return false; } else { return mGestureDetector.onTouchEvent(event); } } @Override public boolean onDown(MotionEvent e) { if (!isDeleteShown) { mSelectedItem = pointToPosition((int) e.getX(), (int) e.getY()); } return false; } @Override public boolean onFling(MotionEvent e1, MotionEvent e}}2, float velocityX, float velocityY) { // 현재 지우기 버튼이 표시되지 않았으며, x 방향 스르르 움직이는 속도가 y 방향 스르르 움직이는 속도보다 크다 if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) { mDeleteBtn = LayoutInflater.from(getContext()).inflate(R.layout.delete_btn, null); R.layout.delete_btn, null); mDeleteBtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mItemLayout.removeView(mDeleteBtn); mDeleteBtn = null; isDeleteShown = false; mOnDeleteListener.onDelete(mSelectedItem); } }); mItemLayout = (ViewGroup) getChildAt(mSelectedItem); - getFirstVisiblePosition()); RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(); LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT); params.addRule(RelativeLayout.CENTER_VERTICAL); mItemLayout.addView(mDeleteBtn, params); isDeleteShown = true; } return false; } // 삭제 버튼을 숨기기 public void hideDelete() { mItemLayout.removeView(mDeleteBtn); mDeleteBtn = null; isDeleteShown = false; } public boolean isDeleteShown() { return isDeleteShown; } /** * 이제 몇 가지 메서드는 이 예제에서 사용되지 않았습니다 */ @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e)1, MotionEvent e}}2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } }
3、定義列表項佈局custom_listview_item.xml,它的結構很簡單,只包含了一個TextView:
<?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" android:descendantFocusability="blocksDescendants" > <TextView android:id="@"+id/content_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_margin="30dp" android:gravity="center_vertical|left" /> </RelativeLayout>
4、定義適應器類CustomListViewAdapter,繼承自ArrayAdapter<String>:
public class CustomListViewAdapter extends ArrayAdapter<String> { public CustomListViewAdapter(Context context, int textViewResourceId, List<String> objects) { super(context, textViewResourceId, objects); } @Override public View getView(int position, View convertView, ViewGroup parent) { View view; if (convertView == null) { view = LayoutInflater.from(getContext()).inflate( R.layout.custom_listview_item, null); } else { view = convertView; } TextView contentTv = (TextView) view.findViewById(R.id.content_tv); contentTv.setText(getItem(position)); return view; } }
5、activity_main.xml에서 직접 제작된 ListView를 가져옵니다:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@"+id/main_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <com.example.test.CustomListView android:id="@"+id/custom_lv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
6、MainActivity에서 목록을 초기화하고, 목록 항목 삭제 버튼 클릭 이벤트 등을 처리합니다:
public class MainActivity extends Activity { // 직접 Lv private CustomListView mCustomLv; // 직접 제작适配기 private CustomListViewAdapter mAdapter; // 내용 목록 private List<String> contentList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); initContentList(); mCustomLv = (CustomListView) findViewById(R.id.custom_lv); mCustomLv.setOnDeleteListener(new OnDeleteListener() { @Override public void onDelete(int index) { contentList.remove(index); mAdapter.notifyDataSetChanged(); } }); mAdapter = new CustomListViewAdapter(this, 0, contentList); mCustomLv.setAdapter(mAdapter); } // 내용 목록 초기화 private void initContentList() { for (int i = 0; i < 20; i++) { contentList.add("내용 항목" + i); } } @Override public void onBackPressed() { if (mCustomLv.isDeleteShown()) { mCustomLv.hideDelete(); return; } super.onBackPressed(); } }
7실행 결과는 다음과 같습니다:
이것이 이 문서의 모든 내용입니다. 많은 도움이 되길 바랍니다. 또한, 노래 튜토리얼을 많이 지지해 주시기 바랍니다.
고지사항: 이 문서의 내용은 인터넷에서 가져왔으며, 저작권자에게 소유되며, 인터넷 사용자가 자발적으로 기여하고 자체적으로 업로드한 내용입니다. 이 웹사이트는 소유권을 가지지 않으며, 인공 편집 처리를 하지 않았으며, 관련 법적 책임도 부담하지 않습니다. 저작권 위반이 의심되는 내용이 있다면, 이메일을 notice#w로 보내 주시기 바랍니다.3codebox.com(메일을 보내는 경우 #을 @으로 변경하십시오. 신고를 하시고 관련 증거를 제공하시면, 실제로 확인되면 이 사이트는 즉시 위반 내용을 삭제합니다。)