編輯:關於Android編程
下拉刷新和上拉加載的listview的實現。
首先看下大致的效果:
接著看一下怎麼使用的:
2.1 在layout中定義
DropDownListView自定義了三個boolean屬性
isDropDownStyle表示是否允許下拉樣式,java代碼中可自定義下拉listener,表示需要完成的任務
isOnBottomStyle表示是否允許底部樣式,java代碼中可自定義滾動到底部的listener,表示需要完成的任務
isAutoLoadOnBottom表示是否允許滾動到底部時自動執行對應listener,僅在isOnBottomStyle為true時有效
PS:如果isDropDownStyle或isOnBottomStyle為false,並不會加載對應的布局,所以性能同ListView一樣。
2.2 在java類中調用:
示例代碼如下:
package com.nsu.app.dropdownlistviewdemo;
import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Toast;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
/**
* Create By Anthony on 2016/2/15
* demo of dropDownListView
*/
public class DropDownListViewDemo extends Activity {
private LinkedList listItems = null;
private DropDownListView listView = null;
private ArrayAdapter adapter;
private String[] mStrings = {"11111", "2222", "3333",
"4444", "5555", "6666", "77777", "8888", "99999",
"aaaaa", "bbbb", "cccc", "dddd", "eeee",};
public static final int MORE_DATA_MAX_COUNT = 3;
public int moreDataCount = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drop_down_list_view_demo);
listView = (DropDownListView)findViewById(R.id.list_view);
// set drop down listener
listView.setOnDropDownListener(new DropDownListView.OnDropDownListener() {
@Override
public void onDropDown() {
new GetDataTask(true).execute();
}
});
// set on bottom listener
listView.setOnBottomListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new GetDataTask(false).execute();
}
});
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
// ToastUtils.show(context, R.string.drop_down_tip);
Toast.makeText(DropDownListViewDemo.this,R.string.drop_down_tip,Toast.LENGTH_LONG).show();
}
});
// listView.setShowFooterWhenNoMore(true);
listItems = new LinkedList();
listItems.addAll(Arrays.asList(mStrings));
adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, listItems);
listView.setAdapter(adapter);
}
private class GetDataTask extends AsyncTask {
private boolean isDropDown;
public GetDataTask(boolean isDropDown) {
this.isDropDown = isDropDown;
}
@Override
protected String[] doInBackground(Void... params) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
return mStrings;
}
@Override
protected void onPostExecute(String[] result) {
if (isDropDown) {
listItems.addFirst("Added after drop down");
adapter.notifyDataSetChanged();
// should call onDropDownComplete function of DropDownListView at end of drop down complete.
SimpleDateFormat dateFormat = new SimpleDateFormat("MM-dd HH:mm:ss");
listView.onDropDownComplete(getString(R.string.update_at) + dateFormat.format(new Date()));
} else {
moreDataCount++;
listItems.add("Added after on bottom");
adapter.notifyDataSetChanged();
if (moreDataCount >= MORE_DATA_MAX_COUNT) {
listView.setHasMore(false);
}
// should call onBottomComplete function of DropDownListView at end of on bottom complete.
listView.onBottomComplete();
}
super.onPostExecute(result);
}
}
}
可以看到我們通過setOnDropDownListener設置下拉的事件,不過需要在事件結束時手動調用onDropDownComplete恢復狀態(注意需要在adapter.notifyDataSetChanged();後面調用)。
通過setOnBottomListener設置滾動到底部的事件,不過需要在事件結束時手動調用onBottomComplete恢復狀態。
樣式的定義(header 和footer)
我們是在listview的上面加上了header和下面加上了footer,那麼來看看我們的自定義屬性:
3.1自定義下拉的圖片,在項目drawable資源下添加文件名為drop_down_list_arrow.png的圖片即可
3.2定義相關文字,strings.xml中定義下面屬性:
DropDownListViewDemo
Settings
Image
Click to refresh。。。
Drop Down to refresh。。。
Release to refresh。。。
Loading。。。
More
Loading。。。
No More
Pull down to refresh or scroll to bottom to load more
updated at:
3.3定義相關字體顏色,colors.xml中定義下面屬性:
#000000
#000000
#000000
3.4 定義相關樣式(會覆蓋前面的string和color定義),styles.xml中定義下面屬性:
3.4 定義相關dimen值,dimens.xml中定義下面屬性:
12dp
15dp
36dp
36dp
也是最重要的我們的自定義控件:
package com.nsu.app.dropdownlistviewdemo;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
/**
* ListView which can drop down to refresh and
* load more when scroll to bottom
*/
public class DropDownListView extends ListView implements OnScrollListener {
private boolean isDropDownStyle = true;
private boolean isOnBottomStyle = true;
private boolean isAutoLoadOnBottom = false;
private String headerDefaultText;
private String headerPullText;
private String headerReleaseText;
private String headerLoadingText;
private String footerDefaultText;
private String footerLoadingText;
private String footerNoMoreText;
private Context context;
/** header layout view **/
private RelativeLayout headerLayout;
private ImageView headerImage;
private ProgressBar headerProgressBar;
private TextView headerText;
private TextView headerSecondText;
/** footer layout view **/
private RelativeLayout footerLayout;
private ProgressBar footerProgressBar;
private Button footerButton;
private OnDropDownListener onDropDownListener;
private OnScrollListener onScrollListener;
/** rate about drop down distance and header padding top when drop down **/
private float headerPaddingTopRate = 1.5f;
/** min distance which header can release to loading **/
private int headerReleaseMinDistance;
/** whether bottom listener has more **/
private boolean hasMore = true;
/** whether show footer loading progress bar when loading **/
private boolean isShowFooterProgressBar = true;
/** whether show footer when no more data **/
private boolean isShowFooterWhenNoMore = false;
private int currentScrollState;
private int currentHeaderStatus;
/** whether reached top, when has reached top, don't show header layout **/
private boolean hasReachedTop = false;
/** image flip animation **/
private RotateAnimation flipAnimation;
/** image reverse flip animation **/
private RotateAnimation reverseFlipAnimation;
/** header layout original height **/
private int headerOriginalHeight;
/** header layout original padding top **/
private int headerOriginalTopPadding;
/** y of point which user touch down **/
private float actionDownPointY;
/** whether is on bottom loading **/
private boolean isOnBottomLoading = false;
public DropDownListView(Context context) {
super(context);
init(context);
}
public DropDownListView(Context context, AttributeSet attrs) {
super(context, attrs);
getAttrs(context, attrs);
init(context);
}
public DropDownListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getAttrs(context, attrs);
init(context);
}
private void init(Context context) {
this.context = context;
initDropDownStyle();
initOnBottomStyle();
// should set, to run onScroll method and so on
super.setOnScrollListener(this);
}
/**
* init drop down style, only init once
*/
private void initDropDownStyle() {
if (headerLayout != null) {
if (isDropDownStyle) {
addHeaderView(headerLayout);
} else {
removeHeaderView(headerLayout);
}
return;
}
if (!isDropDownStyle) {
return;
}
headerReleaseMinDistance = context.getResources().getDimensionPixelSize(
R.dimen.drop_down_list_header_release_min_distance);
flipAnimation = new RotateAnimation(0, 180, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
flipAnimation.setInterpolator(new LinearInterpolator());
flipAnimation.setDuration(250);
flipAnimation.setFillAfter(true);
reverseFlipAnimation = new RotateAnimation(-180, 0, RotateAnimation.RELATIVE_TO_SELF, 0.5f,
RotateAnimation.RELATIVE_TO_SELF, 0.5f);
reverseFlipAnimation.setInterpolator(new LinearInterpolator());
reverseFlipAnimation.setDuration(250);
reverseFlipAnimation.setFillAfter(true);
headerDefaultText = context.getString(R.string.drop_down_list_header_default_text);
headerPullText = context.getString(R.string.drop_down_list_header_pull_text);
headerReleaseText = context.getString(R.string.drop_down_list_header_release_text);
headerLoadingText = context.getString(R.string.drop_down_list_header_loading_text);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
headerLayout = (RelativeLayout)inflater.inflate(R.layout.drop_down_list_header, this, false);
headerText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_default_text);
headerImage = (ImageView)headerLayout.findViewById(R.id.drop_down_list_header_image);
headerProgressBar = (ProgressBar)headerLayout.findViewById(R.id.drop_down_list_header_progress_bar);
headerSecondText = (TextView)headerLayout.findViewById(R.id.drop_down_list_header_second_text);
headerLayout.setClickable(true);
headerLayout.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onDropDown();
}
});
headerText.setText(headerDefaultText);
addHeaderView(headerLayout);
measureHeaderLayout(headerLayout);
headerOriginalHeight = headerLayout.getMeasuredHeight();
headerOriginalTopPadding = headerLayout.getPaddingTop();
currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD;
}
/**
* init on bottom style, only init once
*/
private void initOnBottomStyle() {
if (footerLayout != null) {
if (isOnBottomStyle) {
addFooterView(footerLayout);
} else {
removeFooterView(footerLayout);
}
return;
}
if (!isOnBottomStyle) {
return;
}
footerDefaultText = context.getString(R.string.drop_down_list_footer_default_text);
footerLoadingText = context.getString(R.string.drop_down_list_footer_loading_text);
footerNoMoreText = context.getString(R.string.drop_down_list_footer_no_more_text);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
footerLayout = (RelativeLayout)inflater.inflate(R.layout.drop_down_list_footer, this, false);
footerButton = (Button)footerLayout.findViewById(R.id.drop_down_list_footer_button);
footerButton.setDrawingCacheBackgroundColor(0);
footerButton.setEnabled(true);
footerProgressBar = (ProgressBar)footerLayout.findViewById(R.id.drop_down_list_footer_progress_bar);
addFooterView(footerLayout);
}
/**
* @return isDropDownStyle
*/
public boolean isDropDownStyle() {
return isDropDownStyle;
}
/**
* @param isDropDownStyle
*/
public void setDropDownStyle(boolean isDropDownStyle) {
if (this.isDropDownStyle != isDropDownStyle) {
this.isDropDownStyle = isDropDownStyle;
initDropDownStyle();
}
}
/**
* @return isOnBottomStyle
*/
public boolean isOnBottomStyle() {
return isOnBottomStyle;
}
/**
* @param isOnBottomStyle
*/
public void setOnBottomStyle(boolean isOnBottomStyle) {
if (this.isOnBottomStyle != isOnBottomStyle) {
this.isOnBottomStyle = isOnBottomStyle;
initOnBottomStyle();
}
}
/**
* @return isAutoLoadOnBottom
*/
public boolean isAutoLoadOnBottom() {
return isAutoLoadOnBottom;
}
/**
* set whether auto load when on bottom
*
* @param isAutoLoadOnBottom
*/
public void setAutoLoadOnBottom(boolean isAutoLoadOnBottom) {
this.isAutoLoadOnBottom = isAutoLoadOnBottom;
}
/**
* get whether show footer loading progress bar when loading
*
* @return the isShowFooterProgressBar
*/
public boolean isShowFooterProgressBar() {
return isShowFooterProgressBar;
}
/**
* set whether show footer loading progress bar when loading
*
* @param isShowFooterProgressBar
*/
public void setShowFooterProgressBar(boolean isShowFooterProgressBar) {
this.isShowFooterProgressBar = isShowFooterProgressBar;
}
/**
* get isShowFooterWhenNoMore
*
* @return the isShowFooterWhenNoMore
*/
public boolean isShowFooterWhenNoMore() {
return isShowFooterWhenNoMore;
}
/**
* set isShowFooterWhenNoMore
*
* @param isShowFooterWhenNoMore the isShowFooterWhenNoMore to set
*/
public void setShowFooterWhenNoMore(boolean isShowFooterWhenNoMore) {
this.isShowFooterWhenNoMore = isShowFooterWhenNoMore;
}
/**
* get footer button
*
* @return
*/
public Button getFooterButton() {
return footerButton;
}
@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(adapter);
if (isDropDownStyle) {
setSecondPositionVisible();
}
}
@Override
public void setOnScrollListener(OnScrollListener listener) {
onScrollListener = listener;
}
/**
* @param onDropDownListener
*/
public void setOnDropDownListener(OnDropDownListener onDropDownListener) {
this.onDropDownListener = onDropDownListener;
}
/**
* @param onBottomListener
*/
public void setOnBottomListener(OnClickListener onBottomListener) {
if (!isDropDownStyle) {
throw new RuntimeException(
"isDropDownStyle is false, cannot call setOnBottomListener, you can call setDropDownStyle(true) at fitst.");
}
footerButton.setOnClickListener(onBottomListener);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isDropDownStyle) {
return super.onTouchEvent(event);
}
hasReachedTop = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
actionDownPointY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
adjustHeaderPadding(event);
break;
case MotionEvent.ACTION_UP:
if (!isVerticalScrollBarEnabled()) {
setVerticalScrollBarEnabled(true);
}
/**
* set status when finger leave screen if first item visible and header status is not
* HEADER_STATUS_LOADING
*
*
if current header status is HEADER_STATUS_RELEASE_TO_LOAD, call onDropDown. *
if current header status is HEADER_STATUS_DROP_DOWN_TO_LOAD, then set header status to * HEADER_STATUS_CLICK_TO_LOAD and hide header layout. *
*/ if (getFirstVisiblePosition() == 0 && currentHeaderStatus != HEADER_STATUS_LOADING) { switch (currentHeaderStatus) { case HEADER_STATUS_RELEASE_TO_LOAD: onDropDown(); break; case HEADER_STATUS_DROP_DOWN_TO_LOAD: setHeaderStatusClickToLoad(); setSecondPositionVisible(); break; case HEADER_STATUS_CLICK_TO_LOAD: default: break; } } break; } return super.onTouchEvent(event); } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (isDropDownStyle) { if (currentScrollState == SCROLL_STATE_TOUCH_SCROLL && currentHeaderStatus != HEADER_STATUS_LOADING) { /** * when state of ListView is SCROLL_STATE_TOUCH_SCROLL(ListView is scrolling and finger is on screen) * and header status is not HEADER_STATUS_LOADING *
* if header layout is visiable, *
if height of header is higher than a fixed value, then set header status to * HEADER_STATUS_RELEASE_TO_LOAD. *
else set header status to HEADER_STATUS_DROP_DOWN_TO_LOAD. *
*
* if header layout is not visiable, *
set header status to HEADER_STATUS_CLICK_TO_LOAD. *
*/ if (firstVisibleItem == 0) { headerImage.setVisibility(View.VISIBLE); int pointBottom = headerOriginalHeight + headerReleaseMinDistance; if (headerLayout.getBottom() >= pointBottom) { setHeaderStatusReleaseToLoad(); } else if (headerLayout.getBottom() < pointBottom) { setHeaderStatusDropDownToLoad(); } } else { setHeaderStatusClickToLoad(); } } else if (currentScrollState == SCROLL_STATE_FLING && firstVisibleItem == 0 && currentHeaderStatus != HEADER_STATUS_LOADING) { /** * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and * first item(header layout) is visible and header status is not HEADER_STATUS_LOADING, then hide first * item, set second item visible and set hasReachedTop true. */ setSecondPositionVisible(); hasReachedTop = true; } else if (currentScrollState == SCROLL_STATE_FLING && hasReachedTop) { /** * when state of ListView is SCROLL_STATE_FLING(ListView is scrolling but finger has leave screen) and * hasReachedTop is true(it's because flick back), then hide first item, set second item visible. */ setSecondPositionVisible(); } } // if isOnBottomStyle and isAutoLoadOnBottom and hasMore, then call onBottom function auto if (isOnBottomStyle && isAutoLoadOnBottom && hasMore) { if (firstVisibleItem > 0 && totalItemCount > 0 && (firstVisibleItem + visibleItemCount == totalItemCount)) { onBottom(); } } if (onScrollListener != null) { onScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } } @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (isDropDownStyle) { currentScrollState = scrollState; if (currentScrollState == SCROLL_STATE_IDLE) { hasReachedTop = false; } } if (onScrollListener != null) { onScrollListener.onScrollStateChanged(view, scrollState); } } /** * drop down begin, adjust view status */ private void onDropDownBegin() { if (isDropDownStyle) { setHeaderStatusLoading(); } } /** * on drop down loading, you can call it by manual, but you should manual call onBottomComplete at the same time. */ public void onDropDown() { if (currentHeaderStatus != HEADER_STATUS_LOADING && isDropDownStyle && onDropDownListener != null) { onDropDownBegin(); onDropDownListener.onDropDown(); } } /** * drop down complete, restore view status * * @param secondText display below header text, if null, not display */ public void onDropDownComplete(CharSequence secondText) { if (isDropDownStyle) { setHeaderSecondText(secondText); onDropDownComplete(); } } /** * set header second text * * @param secondText secondText display below header text, if null, not display */ public void setHeaderSecondText(CharSequence secondText) { if (isDropDownStyle) { if (secondText == null) { headerSecondText.setVisibility(View.GONE); } else { headerSecondText.setVisibility(View.VISIBLE); headerSecondText.setText(secondText); } } } /** * drop down complete, restore view status */ public void onDropDownComplete() { if (isDropDownStyle) { setHeaderStatusClickToLoad(); if (headerLayout.getBottom() > 0) { invalidateViews(); setSecondPositionVisible(); } } } /** * on bottom begin, adjust view status */ private void onBottomBegin() { if (isOnBottomStyle) { if (isShowFooterProgressBar) { footerProgressBar.setVisibility(View.VISIBLE); } footerButton.setText(footerLoadingText); footerButton.setEnabled(false); } } /** * on bottom loading, you can call it by manual, but you should manual call onBottomComplete at the same time. */ public void onBottom() { if (isOnBottomStyle && !isOnBottomLoading) { isOnBottomLoading = true; onBottomBegin(); footerButton.performClick(); } } /** * on bottom load complete, restore view status */ public void onBottomComplete() { if (isOnBottomStyle) { if (isShowFooterProgressBar) { footerProgressBar.setVisibility(View.GONE); } if (!hasMore) { footerButton.setText(footerNoMoreText); footerButton.setEnabled(false); if (!isShowFooterWhenNoMore) { removeFooterView(footerLayout); } } else { footerButton.setText(footerDefaultText); footerButton.setEnabled(true); } isOnBottomLoading = false; } } /** * OnDropDownListener, called when header released * * @author Trinea 2012-5-31 */ public interface OnDropDownListener { /** * called when header released */ public void onDropDown(); } /** * set second position visible(index is 1), because first position is header layout */ public void setSecondPositionVisible() { if (getAdapter() != null && getAdapter().getCount() > 0 && getFirstVisiblePosition() == 0) { setSelection(1); } } /** * set whether has more. if hasMore is false, onBottm will not be called when listView scroll to bottom * * @param hasMore */ public void setHasMore(boolean hasMore) { this.hasMore = hasMore; } /** * get whether has more * * @return */ public boolean isHasMore() { return hasMore; } /** * get header layout view * * @return */ public RelativeLayout getHeaderLayout() { return headerLayout; } /** * get footer layout view * * @return */ public RelativeLayout getFooterLayout() { return footerLayout; } /** * get rate about drop down distance and header padding top when drop down * * @return headerPaddingTopRate */ public float getHeaderPaddingTopRate() { return headerPaddingTopRate; } /** * set rate about drop down distance and header padding top when drop down * * @param headerPaddingTopRate */ public void setHeaderPaddingTopRate(float headerPaddingTopRate) { this.headerPaddingTopRate = headerPaddingTopRate; } /** * get min distance which header can release to loading * * @return headerReleaseMinDistance */ public int getHeaderReleaseMinDistance() { return headerReleaseMinDistance; } /** * set min distance which header can release to loading * * @param headerReleaseMinDistance */ public void setHeaderReleaseMinDistance(int headerReleaseMinDistance) { this.headerReleaseMinDistance = headerReleaseMinDistance; } /*** * get header default text, default is R.string.drop_down_list_header_default_text * * @return */ public String getHeaderDefaultText() { return headerDefaultText; } /** * set header default text, default is R.string.drop_down_list_header_default_text * * @param headerDefaultText */ public void setHeaderDefaultText(String headerDefaultText) { this.headerDefaultText = headerDefaultText; if (headerText != null && currentHeaderStatus == HEADER_STATUS_CLICK_TO_LOAD) { headerText.setText(headerDefaultText); } } /** * get header pull text, default is R.string.drop_down_list_header_pull_text * * @return */ public String getHeaderPullText() { return headerPullText; } /** * set header pull text, default is R.string.drop_down_list_header_pull_text * * @param headerPullText */ public void setHeaderPullText(String headerPullText) { this.headerPullText = headerPullText; } /** * get header release text, default is R.string.drop_down_list_header_release_text * * @return */ public String getHeaderReleaseText() { return headerReleaseText; } /** * set header release text, default is R.string.drop_down_list_header_release_text * * @param headerReleaseText */ public void setHeaderReleaseText(String headerReleaseText) { this.headerReleaseText = headerReleaseText; } /** * get header loading text, default is R.string.drop_down_list_header_loading_text * * @return */ public String getHeaderLoadingText() { return headerLoadingText; } /** * set header loading text, default is R.string.drop_down_list_header_loading_text * * @param headerLoadingText */ public void setHeaderLoadingText(String headerLoadingText) { this.headerLoadingText = headerLoadingText; } /** * get footer default text, default is R.string.drop_down_list_footer_default_text * * @return */ public String getFooterDefaultText() { return footerDefaultText; } /** * set footer default text, default is R.string.drop_down_list_footer_default_text * * @param footerDefaultText */ public void setFooterDefaultText(String footerDefaultText) { this.footerDefaultText = footerDefaultText; if (footerButton != null && footerButton.isEnabled()) { footerButton.setText(footerDefaultText); } } /** * get footer loading text, default is R.string.drop_down_list_footer_loading_text * * @return */ public String getFooterLoadingText() { return footerLoadingText; } /** * set footer loading text, default is R.string.drop_down_list_footer_loading_text * * @param footerLoadingText */ public void setFooterLoadingText(String footerLoadingText) { this.footerLoadingText = footerLoadingText; } /** * get footer no more text, default is R.string.drop_down_list_footer_no_more_text * * @return */ public String getFooterNoMoreText() { return footerNoMoreText; } /** * set footer no more text, default is R.string.drop_down_list_footer_no_more_text * * @param footerNoMoreText */ public void setFooterNoMoreText(String footerNoMoreText) { this.footerNoMoreText = footerNoMoreText; } /** status which you can click to load, init satus **/ public static final int HEADER_STATUS_CLICK_TO_LOAD = 1; /** * status which you can drop down and then release to excute onDropDownListener, when height of header layout lower * than a value **/ public static final int HEADER_STATUS_DROP_DOWN_TO_LOAD = 2; /** status which you can release to excute onDropDownListener, when height of header layout higher than a value **/ public static final int HEADER_STATUS_RELEASE_TO_LOAD = 3; /** status which is loading **/ public static final int HEADER_STATUS_LOADING = 4; /** * set header status to {@link #HEADER_STATUS_CLICK_TO_LOAD} */ private void setHeaderStatusClickToLoad() { if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) { resetHeaderPadding(); headerImage.clearAnimation(); headerImage.setVisibility(View.GONE); headerProgressBar.setVisibility(View.GONE); headerText.setText(headerDefaultText); currentHeaderStatus = HEADER_STATUS_CLICK_TO_LOAD; } } /** * set header status to {@link #HEADER_STATUS_DROP_DOWN_TO_LOAD} */ private void setHeaderStatusDropDownToLoad() { if (currentHeaderStatus != HEADER_STATUS_DROP_DOWN_TO_LOAD) { headerImage.setVisibility(View.VISIBLE); if (currentHeaderStatus != HEADER_STATUS_CLICK_TO_LOAD) { headerImage.clearAnimation(); headerImage.startAnimation(reverseFlipAnimation); } headerProgressBar.setVisibility(View.GONE); headerText.setText(headerPullText); if (isVerticalFadingEdgeEnabled()) { setVerticalScrollBarEnabled(false); } currentHeaderStatus = HEADER_STATUS_DROP_DOWN_TO_LOAD; } } /** * set header status to {@link #HEADER_STATUS_RELEASE_TO_LOAD} */ private void setHeaderStatusReleaseToLoad() { if (currentHeaderStatus != HEADER_STATUS_RELEASE_TO_LOAD) { headerImage.setVisibility(View.VISIBLE); headerImage.clearAnimation(); headerImage.startAnimation(flipAnimation); headerProgressBar.setVisibility(View.GONE); headerText.setText(headerReleaseText); currentHeaderStatus = HEADER_STATUS_RELEASE_TO_LOAD; } } /** * set header status to {@link #HEADER_STATUS_LOADING} */ private void setHeaderStatusLoading() { if (currentHeaderStatus != HEADER_STATUS_LOADING) { resetHeaderPadding(); headerImage.setVisibility(View.GONE); headerImage.clearAnimation(); headerProgressBar.setVisibility(View.VISIBLE); headerText.setText(headerLoadingText); currentHeaderStatus = HEADER_STATUS_LOADING; setSelection(0); } } /** * adjust header padding according to motion event * * @param ev */ private void adjustHeaderPadding(MotionEvent ev) { // adjust header padding according to motion event history int pointerCount = ev.getHistorySize(); if (isVerticalFadingEdgeEnabled()) { setVerticalScrollBarEnabled(false); } for (int i = 0; i < pointerCount; i++) { if (currentHeaderStatus == HEADER_STATUS_DROP_DOWN_TO_LOAD || currentHeaderStatus == HEADER_STATUS_RELEASE_TO_LOAD) { headerLayout .setPadding( headerLayout.getPaddingLeft(), (int)(((ev.getHistoricalY(i) - actionDownPointY) - headerOriginalHeight) / headerPaddingTopRate), headerLayout.getPaddingRight(), headerLayout.getPaddingBottom()); } } } /** * reset header padding */ private void resetHeaderPadding() { headerLayout.setPadding(headerLayout.getPaddingLeft(), headerOriginalTopPadding, headerLayout.getPaddingRight(), headerLayout.getPaddingBottom()); } /** * measure header layout * * @param child */ private void measureHeaderLayout(View child) { ViewGroup.LayoutParams p = child.getLayoutParams(); if (p == null) { p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); } int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width); int lpHeight = p.height; int childHeightSpec; if (lpHeight > 0) { childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); } else { childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); } child.measure(childWidthSpec, childHeightSpec); } /** * get attrs * * @param context * @param attrs */ private void getAttrs(Context context, AttributeSet attrs) { TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.drop_down_list_attr); isDropDownStyle = ta.getBoolean(R.styleable.drop_down_list_attr_isDropDownStyle, false); isOnBottomStyle = ta.getBoolean(R.styleable.drop_down_list_attr_isOnBottomStyle, false); isAutoLoadOnBottom = ta.getBoolean(R.styleable.drop_down_list_attr_isAutoLoadOnBottom, false); ta.recycle(); } }
其中的一些重要方法介紹:
public void setOnDropDownListener(OnDropDownListener onDropDownListener)設置下拉的事件
public void onDropDownComplete()和public void onDropDownComplete(CharSequence secondText)恢復下拉狀態,注意onDropDownComplete需要在adapter.notifyDataSetChanged();後面調用
public void setOnBottomListener(OnClickListener onBottomListener)設置滾動到底部的事件
public void onBottomComplete()恢復底部狀態
public void setSecondPositionVisible()
在isDropDownStyle為true情況下,drop down的header layout為ListView position為0的item,所以可能需要調用(如adapter.notifyDataSetChanged())setSecondPositionVisible()設置position為1(即第二個)的item可見。setSelection(0)滾動到的header layout的item。onDropDownComplete()默認已經調用setSecondPositionVisible()
public void setDropDownStyle(boolean isDropDownStyle)同xml中的isDropDownStyle屬性,表示是否為下拉樣式,下拉釋放後執行onDropDownListener
public void setOnBottomStyle(boolean isOnBottomStyle)同xml中isOnBottomStyle屬性,表示滾動到底部執行onBottomListener樣式
public void setAutoLoadOnBottom(boolean isAutoLoadOnBottom)同xml中isAutoLoadOnBottom屬性,表示滾動到底部是否自動執行onBottomListener
public void setHeaderPaddingTopRate(float headerPaddingTopRate)設置header padding top距離與實際下拉距離的比例
public void setHeaderReleaseMinDistance(int headerReleaseMinDistance)設置header可釋放執行onDropDownListener的最小距離
public void setShowFooterProgressBar(boolean isShowFooterProgressBar)設置底部是否顯示progressbar
public void setHasMore(boolean hasMore)set whether has more
public void setHeaderDefaultText(String headerDefaultText)設置header默認文字, default is R.string.drop_down_list_header_default_text
public void setHeaderPullText(String headerPullText)設置header下拉提示文字, default is R.string.drop_down_list_header_pull_text
public void setHeaderReleaseText(String headerReleaseText)設置header可釋放提示文字, default is R.string.drop_down_list_header_release_text
public void setHeaderLoadingText(String headerLoadingText)設置header加載中提示文字, default is R.string.drop_down_list_header_loading_text
public void setFooterDefaultText(String footerDefaultText)設置footer默認文字, default is R.string.drop_down_list_footer_default_text
public void setFooterLoadingText(String footerLoadingText)設置footer加載中提示文字, default is R.string.drop_down_list_footer_loading_text
public void setFooterNoMoreText(String footerNoMoreText)設置footer沒有更多提示文字, default is R.string.drop_down_list_footer_no_more_text
public void setHeaderSecondText(CharSequence secondText)設置header第二部分文字, default is null
Android Studio導入Eclipse項目有兩種方法,一種是直接把Eclipse項目導入Android Studio,另一種是在Eclipse項目裡面進行轉換,然
1、概述 相信做Android開發的寫得最多的就是ListView,GridView的適配器吧,記得以前開發一同事開發項目,一個項目下來基本就一直在寫Lis
最近,看了不少Android內核分析的書籍、文章及Android源程序。感覺自己對Android Binder的工作機制算是有了個徹底的理解。 但是,自己是花了
指紋識別這個名詞聽起來並不陌生,但是實際開發過程中用得並不多。Google從Android6.0(api23)開始才提供標准指紋識別支持,並對外提供指紋識別相關的接口。本