中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何進行封裝橫向滾動View

發布時間:2022-01-07 22:04:50 來源:億速云 閱讀:157 作者:柒染 欄目:移動開發

本篇文章為大家展示了如何進行封裝橫向滾動View,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

首先是基礎只是介紹:

1.Scroller

   這個類主要是支持view控件滑動,其實android很多可滑動的控件里面默認隱藏的就是這個類。而且這個類沒有進行實際的視圖移動,當調用它的 startScroll()方法實際上只是為了在父類調用computeScroll()方法前開始動畫,也就是說這個類實際上就是相當于一個代理,只是為了給后面視圖移動添加一些動畫效果。所以單獨調用startScroll()而不重寫computeScroll()方法是不會看到任何效果的。這兩者必須配合使用,才能有移動的時候的動畫效果。

其中Scroller.computeScrollOffset()方法是判斷scroller的移動動畫是否完成,當你調用startScroll()方法的時候這個方法返回的值一直都為true,如果采用其它方式移動視圖比如:scrollTo()或 scrollBy時那么這個方法返回false。

現在來講講startScroll(int startX, int startY, int dx, int dy, int duration)方法的四個參數的意思:

  • startX表示當前視圖的x坐標值

  • startY表示當前視圖的y坐標值

  • dx表示在當前視圖的x坐標基礎上橫向移動的距離

  • dy表示在當前視圖的y坐標基礎上縱向移動的距離

  • duration表示視圖移動的操作在多少時間內執行完場,也就是動畫的持續時間(單位:毫秒)


2.ViewGroup

這是個特殊的View,它繼承于Android.view.View,它的功能就是裝載和管理下一層的View對象或ViewGroup對象,也就說他是一個容納其它元素的的容器。

下面我們來分別分析我們要使用這5個類的那些方法,首先我們來看ViewGroup類,因為我們自定義的控件就是繼承至這個類,我們會重寫這個類中的5個方法如下:

1.onLayout(boolean changed, int l, int t, int r, int b)

這個方法是在onMeasure()方法執行后調用,作用是父類為子類在屏幕上分配實際的寬度和高度。里面的四個參數分別表示,布局是否發生改變,布局左 上右下的邊距。

2.onMeasure(int widthMeasureSpec, int heightMeasureSpec)

這個方法在控件的父元素正要放置它的子控件時調用。然后傳入兩個參數——widthMeasureSpec和 heightMeasureSpec。它們指明控件可獲得的空間以及關于這個空間描述的元數據。比返回一個結果要好的方法是你傳遞View的高度和寬度到 setMeasuredDimension方法里。widthMeasureSpec和heightMeasureSpec參數在它們使用之前,首先要做 的是使用MeasureSpec類的靜態方法getMode和getSize來譯解。一個MeasureSpec包含一個尺寸和模式。

有三種可能的模式:

  • UNSPECIFIED:父布局沒有給子布局任何限制,子布局可以任意大小。

  • EXACTLY:父布局決定子布局的確切大小。不論子布局多大,它都必須限制在這個界限里。(當布局定義為一個固定像素或者fill_parent時就是EXACTLY模式)

  • AT_MOST:子布局可以根據自己的大小選擇任意大小。(當布局定義為wrap_content時就是AT_MOST模式)

3.computeScroll()

這個方法主要是父類要求它的子類滾動的時候調用。在這個方法里,我們可以實現 view的滾動操作,這里滾動并不是view的滾動而是布局的滾動。當調用scroller的startScroll()方法后父類就會調用這個方法實現 滾動視圖滾動操作。

4.onTouchEvent(MotionEvent event)

處理傳遞到view 的手勢事件。手勢事件類型包括ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL等事件。Layout里 的onTouch默認返回值是false, View里的onTouch默認返回值是true,當我們手指點擊屏幕時候,先調用ACTION_DOWN事件,當onTouch里返回值是true的時 候,onTouch回繼續調用ACTION_UP事件,如果onTouch里返回值是false,那么onTouch只會調用ACTION_DOWN而不調用ACTION_UP.

5.onInterceptTouchEvent(MotionEvent ev)

用于攔截手勢事件的,每個手勢事件都會先調用這個方法。Layout里的onInterceptTouchEvent默認返回值是false,這樣touch事件會傳遞到View控件。

6.Invalidate()和PostInvalidate(),這兩個方法作用都一樣,就是呼叫ui線程重新繪制 界面也就是刷新界面。那為什么要兩個方法呢,這是因為android是多線程應用,大家應該都知道在非UI線程中是不能直接操作界面控件的,所以第2個方 法就幫助大家在子線程中刷行界面,第一個方法則是在UI線程中刷新界面。

7.getX()和getRawX()這兩個方法的左右都是獲取當前點在屏幕上的坐標,getX()是獲取當前點相對于當前視圖左上角的坐標,getRawX()則是獲取當前點相對于手機屏幕左上角的坐標。

封裝View的代碼

package com.xc.view;
import java.util.ArrayList;
import java.util.List;
import com.xc.view.XCSlideListView.XCSlideView;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
    private XCSlideListView list;
    private List<String> items;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initData();
        initViews();
        initActions();
    }
    private void initData() {
        items = new ArrayList<String>();
        for (int i = 0; i < 20; i++) {
            items.add("SlideView" + i);
        }
    }
    private void initViews() {
        setContentView(R.layout.main);
        list = (XCSlideListView) findViewById(R.id.list);
        list.setAdapter(new MyAdapter2(this, items));
    }
    private void initActions() {
    }
    public class MyAdapter2 extends BaseAdapter {
        private Context context;
        private List<String> items;
        private LayoutInflater inflater;
        public MyAdapter2(Context context, List<String> items) {
            this.context = context;
            this.items = items;
            this.inflater = LayoutInflater.from(context);
        }
        @Override
        public int getCount() {
            return items.size();
        }
        @Override
        public Object getItem(int position) {
            return items.get(position);
        }
        @Override
        public long getItemId(int position) {
            return position;
        }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent) {
            final String item = items.get(position);
            MyAdapterHolder holder;
            XCSlideListView.XCSlideView slideView = (XCSlideView) convertView;
            if (slideView == null) {
                slideView = list.new XCSlideView(context);
                slideView.addShowView(View.inflate(context, R.layout.slideview_show, null));
                slideView.addPopupView(View.inflate(context, R.layout.slideview_popup, null), 120);
                holder = new MyAdapterHolder();
                holder.setText((TextView) slideView.findViewById(R.id.text));
                holder.setDelete((TextView) slideView.findViewById(R.id.delete));
                slideView.setTag(holder);
            } else {
                holder = (MyAdapterHolder) slideView.getTag();
            }
            holder.getText().setText(item);
            holder.getDelete().setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    Toast.makeText(context, "delete!-->" + position, Toast.LENGTH_LONG).show();
                }
            });
            return slideView;
        }
    }
}
package com.xc.view;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.Scroller;
public class XCSlideListView extends ListView {
    private final String TAG = "XCSlideListView";
    private XCSlideView currentView;
    private Context context;
    public XCSlideListView(Context context) {
        this(context, null);
    }
    public XCSlideListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        this.context = context;
    }
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        int x = (int) ev.getX();
        int y = (int) ev.getY();
        int position = pointToPosition(x, y);
        if (position != INVALID_POSITION && ev.getAction() == MotionEvent.ACTION_DOWN) {
            int firstVisiblePosition = getFirstVisiblePosition();
            XCSlideView slideView = (XCSlideView) getChildAt(position - firstVisiblePosition);
            if (currentView != null && currentView != slideView) {
                Log.e(TAG, "currentView != slideView");
                currentView.shrink(true);
            }
            currentView = slideView;
        }
        if (currentView != null) {
            currentView.onRequireTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }
    public class XCSlideView extends LinearLayout {
        private Scroller mScroller;
        private int slideWidth = 0;
        private int mLastX = 0;
        private int mLastY = 0;
        private boolean isRight = false;
        private static final int TAN = 2;
        public XCSlideView(Context context) {
            this(context, null);
        }
        public XCSlideView(Context context, AttributeSet attrs) {
            super(context, attrs);
            setOrientation(LinearLayout.HORIZONTAL);
            mScroller = new Scroller(context);
        }
        public void addShowView(View view) {
            addView(view, LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        }
        public void addPopupView(View view, int width) {
            slideWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, width, getResources().getDisplayMetrics()));
            addView(view, slideWidth, LayoutParams.FILL_PARENT);
        }
        @Override
        public Object getTag() {
            shrink(false);
            return super.getTag();
        }
        public void onRequireTouchEvent(MotionEvent event) {
            if (slideWidth == 0)
                return;
            int x = (int) event.getX();
            int y = (int) event.getY();
            int scrollX = getScrollX();
            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN: {
                if (!mScroller.isFinished()) {
                    mScroller.abortAnimation();
                }
                break;
            }
            case MotionEvent.ACTION_MOVE: {
                int deltaX = x - mLastX;
                int deltaY = y - mLastY;
                if (deltaX > 0) {
                    isRight = true;
                } else {
                    isRight = false;
                }
                if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
                    break;
                }
                int newScrollX = scrollX - deltaX;
                if (deltaX != 0) {
                    if (newScrollX < 0) {
                        newScrollX = 0;
                    } else if (newScrollX > slideWidth) {
                        newScrollX = slideWidth;
                    }
                    this.scrollTo(newScrollX, 0);
                }
                break;
            }
            case MotionEvent.ACTION_UP: {
                int newScrollX = 0;
                if (scrollX - (isRight ? slideWidth * 0.75 : slideWidth * 0.25) > 0) {
                    newScrollX = slideWidth;
                }
                this.smoothScrollTo(newScrollX, 0);
                break;
            }
            default:
                break;
            }
            mLastX = x;
            mLastY = y;
        }
        public void shrink(boolean haveAnim) {
            if (getScrollX() != 0) {
                if (haveAnim) {
                    this.smoothScrollTo(0, 0);
                } else {
                    this.scrollTo(0, 0);
                }
            }
        }
        // 緩慢滾動到指定位置
        private void smoothScrollTo(int destX, int destY) {
            int scrollX = getScrollX();
            int delta = destX - scrollX;
            // 最后一個參數:動畫的持續時間  Math.abs:絕對值
            mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);
            invalidate();
        }
        @Override
        public void computeScroll() {
            Log.e("computeScroll", "x" + mScroller.getCurrX() + "--y--" + mScroller.getCurrY());
            // 是判斷scroller的移動動畫是否完成
            // 當你調用startScroll()方法的時候這個方法返回的值一直都為true,如果采用其它方式移動視圖比如:scrollTo()或
            // scrollBy時那么這個方法返回false。
            if (mScroller.computeScrollOffset()) {
                scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                postInvalidate();
            }
        }
    }
}

效果圖:

如何進行封裝橫向滾動View

如何進行封裝橫向滾動View


上述內容就是如何進行封裝橫向滾動View,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

宁陵县| 夏河县| 台湾省| 万州区| 芮城县| 西和县| 博湖县| 班玛县| 乐山市| 正镶白旗| SHOW| 伊川县| 滦平县| 莒南县| 银川市| 临泉县| 陆川县| 东丽区| 古田县| 武穴市| 云南省| 台北市| 崇礼县| 景宁| 务川| 虎林市| 文安县| 新闻| 平果县| 贵溪市| 成安县| 融水| 营山县| 睢宁县| 贵南县| 东至县| 沽源县| 饶平县| 故城县| 樟树市| 英德市|