zoukankan      html  css  js  c++  java
  • Android中自定义控件

    就像其他开发平台一样,android也可以自定义控件,如下所示,定义了四个自定义控件:翻页/menu/list/跳页

    那自定义控件到底如何实现的呢?

    一般是继承某个view,重写某些方法,然后再layout中引用即可。在实践过程发现如下三个问题:

    1. 每个自定义控件都有特别的需求,比如跳页控件,点击button时button变黑,移开时又恢复原来状态。

    有二种方法可以实现:

    A:

    1. 同在在layout 设置background属性,然后在drawable中实现它

    <Button android:id="@+id/alert_bt_submit"
    			android:layout_height="45px" android:layout_width="80px"
    			android:text="@string/goto_page_title" android:layout_toRightOf="@id/alert_bt_clear"
    			android:background="@drawable/btnchanger">
    </Button>
    
    <selector xmlns:android="http://schemas.android.com/apk/res/android">
    	<item android:state_focused="true" android:drawable="@drawable/im_smallimagelogo_click" />
    	<item android:state_pressed="true" android:drawable="@drawable/im_smallimagelogo_click" />
    	<item android:state_selected="true" android:drawable="@drawable/im_smallimagelogo_click" />
    	<item android:drawable="@drawable/im_smallimagelogo" />
    </selector>
    

    效果如下:

    2.你可以通过自定义控件,在layout.xml中引用它:

    <com.fp.app.fpview.FPListTextView
        android:id="@+id/item_line_one" android:layout_below="@id/item_right_one"
    style="@style/directoty_line" />
    
    protected void onDraw(Canvas canvas) {
    		super.onDraw(canvas);
    		if (textfocused) {
    			Paint p = new Paint();
    			p.setColor(Color.BLACK);
    			Rect rct = new Rect();
    			rct.set(this.getPaddingLeft() + MIDDLE_BORDER_OFFSET - 2, this.getHeight() - 2 - MIDDLE_BORDER_OFFSET, this.getWidth() - this.getPaddingLeft() - RIGHT_PADDING, this.getHeight() - MIDDLE_BORDER_OFFSET);
    			Paint pnt = new Paint();
    			pnt.setStyle(Paint.Style.FILL);
    			pnt.setColor(Color.BLACK);
    			canvas.drawRect(rct, pnt);
    		} else {
    			Paint p = new Paint();
    			p.setColor(R.color.solid_grey);
    			Rect rct = new Rect();
    			rct.set(this.getPaddingLeft() + MIDDLE_BORDER_OFFSET - 2, this.getHeight() - 1 - MIDDLE_BORDER_OFFSET, this.getWidth() - this.getPaddingLeft() - RIGHT_PADDING, this.getHeight() - MIDDLE_BORDER_OFFSET);
    			Paint pnt = new Paint();
    			pnt.setStyle(Paint.Style.FILL);
    			pnt.setColor(R.color.solid_grey);
    			canvas.drawRect(rct, pnt);
    		}
    	}
    
    	@Override
    	protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
    		textfocused = focused;
    		this.invalidate();
    	}
    

    效果如下:

    从看出focus从2位置到3位置,实际就是focus变化后invalidate调用ondraw实现的。发现2焦点lost后

    调用onfocus事件, focused = false;3获得焦点后也调用onfocus,但是focus = true

    3. 自定义控件还有一个好处,可以filter 一些狂点或者狂按操作,比如在menu菜单中,通过重写textview的

    onkeydown 和 onkeyup方法,用户频繁按pad up/pad down就被过滤掉

    @Override
    	public boolean onKeyDown(int keyCode, KeyEvent event) {
    		long currentKeyPressTime = SystemClock.uptimeMillis();
    		if (currentKeyPressTime - mLastKeyPressTime < DEBOUNCE_TIME) {
    			mLastKeyPressTime = currentKeyPressTime;
    			return true;
    		}
    
    		mLastKeyPressTime = currentKeyPressTime;
    		if (mIsKeyDisabled || (isWaitingForKeyUp && keyCode != KeyEvent.KEYCODE_BACK))
    			return true;
    		else {
    			isWaitingForKeyUp = true;
    		}
    
    		return super.onKeyDown(keyCode, event);
    	}
    
    	@Override
    	public boolean onKeyUp(int keyCode, KeyEvent event) {
    		isWaitingForKeyUp = false;
    		super.onKeyUp(keyCode, event);
    		return true;
    	}
    

    废话少说,下面贴一个翻页控件的例子:

    1. 先自定义一个linearlayout

    package com.fp.app.pager;
    
    import com.fp.app.entry.R;
    
    import android.content.Context;
    import android.util.AttributeSet;
    import android.view.LayoutInflater;
    import android.view.WindowManager;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class PagingComponent extends LinearLayout {
    
    	private static final double RATIO_NEXTWIDTH = 0.2;
    	private static final double RATIO_FIRSTWIDTH = 0.15;
    	private static final double RATIO_CURRENTWIDTH = 0.14;
    	private TextView tv_firstpage = null;
    	private TextView tv_previouspage = null;
    	private TextView tv_currentpage = null;
    	private TextView tv_nextpage = null;
    	private TextView tv_lastpage = null;
    
    	public PagingComponent(Context context) {
    		super(context);
    		init();
    	}
    
    	public PagingComponent(Context context, AttributeSet aSet) {
    		super(context, aSet);
    		init();
    	}
    
    	private void init() {
    		initLayoutInflater();
    		int totalWidth = getTotalWidth();
    	    initFirstAndLastPage(totalWidth);		
    		initPreviousAndNextPage(totalWidth);
    		initCurrentPage(totalWidth);
    	}
    
    	private void initLayoutInflater() {
    		LayoutInflater lInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    		lInflater.inflate(R.layout.pagingcomponent, this);
    	}
    
    	private int getTotalWidth() {
    		int totalWidth = ((WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getWidth();
    		return totalWidth;
    	}
    
    
    	private void initCurrentPage(int totalWidth) {
    		int currentWidth = (int) (totalWidth * RATIO_CURRENTWIDTH);
    		tv_currentpage = (TextView) findViewById(R.id.currentPage);
    		tv_currentpage.setText(R.string.currentPage);
    		tv_currentpage.setWidth(currentWidth);
    	}
    
    
    	private void  initPreviousAndNextPage(int totalWidth) {
    		int nextWidth = (int) (totalWidth * RATIO_NEXTWIDTH);
    		tv_previouspage = (TextView) findViewById(R.id.previousPage);
    		tv_previouspage.setText(R.string.previousPage);
    		tv_previouspage.setWidth(nextWidth);
    		
    		tv_nextpage = (TextView) findViewById(R.id.nextPage);
    		tv_nextpage.setText(R.string.nextPage);
    		tv_nextpage.setWidth(nextWidth);
    	}
    
    	private void initFirstAndLastPage(int totalWidth) {
    		int firstWidth = (int) (totalWidth * RATIO_FIRSTWIDTH);
    		tv_firstpage = (TextView) findViewById(R.id.firstPage);
    		tv_firstpage.setText(R.string.firstPage);
    		tv_firstpage.setWidth(firstWidth);
    		
    		tv_lastpage = (TextView) findViewById(R.id.lastPage);
    		tv_lastpage.setText(R.string.lastPage);
    		tv_lastpage.setWidth(firstWidth);
    	}
    
    }
    

    2.在需要使用这个控件的activity中引用它

    <com.fp.app.pager.PagingComponent
             xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pagingComponent"
    	 android:layout_width="fill_parent" android:layout_alignParentBottom="true"
    	android:layout_height="wrap_content" />
    

    3. 再用一个专业的class封装其业务逻辑

    package com.fp.app.pager;
    
    import java.util.List;
    
    import com.fp.app.entry.R;
    import com.fp.app.gotopage.GlobalGotoPageDialog;
    
    import android.app.Activity;
    import android.graphics.Color;
    import android.os.Handler;
    import android.os.Message;
    import android.view.View;
    import android.widget.LinearLayout;
    import android.widget.TextView;
    
    public class FPPageChanger {
    	private List contentList;
    	private int pageNumber = 1;
    	private int maxPage = 1;
    	private int maxCount, eachPageCount;
    
    	private OnPageChangedListener onPageChangedListener;
    	private Activity activity;
    
    	private TextView tv_firstpage;
    	private TextView tv_prepage;
    	private TextView tv_nextpage;
    	private TextView tv_lastpage;
    	private TextView tv_currentpage;
    	private FPPageChangedListener pageListener;
    
    	public FPPageChanger(Activity activity, OnPageChangedListener vOnPageChangedListener) {
    		this.activity = activity;
    		this.onPageChangedListener = vOnPageChangedListener;
    		initListener();
    		initPageButtons();
    	}
    
    	private void initListener() {
    		pageListener = new FPPageChangedListener();
    	}
    
    	private void initPageButtons() {
    		tv_firstpage = (TextView) activity.findViewById(R.id.firstPage);
    		tv_firstpage.setOnClickListener(pageListener);
    
    		tv_prepage = (TextView) activity.findViewById(R.id.previousPage);
    		tv_prepage.setOnClickListener(pageListener);
    
    		tv_nextpage = (TextView) activity.findViewById(R.id.nextPage);
    		tv_nextpage.setOnClickListener(pageListener);
    
    		tv_lastpage = (TextView) activity.findViewById(R.id.lastPage);
    		tv_lastpage.setOnClickListener(pageListener);
    
    		tv_currentpage = (TextView) activity.findViewById(R.id.currentPage);
    		tv_currentpage.setOnClickListener(pageListener);
    	}
    
    	protected void initButtonText() {
    		tv_firstpage.setText(R.string.firstPage);
    		tv_currentpage.setText("" + pageNumber + "/" + maxPage);
    		tv_lastpage.setText(R.string.lastPage);
    	}
    
    	public void setButtonsVisible(boolean visible) {
    		LinearLayout buttons = (LinearLayout) activity.findViewById(R.id.pagingComponent);
    		if (visible) {
    			buttons.setVisibility(View.VISIBLE);
    		} else {
    			buttons.setVisibility(View.INVISIBLE);
    		}
    	}
    
    	public boolean isButtonVisible() {
    		LinearLayout buttons = (LinearLayout) activity.findViewById(R.id.pagingComponent);
    		return buttons.isShown();
    	}
    
    	public int getMaxCount() {
    		return maxCount;
    	}
    
    	public void setMaxCount(int maxCount) {
    		this.maxCount = maxCount;
    	}
    
    	public int getEachPageCount() {
    		return eachPageCount;
    	}
    
    	public void setEachPageCount(int eachPageCount) {
    		this.eachPageCount = eachPageCount;
    	}
    
    	public void setPageEnableAndColor(int pageNum, int totalPage) {
    		if (totalPage == 1) {
    			setAllPageColor(R.color.solid_grey);
    			setAllPageEnable(false);
    		} else if (pageNum == 1) {
    			setPrePageColor(R.color.solid_grey);
    			setPrePageEnable(false);
    			setCurrentPageColor(Color.BLACK);
    			setCurrentPageEnable(true);
    			setNextPageColor(Color.BLACK);
    			setNextPageEnable(true);
    		} else if (pageNum == totalPage) {
    			setNextPageColor(R.color.solid_grey);
    			setNextPageEnable(false);
    			setCurrentPageColor(Color.BLACK);
    			setCurrentPageEnable(true);
    			setPrePageColor(Color.BLACK);
    			setPrePageEnable(true);
    		} else {
    			setAllPageColor(Color.BLACK);
    			setAllPageEnable(true);
    		}
    	}
    
    	public void setPageEnableAndColor(int currentPage, int maxCount, int eachPageCount) {
    		setButtonsVisible(true);
    		setPageNumber(currentPage);
    		composePageButtons(maxCount, eachPageCount);
    		setPageEnableAndColor(currentPage, this.getMaxPage());
    	}
    
    	public void setPrePageEnable(boolean enable) {
    		if (enable) {
    			tv_firstpage.setEnabled(true);
    			tv_prepage.setEnabled(true);
    		} else {
    			tv_firstpage.setEnabled(false);
    			tv_prepage.setEnabled(false);
    		}
    	}
    
    	public void setPrePageColor(int color) {
    		tv_firstpage.setTextColor(color);
    		tv_prepage.setTextColor(color);
    	}
    
    	public void setNextPageColor(int color) {
    		tv_nextpage.setTextColor(color);
    		tv_lastpage.setTextColor(color);
    	}
    
    	public void setCurrentPageEnable(boolean enable) {
    		if (enable) {
    			tv_currentpage.setEnabled(true);
    		} else {
    			tv_currentpage.setEnabled(false);
    		}
    	}
    
    	public void setCurrentPageColor(int color) {
    		tv_currentpage.setTextColor(color);
    	}
    
    	public void setNextPageEnable(boolean enable) {
    		if (enable) {
    			tv_lastpage.setEnabled(true);
    			tv_nextpage.setEnabled(true);
    		} else {
    			tv_lastpage.setEnabled(false);
    			tv_nextpage.setEnabled(false);
    		}
    	}
    
    	public void setAllPageEnable(boolean enable) {
    		if (enable) {
    			tv_firstpage.setEnabled(true);
    			tv_prepage.setEnabled(true);
    			tv_currentpage.setEnabled(true);
    			tv_lastpage.setEnabled(true);
    			tv_nextpage.setEnabled(true);
    		} else {
    			tv_firstpage.setEnabled(false);
    			tv_prepage.setEnabled(false);
    			tv_currentpage.setEnabled(false);
    			tv_lastpage.setEnabled(false);
    			tv_nextpage.setEnabled(false);
    		}
    	}
    
    	public void setAllPageColor(int color) {
    		tv_firstpage.setTextColor(color);
    		tv_lastpage.setTextColor(color);
    		tv_currentpage.setTextColor(color);
    		tv_nextpage.setTextColor(color);
    		tv_prepage.setTextColor(color);
    	}
    
    	public void setTextViewEnable(boolean enable) {
    		if (enable) {
    			tv_firstpage.setEnabled(true);
    			tv_lastpage.setEnabled(true);
    			tv_nextpage.setEnabled(true);
    			tv_prepage.setEnabled(true);
    		} else {
    			tv_firstpage.setEnabled(false);
    			tv_lastpage.setEnabled(false);
    			tv_nextpage.setEnabled(false);
    			tv_prepage.setEnabled(false);
    		}
    	}
    
    	public void setTextColor(int color) {
    		tv_firstpage.setTextColor(color);
    		tv_lastpage.setTextColor(color);
    		tv_nextpage.setTextColor(color);
    		tv_prepage.setTextColor(color);
    	}
    
    	
    	public void composePageButtons(int maxCount, int eachPageCount) {
    		this.eachPageCount = eachPageCount;
    		this.maxCount = maxCount;
    		calcMaxPage(maxCount);
    		initButtonText();
    	}
    
    
    	private void calcMaxPage(int maxCount) {
    		if (maxCount % eachPageCount == 0) {
    			maxPage = maxCount / eachPageCount;
    			if (maxPage == 0)
    				maxPage = 1;
    		} else {
    			maxPage = (int) (maxCount / eachPageCount) + 1;
    		}
    	}
    
    	
    	public void clearView() {
    		tv_firstpage.setText(R.string.firstPage);
    		tv_currentpage.setText(R.string.currentPage);
    		tv_lastpage.setText(R.string.lastPage);
    	}
    
    	public void clearData() {
    		if (contentList != null && contentList.size() > 0) {
    			contentList.clear();
    		}
    		pageNumber = 1;
    		maxPage = 1;
    		maxCount = 0;
    	}
    
    	public void clearALL() {
    		this.clearData();
    		this.clearView();
    	}
    
    	public int getMaxPage() {
    		return maxPage;
    	}
    
    	public int getPageNumber() {
    		return pageNumber;
    	}
    
    	public void setPageNumber(int pageNumber) {
    		this.pageNumber = pageNumber;
    		this.tv_currentpage.setText("" + pageNumber + "/" + maxPage);
    	}
    
    	public void resetMaxPageNumber() {
    		tv_lastpage.setText(R.string.lastPage);
    	}
    
    	public void resetFirstPageNumber() {
    		tv_firstpage.setText(R.string.firstPage);
    	}
    	
    
    	public interface OnPageChangedListener {
    		void onPageDown();
    
    		void onPageUp();
    
    		void onFirstPage();
    
    		void onLastPage();
    
    		void onGotoPage(int pageNum);
    
    	}
    
    	class FPPageChangedListener implements View.OnClickListener {
    		public void onClick(View clickedView) {
    			try {
    				if (clickedView.getId() == R.id.firstPage) {
    					if (getPageNumber() > 1) {
    						onPageChangedListener.onFirstPage();
    					}
    				} else if (clickedView.getId() == R.id.previousPage) {
    					if (getPageNumber() > 1) {
    						onPageChangedListener.onPageUp();
    					}
    				} else if (clickedView.getId() == R.id.nextPage) {
    					int maxPage = getMaxPage();
    					int pageIndex = getPageNumber();
    					if (pageIndex < maxPage) {
    						onPageChangedListener.onPageDown();
    					}
    				} else if (clickedView.getId() == R.id.lastPage) {
    					int maxPage = getMaxPage();
    					int pageIndex = getPageNumber();
    					if (pageIndex < maxPage) {
    						onPageChangedListener.onLastPage();
    					}
    				} else if (clickedView.getId() == R.id.currentPage) {
    					int maxPage = getMaxPage();
    					if (maxPage == 1)
    						return;
    
    					Handler numHandler = new Handler() {
    						public void handleMessage(Message msg) {
    							int num = msg.what;
    							onPageChangedListener.onGotoPage(num);
    						}
    					};
    
    					GlobalGotoPageDialog gotoPage = new GlobalGotoPageDialog(activity, numHandler, maxPage);
    					gotoPage.show();
    				}
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    
    	}
    }
    

    4. 因为每个页面翻页的数据不一样,内部定义了一个接口 OnPageChangedListener ,每个activity实现这个接口即可

    protected void initPageChanger() {
    		pageChanger = new FPPageChanger(this, this);
    	}
    
    FPTocActivity extends Activity implements OnPageChangedListener
    
    	public void onPageDown() {
    		if (pageNum == pageChanger.getMaxPage()) {
    			return;
    		} else {
    			pageNum++;
    			getDataItem(pageNum, eachPageCount);
    		}
    	}
    
    	public void onPageUp() {
    		if (pageNum == FIRSTPAGE) {
    			return;
    		} else {
    			pageNum--;
    			getDataItem(pageNum, eachPageCount);
    		}
    	}
    
    	public void onFirstPage() {
    		pageNum = FIRSTPAGE;
    		getDataItem(pageNum, eachPageCount);
    	}
    
    	public void onLastPage() {
    		pageNum = pageChanger.getMaxPage();
    		getDataItem(pageNum, eachPageCount);
    	}
    
    	public void onGotoPage(int gotoNum) {
    		int currentPageNum = FIRSTPAGE;
    		int maxPage = pageChanger.getMaxPage();
    		if (gotoNum == pageChanger.getPageNumber() || (gotoNum > maxPage && maxPage == pageChanger.getPageNumber()))
    			return;
    		if (gotoNum >= maxPage) {
    			currentPageNum = maxPage;
    		} else
    			currentPageNum = gotoNum;
    		pageNum = currentPageNum;
    		getDataItem(pageNum, eachPageCount);
    	}
    

    其他控件实现方法类似,收工!


  • 相关阅读:
    iOS程序-UIScrollView的基本使用
    iOS方法类:CGAffineTransform
    指南针开发
    iOS用if语句判断null
    UIView常用的一些方法
    xcode视图缩短了
    TCP&UDP基础
    朴素贝叶斯方法在乳腺肿块检测中的应用
    进程与线程的相关知识点总结
    C++中sizeof操作符与strlen函数
  • 原文地址:https://www.cnblogs.com/budoudou/p/2104618.html
Copyright © 2011-2022 走看看