为了满足越来越好看的界面效果,android内部的控件已经无法满足大量程序员们的需求。那么自定义控件应运而生,下面我们写一个自定义的选择框:
首先activity_down_selected.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" android:background="#22000000" > <RelativeLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_marginTop="20dp" > <EditText android:id="@+id/et" android:layout_width="150dp" android:layout_height="40dp" /> <ImageView android:id="@+id/iv" android:layout_centerVertical="true" android:layout_alignRight="@id/et" android:src="@android:drawable/ic_menu_add" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </RelativeLayout> </RelativeLayout>
package com.xuhao.downselect; import java.util.ArrayList; import android.app.Activity; import android.graphics.Color; import android.graphics.drawable.BitmapDrawable; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ImageView; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.TextView; public class DownSelectedActivity extends Activity implements OnClickListener { private EditText et; private ImageView iv; private ArrayList<String> lists = new ArrayList<String>(); private int popwindowHeight = 300; private ListView listView; private MyBaseAdapter adapter; private PopupWindow popupWindow; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initListener(); initData(); } private void initView() { setContentView(R.layout.activity_down_selected); et = (EditText) findViewById(R.id.et); iv = (ImageView) findViewById(R.id.iv); } private void initListener() { iv.setOnClickListener(this); } private void initData() { for (int i = 0; i < 15; i++) { lists.add(90000 + i + ""); } initListView(); } private void initListView() { listView = new ListView(this); listView.setBackgroundColor(Color.WHITE); listView.setVerticalScrollBarEnabled(false);// 隐藏listview的滚动条 adapter = new MyBaseAdapter(); listView.setAdapter(adapter); listView.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { et.setText(lists.get(position)); popupWindow.dismiss(); } }); } private void showNumberLists() { if (popupWindow == null) { popupWindow = new PopupWindow(listView, et.getWidth(), popwindowHeight); } popupWindow.setFocusable(true); popupWindow.setBackgroundDrawable(new BitmapDrawable()); popupWindow.setOutsideTouchable(true); popupWindow.showAsDropDown(et, 0, 0); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.iv: showNumberLists(); break; } } class MyBaseAdapter extends BaseAdapter { @Override public int getCount() { return lists.size(); } @Override public View getView(final int position, View convertView, ViewGroup parent) { final View view = View.inflate(DownSelectedActivity.this, R.layout.adapter_item, null); TextView tv = (TextView) view.findViewById(R.id.tv); ImageButton ivs = (ImageButton) view.findViewById(R.id.iv); tv.setText(lists.get(position)); ivs.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { lists.remove(position); notifyDataSetChanged(); int listviewHeight = lists.size() * view.getHeight(); popupWindow.update(et.getWidth(), listviewHeight > popwindowHeight ? popwindowHeight : listviewHeight); if (lists.size() == 0) { popupWindow.dismiss(); iv.setVisibility(View.GONE); } } }); return view; } @Override public Object getItem(int position) { return lists.get(position); } @Override public long getItemId(int position) { return position; } } }那么咱们还需要一个显示下拉信息的布局文件adapter_item.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="wrap_content" android:gravity="center_vertical" android:padding="5dp" android:descendantFocusability="blocksDescendants" android:orientation="horizontal" > <!-- 如果listview中存在button,checedbox等可以获得焦点的空间需要加上这一句 特么才能点击出效果 android:descendantFocusability="blocksDescendants"--> <TextView android:id="@+id/tv" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:paddingRight="10dp" android:drawableLeft="@android:drawable/ic_btn_speak_now" android:gravity="center_vertical" android:text="90000" /> <ImageButton android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@android:drawable/ic_delete" /> </LinearLayout>最后效果就实现了:
点击之后文字进入编辑框(哈哈,有点丑)
。
下面的是开关选择,自己用ps做了个图片大家不要介意:
首先还是布局文件:
<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" > <com.xuhao.downselect.view.ToggledSelectedView android:id="@+id/tsv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"> </com.xuhao.downselect.view.ToggledSelectedView> </RelativeLayout>表着急接着就是自定义的view:
package com.xuhao.downselect.view; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; /** * 自定义开关 * * @author json * */ public class ToggledSelectedView extends View { private ToggleState toggleState = ToggleState.Open;// 开关状态 private Bitmap sildeBg; private Bitmap switchBg; private int currentX; private boolean silding = false; // 如果view想要在java代码中动态创建,走这个方法 public ToggledSelectedView(Context context) { super(context); } // 如果是在布局中使用只需要重写这个狗仔方法 public ToggledSelectedView(Context context, AttributeSet attrs) { super(context, attrs); } public enum ToggleState { Open, Close; } /** * 设置滑动背景 * * @param on */ public void setSildeBackgroundResource(int sildeBackground) { sildeBg = BitmapFactory.decodeResource(getResources(), sildeBackground); } /** * 设置滑动块背景 * * @param off */ public void setSwitchBackgroundResource(int switchBackground) { switchBg = BitmapFactory.decodeResource(getResources(), switchBackground); } /** * 设置开关状态 * * @param open */ public void setToggleState(ToggleState state) { toggleState = state; } /** * 1.测量 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); setMeasuredDimension(sildeBg.getWidth(), sildeBg.getHeight()); } /** * 3.绘制 */ @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 1.绘制背景图片 canvas.drawBitmap(sildeBg, 0, 0, null); // 2.绘制开关 if (silding) { int left = currentX - switchBg.getWidth() / 2; if (left < 0) left = 0; if (left > sildeBg.getWidth() - switchBg.getWidth()) { left = sildeBg.getWidth() - switchBg.getWidth(); } canvas.drawBitmap(switchBg, left, 0, null); } else { if (toggleState == ToggleState.Open) { canvas.drawBitmap(switchBg, sildeBg.getWidth() - switchBg.getWidth(), 0, null); } else { canvas.drawBitmap(switchBg, 0, 0, null); } } } @Override public boolean onTouchEvent(MotionEvent event) { currentX = (int) event.getX(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: silding = true; break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: silding = false; int centerX = sildeBg.getWidth() / 2; if (currentX > centerX) { if (toggleState != ToggleState.Open) { toggleState = ToggleState.Open; if (buttonStateListener != null) { buttonStateListener .setOnToggleButtonChange(toggleState); } } } else { if (toggleState != ToggleState.Close) { toggleState = ToggleState.Close; if (buttonStateListener != null) { buttonStateListener .setOnToggleButtonChange(toggleState); } } } break; } invalidate(); return true; } private OnToggleButtonStateListener buttonStateListener; public void setOnToggleButtonChangeListener( OnToggleButtonStateListener buttonStateListener) { this.buttonStateListener = buttonStateListener; }; // 通过自定义接口把数据传递给调用者类似于观察者模式 public interface OnToggleButtonStateListener { void setOnToggleButtonChange(ToggleState state); } }
package com.xuhao.downselect; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.widget.Toast; import com.xuhao.downselect.view.ToggledSelectedView; import com.xuhao.downselect.view.ToggledSelectedView.OnToggleButtonStateListener; import com.xuhao.downselect.view.ToggledSelectedView.ToggleState; public class MainActivity extends Activity { private ToggledSelectedView tsv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); initView(); initData(); } private void initView() { setContentView(R.layout.activity_main); tsv = (ToggledSelectedView) findViewById(R.id.tsv); } private void initData() { tsv.setSildeBackgroundResource(R.drawable.on); tsv.setSwitchBackgroundResource(R.drawable.off); tsv.setToggleState(ToggleState.Open); tsv.setOnToggleButtonChangeListener(new OnToggleButtonStateListener() { @Override public void setOnToggleButtonChange(ToggleState state) { Toast.makeText(MainActivity.this, state == ToggleState.Open ? "开启" : "关闭", Toast.LENGTH_SHORT).show(); if(state == ToggleState.Open){ MainActivity.this.startActivity(new Intent(MainActivity.this,DownSelectedActivity.class)); } } }); } }
项目下载地址:https://github.com/xh2015/downselect-switch.git