日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android项目开发实战—自定义左右菜单

發(fā)布時(shí)間:2024/4/14 Android 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android项目开发实战—自定义左右菜单 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Android實(shí)現(xiàn)自定義左右菜單

功能描述:
在左中右三個(gè)區(qū)域分別承載三個(gè)不同的view,把它全部添加進(jìn)來,而我們實(shí)現(xiàn)左右菜單,就是來控制當(dāng)前顯示的是哪一部分;如果顯示中間菜單,就把中間菜單呈現(xiàn)在用戶面前;如果顯示左菜單,就把左菜單和一部分的中間菜單呈現(xiàn)在用戶面前;如果顯示右菜單,就把右菜單和一部分的中間菜單呈現(xiàn)在用戶面前。即整張圖的左中右不斷移動(dòng)。

功能實(shí)現(xiàn)(step by step):
1、菜單布局(通過擴(kuò)展,完成基本布局。包含左右菜單布局和中間內(nèi)容區(qū)域,并設(shè)置顏色用于區(qū)分)2、菜單左右滑動(dòng)(使用邏輯,找出滑動(dòng)中間點(diǎn),并對(duì)事件作處理,主要針對(duì)滑動(dòng)事件)3、加入左右滑動(dòng)動(dòng)畫(使用Scroll進(jìn)行滑動(dòng)事件處理,主要是自動(dòng)滑動(dòng),增加用戶體驗(yàn))4、處理點(diǎn)擊事件(通過對(duì)左右事件的處理,會(huì)阻止點(diǎn)擊事件的處理,這里需要調(diào)用系統(tǒng),返還點(diǎn)擊事件)5、添加蒙板效果(通過增加view,對(duì)view的透明度進(jìn)行處理,從而實(shí)現(xiàn)蒙版效果)

核心內(nèi)容:
1.布局的添加
2.事件分發(fā)機(jī)制
3.滾動(dòng)添加
4.蒙版添加

構(gòu)想圖:

開發(fā)過程中遇到的錯(cuò)誤:
Caused by:java.lang.IllegalStateException:The specified child already has a parent.You must call removeView() on the child’s parent first.
造成這個(gè)原因,是組件在父類中重復(fù)加載了相同的組件
如:
addView(leftMenu, mLayout); // 第一次添加
addView((leftMenu, , mLayout); // 第二次添加

源代碼:

activity_main.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools= "http://schemas.android.com/tools"android:layout_width= "match_parent"android:layout_height= "match_parent"tools:context= ".MainActivity" ></RelativeLayout>

left.xml:

<?xml version= "1.0" encoding ="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width= "match_parent"android:layout_height= "match_parent"android:orientation= "vertical" ><Button android:id="@+id/button1"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="Button" /></LinearLayout>

MainActivity.java

package com.example.mymenu;import android.os.Bundle; import android.app.Activity; import android.support.v4.app.FragmentActivity; import android.view.Menu;public class MainActivity extends FragmentActivity {private MainUI mainUI ;private LeftMenu leftMenu ;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);//實(shí)例化MainUImainUI= new MainUI(this );setContentView( mainUI);//實(shí)例化LeftMenuleftMenu= new LeftMenu();getSupportFragmentManager().beginTransaction().add(MainUI. LEFT_ID,leftMenu ).commit();}}

MainUI.java

package com.example.mymenu;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Point;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;

@SuppressLint(“NewApi” )
public class MainUI extends RelativeLayout{

private Context context ;private FrameLayout leftMenu ;private FrameLayout middleMenu ;private FrameLayout rightMenu ;//設(shè)置蒙版private FrameLayout middleMask ;private Scroller mScroller ;//定義左中右菜單的IDpublic static final int LEFT_ID=0xaabbcc;public static final int MIDDLE_ID=0xaaccbb;public static final int RIGHT_ID=0xccbbaa;//繼承自RelativeLayout,并實(shí)現(xiàn)兩個(gè)構(gòu)造方法public MainUI(Context context) {super(context);initView(context);}public MainUI(Context context, AttributeSet attrs) {super(context, attrs);initView(context);}public void initView(Context context){this.context =context;mScroller=new Scroller(context, new DecelerateInterpolator()); //渲染器//實(shí)例化三個(gè)區(qū)域leftMenu= new FrameLayout(context);middleMenu=new FrameLayout(context);rightMenu=new FrameLayout(context);middleMask=new FrameLayout(context);//分別為三個(gè)區(qū)域添加不同的顏色leftMenu.setBackgroundColor(Color. RED);middleMenu.setBackgroundColor(Color.GREEN);rightMenu.setBackgroundColor(Color.RED);middleMask.setBackgroundColor(0x88000000);//蒙版的初始顏色為淺灰色//為自定義的左中右菜單添加IDleftMenu.setId( LEFT_ID);middleMenu.setId(MIDDLE_ID );rightMenu.setId(RIGHT_ID ); //把三個(gè)區(qū)域全部填充到一個(gè)view中,實(shí)際上這個(gè)view就是我們承載三個(gè)區(qū)域的最外層的RelativeLayout,也是當(dāng)前的主文件addView( leftMenu);addView( middleMenu);addView( rightMenu);addView( middleMask);middleMask.setAlpha(0);//設(shè)置蒙版的科技度(完全可見),只有在滑動(dòng)的時(shí)候才是不可見的}public float onMiddleMask(){System. out.println("透明度:" +middleMask .getAlpha());return middleMask .getAlpha(); }//根據(jù)滑動(dòng)的距離的變化來設(shè)置可見度值的變化@Overridepublic void scrollTo(int x, int y) {super.scrollTo(x, y);onMiddleMask();int curX=Math.abs(getScrollX());float scale=curX/(float)leftMenu.getMeasuredWidth(); //計(jì)算整個(gè)可見寬度middleMask.setAlpha(scale);}//在把三個(gè)區(qū)域添加到Layout之前,先對(duì)它們的寬和高進(jìn)行測(cè)量@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {//widthMeasureSpec,heightMeasureSpec是當(dāng)前屏幕的寬度和高度super.onMeasure(widthMeasureSpec, heightMeasureSpec);//中間菜單的寬和高即為當(dāng)前屏幕的寬和高middleMenu.measure(widthMeasureSpec, heightMeasureSpec);//獲取蒙版的寬和高middleMask.measure(widthMeasureSpec, heightMeasureSpec);//得到當(dāng)前屏幕的真實(shí)寬度int realWidth=MeasureSpec.getSize(widthMeasureSpec);//計(jì)算所需要的寬度int tempWidthMeasure=MeasureSpec.makeMeasureSpec(( int)(realWidth*0.8f),MeasureSpec.EXACTLY);//為左右菜單設(shè)置相應(yīng)的寬度leftMenu.measure(tempWidthMeasure, heightMeasureSpec);rightMenu.measure(tempWidthMeasure, heightMeasureSpec); }//把三個(gè)區(qū)域添加到Layout中@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {//五個(gè)參數(shù)(改變監(jiān)聽,left,top,right,bottom)super.onLayout(changed, l, t, r, b);//設(shè)置三個(gè)區(qū)域在layout中的位置middleMenu.layout(l, t, r, b);middleMask.layout(l, t, r, b);leftMenu.layout(l- leftMenu.getMeasuredWidth(), t, l, b);//(l-leftMenu.getMeasuredWidth(), t, r, b)rightMenu.layout(r,t,r+ rightMenu.getMeasuredWidth(),b); //(l+middleMenu.getMeasuredWidth(), t, l+middleMenu.getMeasuredWidth()+rightMenu.getMeasuredWidth(), b)}private boolean isTestCompete ;private boolean isleftrightEvent ;//標(biāo)識(shí)上下滑動(dòng)和左右滑動(dòng),左右滑動(dòng)為true,上下滑動(dòng)為false//事件分發(fā)@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {//檢測(cè)到一個(gè)事件,判斷是什么事件(上下滑動(dòng)事件、左右滑動(dòng)事件、點(diǎn)擊事件)if (!isTestCompete ) {//沒有初始化,默認(rèn)為falsegetEventType(ev); //創(chuàng)建一個(gè)判斷處理事件的方法return true ;}if (isleftrightEvent ) {//左右滑動(dòng)應(yīng)該觸發(fā)的響應(yīng)switch (ev.getActionMasked()) {case MotionEvent.ACTION_MOVE://你手指滑動(dòng)的距離即為當(dāng)前屏幕滑動(dòng)的距離int curScrollX=getScrollX();//定義屏幕滑動(dòng)的距離int dis_x=(int )(ev.getX()-point.x);//定義手指滑動(dòng)的距離int expectX=-dis_x+curScrollX;//根據(jù)差值判斷是向左滑動(dòng)還是向右滑動(dòng)(差值大于20是向右滑動(dòng);差值小于20是向左滑動(dòng))int finalX=0; //定義屏幕最終的左右滑動(dòng)距離if (expectX<0) {//向左finalX=Math. max(expectX, -leftMenu.getMeasuredWidth());//最大值} else{ //向右finalX=Math. min(expectX, rightMenu.getMeasuredWidth());//最小值}scrollTo(finalX, 0); //使屏幕移動(dòng)到最終的位置point. x=( int)ev.getX();break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:curScrollX=getScrollX();if (Math.abs(curScrollX)> leftMenu.getMeasuredWidth() >> 1) {//當(dāng)屏幕滑動(dòng)的距離大于左右菜單的一半時(shí),自動(dòng)跳到相應(yīng)的菜單if (curScrollX<0) {mScroller.startScroll(curScrollX,0,- leftMenu.getMeasuredWidth()-curScrollX, 0,200); //起始X,起始Y,終止X,終止Y} else {mScroller.startScroll(curScrollX,0,leftMenu.getMeasuredWidth()-curScrollX, 0,200);}} else {//返回原點(diǎn)mScroller.startScroll(curScrollX,0,-curScrollX, 0,200);}invalidate(); //調(diào)用view的重繪方法進(jìn)行刷新isleftrightEvent=false ;isTestCompete=false ; break;}} else{//對(duì)上下滑動(dòng)和點(diǎn)擊觸發(fā)的響應(yīng)switch (ev.getActionMasked()) {case MotionEvent.ACTION_UP:isleftrightEvent=false ;isTestCompete=false ;break;default: break;}}return super .dispatchTouchEvent(ev);}//重寫回調(diào)方法,使左右菜單進(jìn)行滑動(dòng)@Overridepublic void computeScroll() {super.computeScroll();if (mScroller .computeScrollOffset()) {return;}int tempX=mScroller .getCurrX();scrollTo(tempX, 0);}private Point point =new Point(); //獲取當(dāng)前屏幕的點(diǎn),通過點(diǎn)來計(jì)算滑動(dòng)的距離,根據(jù)滑動(dòng)的距離來判斷相應(yīng)的事件是滑動(dòng)還是點(diǎn)擊private static final int TEST_DIS=20; //如果移動(dòng)距離大于20就定義為滑動(dòng)//判斷處理事件private void getEventType(MotionEvent ev) {switch (ev.getActionMasked()) {case MotionEvent.ACTION_DOWN:point. x=( int) ev.getX();//floatpoint. y=( int) ev.getY();super.dispatchTouchEvent(ev);break;case MotionEvent.ACTION_MOVE:int dX= Math.abs(( int)ev.getX()-point .x );//獲取水平方向上移動(dòng)距離的絕對(duì)值int dY=Math.abs(( int)ev.getY()-point .y );//獲取垂直方向上移動(dòng)距離的絕對(duì)值if (dX>=TEST_DIS && dX>dY) {//左右滑動(dòng)isleftrightEvent=true ;isTestCompete=true ; //允許進(jìn)入接下來的返出測(cè)試階段//獲取當(dāng)前點(diǎn)的 xy坐標(biāo)point. x=( int) ev.getX();//floatpoint. y=( int) ev.getY();} else if (dY>=TEST_DIS && dY>dX) { //上下滑動(dòng)isleftrightEvent=false ;isTestCompete=true ;//允許進(jìn)入接下來的返出測(cè)試階段point. x=( int) ev.getX();//floatpoint. y=( int) ev.getY();}break;case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL://觸摸到屏幕的邊緣//對(duì)點(diǎn)擊事件進(jìn)行處理(返還給系統(tǒng)處理)super.dispatchTouchEvent(ev);isleftrightEvent=false ;isTestCompete=false ;break;}}

}

LeftMeau.java:

package com.example.mymenu;import android.os.Bundle; import android.support.v4.app.Fragment; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup;public class LeftMenu extends Fragment{@Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {View v=inflater.inflate(R.layout. left, container,false);//引入left.xml布局文件//為button按鈕添加監(jiān)聽事件v.findViewById(R.id. button1).setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {System. out.println("Hello LMB!!" ); }});return v;} }

總結(jié)

以上是生活随笔為你收集整理的Android项目开发实战—自定义左右菜单的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。