上個(gè)章節(jié)我們使用MPAndroidChart完成了一個(gè)靜態(tài)的K線面板,這個(gè)章節(jié)我們將介紹如何在K線面板中處理用戶的手勢操作。
處理用戶的手勢操作
在K線面板中,需要處理的手勢操作主要包括:
1.單次點(diǎn)擊(加載失敗時(shí)重新加載)
2.勻速滑動(dòng)(K線圖左右滾動(dòng))
3.快速滑動(dòng)(前后切換股票)
4.長按后滑動(dòng)(高亮顯示被選中的數(shù)據(jù))
如果你對(duì)上述手勢操作不是太了解,可以下載apk體驗(yàn)一下 apk下載地址
1.設(shè)計(jì)思路
寫代碼之前我們首先來談一下設(shè)計(jì)思路,上述的手勢操作并不復(fù)雜,但是結(jié)合到一起容易引起重疊,造成不好的用戶體驗(yàn)。所以這次我們的設(shè)計(jì)思路是:
首先判斷長按事件,在長按狀態(tài)下被選中數(shù)據(jù)高亮顯示;
在非長按狀態(tài)下,通過判斷滑動(dòng)速率和滑動(dòng)時(shí)間區(qū)分快速滑動(dòng)和勻速滑動(dòng);
在勻速滑動(dòng)狀態(tài)下,每滑動(dòng)一個(gè)單位都重新獲取手指的位置。
2.繼承CandleStickChart類
開始編寫代碼,我們首先繼承CandleStickChart類,CandleStickChart是MPAndroidChart提供的用于展示K線圖的控件,在上個(gè)章節(jié)實(shí)現(xiàn)靜態(tài)K線圖的時(shí)候我們有用到:
public class TsCandleStickChart extends CandleStickChart {
public TsCandleStickChart(Context context) {
super(context);
}
public TsCandleStickChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TsCandleStickChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
}
創(chuàng)建OnTsGestureListener接口:
public interface OnTsGestureListener {
/**
* 單次點(diǎn)擊
*/
void onChartSingleTapped();
/**
* 多次點(diǎn)擊
*/
void onChartDoubleTapped();
/**
* 快速滑動(dòng)
* @param direction 滑動(dòng)方向
*/
void onChartFastSlide(int direction);
/**
* 勻速滑動(dòng)
* @param direction 滑動(dòng)方向
*/
void onChartSlowSlide(int direction);
/**
* 長按后滑動(dòng)
* @param position 當(dāng)前位置
*/
void onChartSlideLongClick(int position);
}
3.長按后滑動(dòng)
按照最初的構(gòu)思,我們先區(qū)分將長按事件跟非長按事件,這里我們復(fù)寫setOnChartGestureListener,在onChartLongPressed中處理長按事件,其中變量isLongPressed用來記錄當(dāng)前是否處于長按狀態(tài):
@Override
public void onChartLongPressed(MotionEvent me) {
//為了避免滑動(dòng)事件與高亮?xí)r間沖突,高亮事件只在長按后顯示,優(yōu)先消費(fèi)滑動(dòng)事件
if (me.getFlags() == 0) {
isLongPressed = true;
setHighlightPerDragEnabled(true);
highlightValue(getHighlightByTouchPoint(me.getX(), me.getY()).getXIndex(),0);
}
}
接著我們復(fù)寫setOnChartValueSelectedListener來獲取當(dāng)前被選中的數(shù)據(jù),當(dāng)前處于長按狀態(tài)時(shí),將被選中的數(shù)據(jù)高亮顯示:
setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry e, int dataSetIndex, Highlight h) {
if (isLongPressed && onTsGestureListener != null) {
onTsGestureListener.onChartSlideLongClick(e.getXIndex());
}
}
});
4.快速滑動(dòng)
在非長按狀態(tài)下,我們用滑動(dòng)時(shí)間和滑動(dòng)速率來區(qū)分快速滑動(dòng)和勻速滑動(dòng):
@Override
public void onChartFling(MotionEvent me1, MotionEvent me2, float velocityX, float velocityY) {
if (!isLongPressed && onTsGestureListener != null) {
if((me2.getEventTime() - me2.getDownTime()) < FLIP_PERIOD){
if (velocityX > FLIP_DISTANCE) {
onTsGestureListener.onChartFastSlide(-1);
} else if (velocityX < -FLIP_DISTANCE) {
onTsGestureListener.onChartFastSlide(1);
}
}
}
}
5.勻速滑動(dòng)
這里使用setOnTouchListener實(shí)現(xiàn)勻速滑動(dòng),對(duì)于onTouchListener想必大家都比較熟悉,手指按下時(shí)記錄點(diǎn)擊的位置:
case MotionEvent.ACTION_DOWN:
currentDownindex = motionEvent.getRawX();
break;
每當(dāng)用戶滑動(dòng)的距離達(dá)到默認(rèn)值時(shí),我們會(huì)通知接口用戶滑動(dòng)了一個(gè)單位。
實(shí)際操作中用戶滑動(dòng)的距離可能會(huì)超過默認(rèn)值,超過的情況也統(tǒng)一按照滑動(dòng)了一個(gè)單位進(jìn)行處理,這樣可以使得滑動(dòng)過程更加平順:
case MotionEvent.ACTION_MOVE:
if(!isLongPressed && onTsGestureListener != null){
if((motionEvent.getEventTime() - motionEvent.getDownTime()) > SLIDE_PERIOD){
float rawX = motionEvent.getRawX();
int distance = (int)(rawX - currentDownindex);
if(Math.abs(distance) > INSERTDATAPIXELS){
currentDownindex = rawX;
int num = distance/INSERTDATAPIXELS;
int change = num > 0?1:-1;
onTsGestureListener.onChartSlowSlide(change);
}
}
}
break;
編寫完TsCandleStickChart類后,我們在布局中使用TsCandleStickChart代替之前的CandleStickChart:
<com.system.ts.android.utils.view.TsCandleStickChart
android:id="@+id/ts_candler_chart"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/top_line"
android:layout_above="@+id/rl_bottom_view" />
最后,在Activity中調(diào)用setOnTsGestureListener方法實(shí)現(xiàn)上述的手勢操作:
@Bind(R.id.ts_candler_chart)
TsCandleStickChart mChart;
mChart.setOnTsGestureListener(new OnTsGestureListener() {
@Override
public void onChartDoubleTapped() { //多次點(diǎn)擊
if (loadError) {
String tkCode = SharedPreferencesUtils.getCurrentTkCode();
loadStickData(tkCode, true);
}
}
@Override
public void onChartFastSlide(int direction) { //快速滑動(dòng)
String code = TkCodeUtils.getNextCode(SharedPreferencesUtils.getCurrentTkCode(), direction);
if (!TextUtils.isEmpty(code)) {
loadStickData(code, true);
}
}
@Override
public void onChartSlowSlide(int direction) { //勻速滑動(dòng)
onTranslateUI(direction);
}
@Override
public void onChartSlideLongClick(int position) { //長按后滑動(dòng)
updateTopView(position);
}
});
到此為止,我們已經(jīng)實(shí)現(xiàn)了K線面板中的各種手勢操作,下個(gè)章節(jié) MPAndroidChart實(shí)現(xiàn)K線面板(三)