Android 사용자 정의 View 의 세 가지 실현 방식 요약

15089 단어 androidview
완 설 된 항목 에 서 는 사용자 정의 컨트롤 을 많이 사용 합 니 다.사용자 정의 컨트롤 의 실현 방식 을 정리 하려 고 했 습 니 다.오늘 은 정리 해 보 겠 습 니 다.그 전에 곽 림 대신 블 로그 에서 사용자 정의 View 에 관 한 몇 편의 박문 을 배 웠 는데 많은 이익 을 얻 었 다 고 느 꼈 다.본 고 는 그 중의 일부 내용 을 참고 했다.
결론 적 으로 사용자 정의 컨트롤 의 실현 은 세 가지 방식 이 있 는데 그것 이 바로 조합 컨트롤,자체 그리 기 컨트롤 과 계승 컨트롤 이다.다음은 이 세 가지 방식 에 대해 각각 소개 할 것 이다.
(1)조합 컨트롤
조합 컨트롤 은 말 그대로 작은 컨트롤 을 조합 하여 새로운 컨트롤 을 만 드 는 것 입 니 다.이 작은 컨트롤 들 은 대부분 시스템 자체 의 컨트롤 입 니 다.예 를 들 어 많은 응용 프로그램 에서 보편적으로 사용 되 는 제목 표시 줄 컨트롤 은 조합 컨트롤 이 실 용적 입 니 다.다음은 간단 한 제목 표시 줄 사용자 정의 컨트롤 을 통 해 조합 컨트롤 의 용법 을 말 합 니 다.
1.안 드 로 이 드 항목 을 새로 만 들 고 사용자 정의 제목 표시 줄 의 레이아웃 파일 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>

이 제목 표시 줄 컨트롤 이 비교적 간단 하 다 는 것 을 알 수 있 습 니 다.그 중에서 왼쪽 에 반환 버튼 이 있 습 니 다.배경 은 미리 준 비 된 그림 back1 입 니 다.64.png,제목 표시 줄 중간 은 제목 텍스트 입 니 다.
2.클래스 TitleView 를 만 들 고 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 에 서 는 사용자 정의 제목 표시 줄 에 레이아웃 을 불 러 오고 되 돌아 오 는 단추 에 이벤트 감청 방법 을 추가 하 며 제목 텍스트 를 설정 하 는 방법 을 제공 합 니 다.
3、activitymain.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>

4.MainActivity 에서 사용자 정의 제목 표시 줄 을 가 져 오고 반환 단 추 를 위해 사용자 정의 클릭 이 벤트 를 추가 합 니 다.

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 을 더 해서 표 시 됩 니 다.
1.CounterView 클래스 를 만 들 고 자체 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();
  }

}

2、activitymain.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>

2.CustomListView 클래스 를 만 들 고 ListView 에서 계승 하 며 OnTouch Listener 와 OnGesture Listener 인 터 페 이 스 를 실현 합 니 다.

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 e2, float velocityX,
      float velocityY) {
    //               ,  x         y       
    if (!isDeleteShown && Math.abs(velocityX) > Math.abs(velocityY)) {
      mDeleteBtn = LayoutInflater.from(getContext()).inflate(
          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 e1, MotionEvent e2, float distanceX,
      float distanceY) {
    return false;
  }

  @Override
  public void onLongPress(MotionEvent e) {

  }

}
3,정의 목록 항목 레이아웃 customlistview_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.어댑터 클래스 CustomListView Adapter 를 정의 하고 Array Adapter에서 계승 합 니 다.

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、activitymain.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.운행 효 과 는 다음 과 같다.

이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기