Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android自定義視圖之類似淘寶商品詳情

android自定義視圖之類似淘寶商品詳情

編輯:關於Android編程

公司項目需求,需要一個類似淘寶詳情一樣的頁面,但又有所不同,於是自己寫了一個。本文只是提供一種思路,控件的普適性還不夠,希望讀者能自行修改。

老規矩,先上一個項目原圖吧:

\

\

本文只是上圖右邊部分效果。demo也只有右邊部分。不過這個控件的代碼是一樣的。

直接貼代碼

TwoPageLayout.java:

 

/**
 * Created by paulz on 2016/9/21.
 */
public class TwoPageLayout extends ViewGroup {
    Context context;
    View pageOne;
    View pageTwo;
    private int mTouchSlop;
    private int mPageChangeLimit;
    private int currentPage;
    private boolean isIntercept;

    OnPageChangeListener mOnPageChangeListener;
    public OverScroller scroller;


    public TwoPageLayout(Context context) {
        super(context);
        init(context);
    }

    public TwoPageLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public TwoPageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);

    }


    private void init(Context context){
        this.context=context;
        final ViewConfiguration vc = ViewConfiguration.get(context);
        mTouchSlop=vc.getScaledTouchSlop();
        //滑動翻頁的臨界值
        mPageChangeLimit=150;
        scroller=new OverScroller(getContext());
    }


    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                downX=ev.getX();
                downY=ev.getY();
                isIntercept=touchChildToTop();
                break;
            case MotionEvent.ACTION_MOVE:
                if(!isIntercept)return false;
                if(Math.abs(downY-ev.getY())>mTouchSlop){
                    //滑動開始
                    if(currentPage==1&&downY-ev.getY()<0){
                        isScrolling=true;
                        return true;
                    }else if(currentPage==0&&downY-ev.getY()>0){
                        isScrolling=true;
                        return true;
                    }
                }
                break;
            case MotionEvent.ACTION_UP:
                isScrolling=false;
                break;
            case MotionEvent.ACTION_CANCEL:
                isScrolling=false;
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        measureChildren(widthMeasureSpec,heightMeasureSpec);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if(pageOne==null){
            pageOne=getChildAt(0);
        }
        if(pageTwo==null){
            pageTwo=getChildAt(1);
        }
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
            if (pageOne!=null&&pageOne.getVisibility() != GONE) {
                pageOne.layout(0+getPaddingLeft(), 0+getPaddingTop(), getWidth()-getPaddingRight(), getHeight()-getPaddingBottom());
            }
            if (pageTwo!=null&&pageTwo.getVisibility() != GONE) {
                pageTwo.layout(0+getPaddingLeft(), getHeight(), getWidth()-getPaddingRight(), getHeight()+getHeight()-getPaddingBottom());
            }
    }

    private float downX;
    private float downY;
    private boolean isScrolling;

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                downX=event.getX();
                downY=event.getY();
                isIntercept=touchChildToTop();
                break;
            case MotionEvent.ACTION_MOVE:
                if(currentPage==1&&downY-event.getY()<0){
                    isScrolling=true;
                }else if(currentPage==0&&downY-event.getY()>0){
                    isScrolling=true;
                }else {
                    isScrolling=false;
                }
                if(currentPage==1&&!isIntercept){
                    isScrolling=false;
                }
                if(isScrolling){
                    if(currentPage==0&&downY-event.getY()>0){//整體向上偏移,翻到下一頁
                        scrollTo(0,(int)(downY-event.getY()));
                    }else if(currentPage==1&&downY-event.getY()<0){//翻到上一頁
                        scrollTo(0,getHeight()+(int)(downY-event.getY()));
                    }else {
                        return false;
                    }
                }else {
                    return false;
                }
                break;
            case MotionEvent.ACTION_UP:
                if(isScrolling){
                    if(currentPage==0){
                        if((downY-event.getY()>mPageChangeLimit)){
                            scroller.startScroll(0,getScrollY(),0,getHeight()-getScrollY(),500);
                            invalidate();
//                            scrollTo(0,getHeight());
                            currentPage=1;
                            if(mOnPageChangeListener!=null){
                                mOnPageChangeListener.onPageChanged(currentPage,pageTwo,true);
                            }
                        }else {
                            scroller.startScroll(0,getScrollY(),0,-getScrollY(),300);
                            invalidate();
//                            scrollTo(0,0);
                        }
                    }else {
                        if(Math.abs(downY-event.getY())>mPageChangeLimit){
                            scroller.startScroll(0,getScrollY(),0,-getScrollY(),500);
                            invalidate();
                            if(mOnPageChangeListener!=null){
                                mOnPageChangeListener.onPageChanged(currentPage,pageOne,true);
                            }
                            currentPage=0;
                        }else {
                            scroller.startScroll(0,getScrollY(),0,pageOne.getHeight()-getScrollY(),300);
                            invalidate();
//                            scrollTo(0,pageOne.getHeight());
                        }
                    }
                    isScrolling=false;
                }
                isIntercept=false;
                break;
            case MotionEvent.ACTION_CANCEL:
                isScrolling=false;
                scrollTo(0,0);
                isIntercept=false;
                break;
        }
        return true;
    }

    private WebView childOne;
    private ListView childTwo;
    private int curTouchChild;

    public void setScrollerChildren(WebView childOne, ListView childTwo){
        this.childOne=childOne;
        this.childTwo=childTwo;
        curTouchChild=0;
    }

    public void changeCurScrollerChild(int i){
        curTouchChild=i;
    }


    //實現第二頁中包含可滑動控件時是否滑到頂部
    //從而決定本控件是否處理touch事件。
    private boolean touchChildToTop(){
        if(curTouchChild==0&&childOne!=null&&childOne.getScrollY()<=0){
            return true;
        }else if(curTouchChild==1&&childTwo!=null&&childTwo.getScrollY()<=0&&childTwo.getFirstVisiblePosition()==0){
            return true;
        }else {
            return false;
        }
    }


    @Override
    public void computeScroll() {
        if(scroller.computeScrollOffset()){
            scrollTo(0,scroller.getCurrY());
            postInvalidate();
        }
    }

    public void setOnPageChangeListener(OnPageChangeListener onPageChangeListener){
        mOnPageChangeListener=onPageChangeListener;

    }

    public interface OnPageChangeListener{
        public void onPageChanged(int page, View currentView,boolean bySelf);
    }


}

 

 

MainActivity.java:

 

public class MainActivity extends AppCompatActivity {
    TwoPageLayout mLayout;
    WebView mWebView;
    RadioGroup mTabs;
    ListView mListview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

    }
    private List> getListData(){
        List> data=new ArrayList<>();
        Random r=new Random(100);
        for(int i=0;i<20;i++){
            Map map=new HashMap<>();
            map.put("key_text", "第二頁第二選項卡 listview---item+"+i);
            map.put("key_text2", "呵呵 listview---item+"+i);
            data.add(map);
        }
        return data;
    }

    private void initView() {
        mLayout=(TwoPageLayout)findViewById(R.id.main_content);
        mWebView=(WebView)findViewById(R.id.web_view);

        mTabs=(RadioGroup)findViewById(R.id.radio_group);
        mListview=(ListView)findViewById(R.id.lv);
        initWebView();
        mWebView.loadUrl("http://blog.csdn.net/qinzhen308/article/details/52789199");
        //設置滑動會沖突的視圖進去
        mLayout.setScrollerChildren(mWebView,mListview);

        //第二頁切換標簽
        mTabs.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(RadioGroup group, int checkedId) {
                switch (checkedId){
                    case R.id.rb_detail:
                        mListview.setVisibility(View.GONE);
                        mWebView.setVisibility(View.VISIBLE);
                        mLayout.changeCurScrollerChild(0);
                        break;
                    case R.id.rb_comments:
                        mWebView.setVisibility(View.GONE);
                        mListview.setVisibility(View.VISIBLE);
                        mLayout.changeCurScrollerChild(1);
                        break;
                }
            }
        });
        mTabs.check(R.id.rb_detail);
        mListview.setAdapter(new SimpleAdapter(MainActivity.this,getListData(),R.layout.item_adapter,new String[]{"key_text","key_text2"},new int[]{R.id.text1,R.id.text2}));
        //監聽切換到那一頁了
        mLayout.setOnPageChangeListener(new TwoPageLayout.OnPageChangeListener() {
            @Override
            public void onPageChanged(int page, View currentView, boolean bySelf) {
                Toast.makeText(getApplicationContext(),"當前頁碼:"+page+",是否自己改變:"+bySelf,Toast.LENGTH_LONG).show();
                if(page==1){
//                    mWebView.loadUrl("http://blog.csdn.net/qinzhen308/article/details/52789199");
                    if(mTabs.getCheckedRadioButtonId()==R.id.rb_detail){
                        mWebView.loadUrl("http://blog.csdn.net/qinzhen308/article/details/52789199");
                    }
                }
            }
        });
    }

    private void initWebView() {
        // LayoutParams lp=new
        // LayoutParams(LayoutParams.MATCH_PARENT,ScreenUtil.HEIGHT);
        // mWebView.setLayoutParams(lp);
        // contentInSV.addView(mWebView);
        WebSettings wSet = mWebView.getSettings();
        wSet.setDefaultTextEncodingName("UTF-8");
        wSet.setJavaScriptEnabled(true);
        mWebView.setVerticalScrollbarOverlay(true); // 指定的垂直滾動條有疊加樣式
        wSet.setUseWideViewPort(true);// 設定支持viewport
        wSet.setLoadWithOverviewMode(true);
        wSet.setBuiltInZoomControls(false);
        wSet.setSupportZoom(false);
//        wSet.setDisplayZoomControls(false);
        mWebView.setWebViewClient(new WebViewClient() {

            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                // TODO Auto-generated method stub
                view.loadUrl(url);
                return true;
            }

            @Override
            public void onPageFinished(WebView view, String url) {
                // TODO Auto-generated method stub
                super.onPageFinished(view, url);
            }
        });
    }
}

activity_main.xml:

 

 




    

        
            

                


                

                

                    

                    
                

                

                    


                    



                

                

                

            


        




        

            
                

                
            

            

            

        

    


主要代碼就這幾部分。TowPageLayout這個布局的用法有點類似DrawerLayout,他只能擁有2個子視圖,看字面意思也就是2頁的布局嘛。主要需要注意的是,當第二頁有可滑動控件的情況,需要對事件攔截。滑動的動畫是通過OverScroller這個類進行輔助計算。當然要注意,OverScroller只是負責計算滑動過程中的坐標變化,並不會改變控件的滑動狀態,需要通過重繪來實現位置的改變。

 

源碼地址:https://github.com/qinzhen308/TwoPageView

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved