Android 自定義水平滾動的容器
public class HorizontalScrollView extends ViewGroup {
//手勢
private GestureDetector mGestureDetector;
private HorizontalScroller mScroller;
private int curID;
//快速滑動
private boolean isFlying;
//--回撥函式-------------------------------------
private OnChangeListener mListener;
public void setOnChangeListener(OnChangeListener listener) {
if (listener != null) {
mListener = listener;
}
}
public interface OnChangeListener{
void move2dest(int curID);
}
public HorizontalScrollView(Context context) {
this(context, null);
}
public HorizontalScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public HorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mScroller = new HorizontalScroller();
isFlying = false;
initGesture(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
// 模向移動,
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
//給水平方向的每個view定位
view.layout(i * getWidth(), 0, getWidth() + i * getWidth(), getHeight());
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
for (int i = 0; i < getChildCount(); i++) {
View view = getChildAt(i);
view.measure(widthMeasureSpec, heightMeasureSpec);
}
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isFlying) {
move2dest();
}
isFlying = false;
break;
case MotionEvent.ACTION_MOVE:
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
return true;
}
public void move2dest() {
//
int destID = (getScrollX() + getWidth() / 2) / getWidth();
move2dest(destID);
}
public void move2dest(int destID) {
curID = destID;
if (destID > getChildCount() - 1) {
destID = getChildCount() - 1;
}
if (mListener != null) {
mListener.move2dest(curID);
}
int distance = (int) (destID * getWidth() - getScrollX());
// scrollBy(distance, 0);
mScroller.startScroll(getScrollX(), getScrollY(), distance, 0);
invalidate();
}
/**
* invalidate()此方法會觸發下面的方法
*/
@Override
public void computeScroll() {
// 如果存在偏移,就不斷重新整理
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), 0);
invalidate();
}
super.computeScroll();
}
private void initGesture(Context context) {
mGestureDetector = new GestureDetector(context, new OnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
@Override
public void onShowPress(MotionEvent e) {
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
scrollBy((int) distanceX, 0);
return false;
}
@Override
public void onLongPress(MotionEvent e) {
}
@Override
/**
* 快速滑動時
*/
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
isFlying = true;
if (curID > 0 && velocityX > 0) {// 表示向左移
move2dest(curID - 1);
} else if (curID < getChildCount() && velocityX < 0) {
move2dest(curID + 1);// 向右
} else {
move2dest();// 移到原位
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return false;
}
});
}
}
/**
* 位移計算工具類
*
* @author chenlin
*
*/
public class HorizontalScroller {
private int startX;
private int startY;
private int distanceX;
private int distanceY;
private int currentX;
private int currentY;
private long startTime;
private long duration = 1000L;
private boolean isFinish;
/**
*
* @param scrollX
* x座標
* @param scrollY
* y座標
* @param distanceX
* X方向移動的距離
* @param distanceY
* y方向移動的距離
*/
public void startScroll(int scrollX, int scrollY, int distanceX, int distanceY) {
startX = scrollX;
startY = scrollY;
this.distanceX = distanceX;
this.distanceY = distanceY;
isFinish = false;
startTime = SystemClock.uptimeMillis();
}
/**
* 計算偏移量,
*
* @return true 還在移動 false:移動已經停止
*/
public boolean computeScrollOffset() {
if (isFinish) {
return false;
}
long timePassed = SystemClock.uptimeMillis() - startTime;
if (timePassed < duration) {
currentX = (int) (startX + distanceX * timePassed / duration);
currentY = (int) (startY + distanceY * timePassed / duration);
System.out.println("currentX:::" + currentX);
} else if (timePassed >= duration) {
currentX = startX + distanceX;
currentY = startY + distanceY;
isFinish = true;
}
return true;
}
public int getCurrX() {
return currentX;
}
public void setCurrentX(int currentX) {
this.currentX = currentX;
}
public int getCurrentY() {
return currentY;
}
public void setCurrentY(int currentY) {
this.currentY = currentY;
}
}
使用方法
public class ScrollActivity extends Activity implements OnCheckedChangeListener, OnChangeListener {
private int[] ids = { R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4, R.drawable.a5, R.drawable.a6 };
private HorizontalScrollView mView;
private LinearLayout mLayout;
private RadioGroup mGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_myscrollview);
init();
}
private void init() {
mLayout = (LinearLayout) findViewById(R.id.body_layout);
mGroup = (RadioGroup) findViewById(R.id.radiogroup);
mView = new HorizontalScrollView(this);
for (int i = 0; i < ids.length; i++) {
ImageView imageView = new ImageView(this);
imageView.setBackgroundResource(ids[i]);
mView.addView(imageView);
}
mLayout.addView(mView);
// 隨便新增一個view
View view = getLayoutInflater().inflate(R.layout.activity_progressview, null);
mView.addView(view, 3);
for (int i = 0; i < mView.getChildCount(); i++) {
RadioButton radioButton = new RadioButton(this);
// 設定id的編號
radioButton.setId(i);
mGroup.setOrientation(LinearLayout.HORIZONTAL);
mGroup.addView(radioButton);
if (i == 0) {
radioButton.setChecked(true);
}
}
mGroup.setOnCheckedChangeListener(this);
mView.setOnChangeListener(this);
}
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
mView.move2dest(checkedId);
}
@Override
public void move2dest(int curID) {
RadioButton radioButton = (RadioButton) mGroup.getChildAt(curID);
radioButton.setChecked(true);
}
}
佈局檔案
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RadioGroup
android:id="@+id/radiogroup"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</RadioGroup>
<LinearLayout
android:id="@+id/body_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
</LinearLayout>
</LinearLayout>
相關推薦
Android 自定義水平滾動的容器
public class HorizontalScrollView extends ViewGroup { //手勢 private GestureDetector mGestureDetector; private Horizonta
android自定義水平虛線View
import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; import android.graphics.DashPathEffe
android 自定義實現滾動View:WheelView
專案中用到一個比較覺得不錯的控制元件:WheelView,即上下滾動View。它是繼承ScrollView實現,在Android各版本上的效果都是如下:也許在git上有許多這樣功能的控制元件,但個人認為這個控制元件實現的方式簡單,比較讓人容易理解,對自定義控制元件的實現有借
Android自定義水平日曆控制元件
ZzHorizontalCalenderView A horizontal and scrollable CalenderView. Gradle: compile 'me.zhouzhu
Android 自定義橫向滾動條聯動進階版
前一段時間寫了一個自定義橫向滾動條,感覺效果不怎樣好( )。又開始改善結構,使用setScrollView寫了一個聯動進階版。標題的滾動條和內容資料item資料滾動條都可以聯動滾動。豎向是兩個listview,但是是使用全域性的豎向滾動條來滾動。所以橫向與豎向、單擊、長按
Android 自定義含有滾動選擇器的對話方塊
1.概述 使用LIstView和Dialog實 自定義含有滾動選擇器的對話方塊,可以設定顯示字型的不同顏色,設定字型透明度,設定大小,設定顯示多少項。下面給兩個效果: 顯示7項,字型透明度和大小改變 顯示5項,字型顏色和大小改變
Android 自定義控件之繼承ViewGroup創建新容器
多個 osi count() arc ron min ole tro 定位 歡迎大家來學習本節內容,前幾節我們已經學習了其他幾種自定義控件,分別是Andriod 自定義控件之音頻條及 Andriod 自定義控件之創建可以復用的組合控件還沒有學習的同學請先去學習下,因為本節將
Android 自定義跑馬燈 實現超長文字,滾動完當前在繼續切換下一條
1 前言 最近專案上有一個跑馬燈的需求。 需求: 無限滾動,可以自動切換下一條 如果當前的文字超過一屏,則滾動完當前再切換下一條 第一點很簡單,但是第二點就比較蛋疼了,看了網上很多輪子都沒有太合適的,於是自己寫了一個。 記錄總結一下Android 跑馬燈的
Android自定義控制元件實戰——滾動選擇器PickerView
手機裡設定鬧鐘需要選擇時間,那個選擇時間的控制元件就是滾動選擇器,前幾天用手機刷了MIUI,發現自帶的那個時間選擇器效果挺好看的,於是就自己仿寫了一個,權當練手。先來看效果:
我的Android進階之旅------>Android自定義View來實現解析lrc歌詞並同步滾動、上下拖動、縮放歌詞的功能
前言 最近有個專案有關於播放音樂時候,關於歌詞有以下幾個功能: 1、實現歌詞同步滾動的功能,即歌曲播放到哪句歌詞,就高亮地顯示出正在播放的這個歌詞; 2、實現上下拖動歌詞時候,可以拖動播放器的進度。即可以不停地上下拖動歌詞,
Android自定義View,高仿QQ音樂歌詞滾動控制元件!
最近在以QQ音樂為樣板做一個手機音樂播放器,原始碼下篇博文放出。今天我想聊的是這個QQ音樂播放器中歌詞顯示控制元件的問題,和小夥伴們一起來探討怎麼實現這個歌詞滾動的效果。OK,廢話不多說,先來看看效果圖:好,接下來我們就來看看怎麼實現這樣一個效果。本文主要包括如下幾方面內容:
android 自定義View(二) 自定義屬性和帶滾動的View
自定義View的屬性 在上一章中講了那麼多,這一章開始就進行實戰了。首先來一發自定義View屬性的demo。 自定義View屬性的步驟分為以下3步。 (1) 新建一個attrs.xml檔案,在這個資原始檔中定義我們需要的屬性。 (2)新建一個自定義的
Android自定義View(LineBreakLayout-自動換行的標籤容器)
最近一段時間比較忙,都沒有時間更新部落格,今天公司的事情忙完得空,繼續為我的自定義控制元件系列部落格添磚加瓦。本篇部落格講解的是標籤自動換行的佈局容器,正好前一陣子有個專案中需要,想了想沒什麼難度就自己弄了。而自定義控制元件系列文章中對於自定義ViewGro
Android自定義半圓形圓盤滾動選擇器View
前段時間公司專案要求做一個特效的滑動選擇器,效果如下圖的樣子: 功能要求:兩邊的半圓形轉盤可以轉動,轉盤上的圖示也一起滾動,藍紅色圖示指著的小圖示變成高亮選中狀態。 第一眼看到這個需求就想到這個必須要用自定義控制元件來做才
Android自定義View來實現解析lrc歌詞同步滾動、上下拖動、縮放歌詞等功能
http://blog.csdn.net/ouyang_peng/article/details/50813419 前言 最近有個專案有關於播放音樂時候,關於歌詞有以下幾個功能: 1、實現歌詞同步滾動的功能,即歌曲播放到哪句
Android 自定義View之Scroller處理滾動工具類詳解
public class ScrollerLayout extends ViewGroup { /** * 用於完成滾動操作的例項 */ private Scroller mScroller; /** * 判定為拖動的最小移動畫素數 */
Android自定義View——仿1號店垂直滾動廣告條實現
效果圖 原理分析 整個過程都是基於座標Y的增加和交換進行處理的,Y值都會一直增加到endY,然後進行交換邏輯 實現步驟 1、初始化變數 由於1號店是兩句話的滾動,所以我們也是使用兩句話來實現的 public class VerTe
Android自定義TextView實現文字自動滾動
效果:迴圈滾動,類似廣告條思路:開啟定時器重新整理繪製文字的位置即可達到效果。步驟1:新建ScrollTextView類繼承自TextView。程式碼如下:public class ScrollTextView extends TextView { private
Android:自定義滾動邊緣(EdgeEffect)效果
原文 0 Android可滾動控制元件(GridView、ListView、ScrollView等)當用戶滾動到頭的時候會有個邊緣反饋效果,在4.0上預設為Holo藍色效果。 如果您的App自定義了主題顏色,比如Google Play Music的橘黃色。 那麼在
Android之自定義橫向滾動選單
##前言 已經好長時間沒更新部落格了,今天給大家帶來一個橫向滾動的選單,用的是HorizontalScrollView,但HorizontalScrollView不能在滾動時定位到某個選單,因此監聽了onScrollChanged方法,程式碼比較簡單,大家看程