可滑动的系统状态栏控制面板(wifi,bluetooth,数据通信,声音,自动旋转)

本文介绍如何在Android系统状态栏中添加滑动控制面板,以方便用户快速开关Wifi、蓝牙和数据通信等功能。通过使用ViewFlipper组件实现视图切换,并结合手势控制,提供良好的用户体验。控制面板的代码已独立为单独类,方便项目维护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

       在系统状态栏里添加一些开关,便于用户操作一些常用的操作,比如开关Wifi,开关蓝牙,开关数据通信等,这些都是在设置里可以控制 的,但是用户要点击多次之后才能到达要去的区域,这个对用户体验不佳。所以在状态栏里添加些控制按钮很有必要,一般一个页面放3到5个开关布局比较好看,但是要是想放多个多个开关,则可以通过布局画或者用组件。

       左右滑动可以使用ViewFlipper组件来实现视图之间的切换,然后添加手势控制类即可。

                     


我为了方便修改项目,把控制面板的代码单独的提取出来,放到一个类里控制。

首先添加布局,在SystemUI的status_bar_expanded.xml里添加自定义的类。

    <com.android.systemui.statusbar.SwitchControlPanel 
    	android:id="@+id/switch_control_panel"
    	android:layout_height="wrap_content" 
    	android:layout_width="match_parent"/>

然后要去SystemUI的StatusBarService.java里初始化这个类,这样系统启动时候就会发现这个类,进而进行操作了。

SwitchControlPanel  mPanel;

mPanel = (SwitchControlPanel)expanded.findViewById(R.id.switch_control_panel);

然后就可以操作SwitchControlPanel.java这个类了,这个是继承于LinearyLayout,所以要在里面添加布局,需要用到inflate这个类,因为不是在Activity里使用,所以这里就与众不同点。


package com.android.systemui.statusbar;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.wifi.WifiManager;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.View.OnTouchListener;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.view.animation.Animation.AnimationListener;
import android.widget.AdapterView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ViewFlipper;
import android.widget.AdapterView.OnItemClickListener;

import com.android.systemui.R;

public class SwitchControlPanel extends LinearLayout implements OnItemClickListener, OnGestureListener, OnTouchListener,AnimationListener {
	
	private ViewFlipper mFlipper;
	GestureDetector mGestureDetector;
	private int mCurrentLayoutState;
	private static final int FLING_MIN_DISTANCE = 100;
	private static final int FLING_MIN_VELOCITY = 200;
	
	TextView wifiView;
	LinearLayout wifiLayout;
	private WifiManager mWifiManager;
	private IntentFilter mWifiStateFilter;
	
	public SwitchControlPanel(Context context) {
		super(context);

	}

	public SwitchControlPanel(Context context, AttributeSet attrs) {
		super(context, attrs);
		LayoutInflater inflater = LayoutInflater.from(context);
		inflater.inflate(R.layout.switch_control_panel, this);
		Log.e("kingfly", "kingfly SwitchControlPanel enter");

	}

	@Override
	protected void onAttachedToWindow() {
		super.onAttachedToWindow();

	}

	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();
		mFlipper=(ViewFlipper)findViewById(R.id.flipper);
		mGestureDetector=new GestureDetector(this);
		
		wifiLayout=(LinearLayout)mFlipper.findViewById(R.id.switch_wifi);
		wifiView=(TextView)mFlipper.findViewById(R.id.switch_text_wifi);
		wifiLayout.setOnClickListener(mChangeWifi);
		wifiLayout.setOnTouchListener(mOnTouch);
		wifiView.setOnTouchListener(mOnTouch);
		mWifiManager = (WifiManager) this.getContext().getSystemService(Context.WIFI_SERVICE);
		handleWifiStateChanged(mWifiManager.getWifiState());
		mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION);
		this.getContext().registerReceiver(mWifiReceiver, mWifiStateFilter);
		
		
        mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
			@Override
			public boolean onSingleTapConfirmed(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
			
			@Override
			public boolean onDoubleTapEvent(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
			
			@Override
			public boolean onDoubleTap(MotionEvent e) {
				// TODO Auto-generated method stub
				return false;
			}
		});
        mFlipper.setOnTouchListener(this);
		mCurrentLayoutState=0;
		mFlipper.setLongClickable(true);
		
		Log.e("kingfly", "kingfly onFinishInflate enter");

	}
	
	
		private View.OnClickListener mChangeWifi = new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) {
					mWifiManager.setWifiEnabled(true);
					handleWifiStateChanged(mWifiManager.getWifiState());
				} else if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_ENABLED) {
					mWifiManager.setWifiEnabled(false);
					handleWifiStateChanged(mWifiManager.getWifiState());
				} else if (mWifiManager.getWifiState() == WifiManager.WIFI_STATE_UNKNOWN) {
					mWifiManager.setWifiEnabled(true);
					handleWifiStateChanged(mWifiManager.getWifiState());
				}

			}
		};
		
		private View.OnTouchListener mOnTouch=new View.OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				Log.e("kingfly", "kingfly View.onTouch");
				mGestureDetector.onTouchEvent(event);
				return false;
			}
		};
	
	

		private void handleWifiStateChanged(int state) {
			switch (state) {
			case WifiManager.WIFI_STATE_ENABLING:
				wifiView.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.stat_switch_wifi_off), null, getResources().getDrawable(R.drawable.stat_switch_ind_off));
				wifiView.setText(R.string.switch_enabling);
				break;
			case WifiManager.WIFI_STATE_ENABLED:
				wifiView.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.stat_switch_wifi_on), null, getResources().getDrawable(R.drawable.stat_switch_ind_on));
				wifiView.setText(R.string.switch_wifi_summary);
				break;
			case WifiManager.WIFI_STATE_DISABLING:
				wifiView.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.stat_switch_wifi_on), null, getResources().getDrawable(R.drawable.stat_switch_ind_on));
				wifiView.setText(R.string.switch_closing);
				break;
			case WifiManager.WIFI_STATE_DISABLED:
				wifiView.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.stat_switch_wifi_off), null, getResources().getDrawable(R.drawable.stat_switch_ind_off));
				wifiView.setText(R.string.switch_wifi_summary);
				break;
			default:
				wifiView.setCompoundDrawablesWithIntrinsicBounds(null, getResources().getDrawable(R.drawable.stat_switch_wifi_off), null, getResources().getDrawable(R.drawable.stat_switch_ind_off));
				wifiView.setText(R.string.switch_wifi_summary);
			}
		}
		
		private final BroadcastReceiver mWifiReceiver = new BroadcastReceiver() {
			@Override
			public void onReceive(Context context, Intent intent) {
				String action = intent.getAction();
				if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
					handleWifiStateChanged(intent.getIntExtra(
							WifiManager.EXTRA_WIFI_STATE, mWifiManager
									.getWifiState()));
				}

			}

		};
	
	
	protected Animation inFromRightAnimation() {
		Animation inFromRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromRight.setDuration(500);
		inFromRight.setInterpolator(new AccelerateInterpolator());
		return inFromRight;
	}

	protected Animation outToLeftAnimation() {
		Animation outtoLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoLeft.setDuration(500);
		outtoLeft.setInterpolator(new AccelerateInterpolator());
		return outtoLeft;
	}

	protected Animation inFromLeftAnimation() {
		Animation inFromLeft = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, -1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		inFromLeft.setDuration(500);
		inFromLeft.setInterpolator(new AccelerateInterpolator());
		return inFromLeft;
	}

	protected Animation outToRightAnimation() {
		Animation outtoRight = new TranslateAnimation(
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, +1.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f,
				Animation.RELATIVE_TO_PARENT, 0.0f);
		outtoRight.setDuration(500);
		outtoRight.setInterpolator(new AccelerateInterpolator());
		return outtoRight;
	}

	@Override
	public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onDown(MotionEvent arg0) {
		// TODO Auto-generated method stub
		return true;
	}

	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		Log.e("kingfly", "kingfly e1 :"+e1.getX()+" e2 :"+e2.getX());
		Log.e("kingfly", "Kingfly velocityX :"+velocityX+" velocityY :"+velocityY);
		if (e1.getX() - e2.getX() > FLING_MIN_DISTANCE
				&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
			mFlipper.setInAnimation(inFromRightAnimation());
			mFlipper.setOutAnimation(outToLeftAnimation());
			mFlipper.showNext();
		} else if (e2.getX() - e1.getX() > FLING_MIN_DISTANCE
				&& Math.abs(velocityX) > FLING_MIN_VELOCITY) {
			mFlipper.setInAnimation(inFromLeftAnimation());
			mFlipper.setOutAnimation(outToRightAnimation());
			mFlipper.showPrevious();
		}
		return false;

	}

	@Override
	public void onLongPress(MotionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onScroll(MotionEvent arg0, MotionEvent arg1, float arg2,
			float arg3) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public boolean onSingleTapUp(MotionEvent arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onTouch(View v, MotionEvent event) {
		Log.e("kingfly", "kingfly onTouch");
    	switch(event.getAction()){
    	case MotionEvent.ACTION_MOVE:
    		v.setAnimation(new Animation() {
			});
    		break;
    	}	
    	return mGestureDetector.onTouchEvent(event);
	}

	@Override
	public void onAnimationEnd(Animation arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onAnimationRepeat(Animation arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onAnimationStart(Animation arg0) {
		// TODO Auto-generated method stub

	}
}

里面引用的布局文件switch_control_panel.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:background="@drawable/stat_switch_bg" >
    <ViewFlipper 
    	android:id="@+id/flipper" 
    	android:layout_below="@+id/CockpitLayout" 
    	android:layout_height="fill_parent" 
    	android:layout_width="fill_parent">
    	     <include android:id="@+id/firstlayout" layout="@layout/statusbarfirst"></include>
    	     <include android:id="@+id/secondlayout" layout="@layout/statusbarsecond"></include>
    </ViewFlipper>
</LinearLayout>

include里的两个都是布局文件,statusbarfirst.xml

<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:orientation="horizontal"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content">
<LinearLayout
        android:id="@+id/switch_wifi"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true"
        android:orientation="vertical">

        <TextView
        	android:id="@+id/switch_text_wifi"
        	android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
        	/>

        </LinearLayout>

    <ImageView
        android:layout_width="2dip"
        android:layout_height="match_parent"
        android:background="@drawable/stat_switch_divider"
        />
    <LinearLayout
        android:id="@+id/switch_bluetooth"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true"
        android:orientation="vertical">

        <ImageView
            android:id="@+id/switch_img_bluetooth"
            android:layout_width="wrap_content"
            android:layout_height="0dip"
            android:layout_weight="1"
            android:scaleType="center"
            android:layout_gravity="center_horizontal"
            android:background="@drawable/stat_switch_bluetooth_on"
            />
        <TextView
        	android:id="@+id/switch_text_bluetooth"
        	android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="@string/switch_bluetooth_summary"
        	/>

        <ImageView
            android:id="@+id/switch_ind_bluetooth"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scaleType="fitXY"
          android:layout_marginLeft="6dip"
            android:layout_marginRight="6dip"
            android:background="@drawable/stat_switch_ind_on"
            />
        </LinearLayout>
</LinearLayout>


还有就是onTouch(返回false就不会覆盖掉onClick()事件了,所以这样既可以滑动也可以点击。

其他的功能可以依照上面的代码继续添加,也可以直接用LinearLayout等布局画出来,不需要ViewFlipper,当然还要添加几个小点来提示用户有多少个视图,这样用户体验更加。



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值