GVKun编程网logo

仿iPhone通讯录制作小程序自定义选择组件(仿iphone通讯录制作小程序自定义选择组件)

8

本文将为您提供关于仿iPhone通讯录制作小程序自定义选择组件的详细介绍,我们还将为您解释仿iphone通讯录制作小程序自定义选择组件的相关知识,同时,我们还将为您提供关于Android仿iphone

本文将为您提供关于仿iPhone通讯录制作小程序自定义选择组件的详细介绍,我们还将为您解释仿iphone通讯录制作小程序自定义选择组件的相关知识,同时,我们还将为您提供关于Android仿iphone自定义滚动选择器、iphone – 将自定义选择器添加到UIBarButtonItem、iPhone如何导出通讯录(怎样导出iPhone通讯录)、iphone通讯录传给华为的实用信息。

本文目录一览:

仿iPhone通讯录制作小程序自定义选择组件(仿iphone通讯录制作小程序自定义选择组件)

仿iPhone通讯录制作小程序自定义选择组件(仿iphone通讯录制作小程序自定义选择组件)

前言

近期闲来无事,想着闲着也是闲着,不如给自己搞点事情做!敢想敢做,于是选择了给微信小程序做个仿iPhone通讯录效果的自定义组件。

先来整理一下,瞧瞧需要实现的核心功能。

  1. 按照第一个字的首字母排序;
  2. 实现输入搜索功能;
  3. 侧边栏字母导航;
从易到难,先来看看页面的结构布局。

基本上分为3块:
  • 顶部的搜索区域;
  • 内容的展示区域;
  • 侧边字母导航栏区域;
// index.wxml
<view class="main">
  <!-- 顶部搜索区域 -->
  <view class="header">
  </view>
  <!-- 内容区域 -->
  <scroll-view class="scroll">
  </scroll-view>
  <!-- 侧边导航 -->
  <view class="sub_nav">
  </view>
</view>
复制代码

【顶部的搜索区域】

一目了然就直接贴代码了。

<view class="header">
    // 这里或许有人要问,为啥不用小程序的label组件呢。?_?
    // 原因就是...我就不用,你还能咬我?!^(oo)^
    // 哈哈哈哈~开个玩笑,其实是小程序的label组件还没支持input!
    <view class="label"> 
      <icon></icon>
      <input type="text" placeholder="搜索" />
    </view>
</view>
复制代码

【内容的展示区域】

再说一目了然会不会被打呢?
根据图片就可以看出来,存在2个区域。

  1. 红框包围的外框,负责圈定展示的范围;
  2. 绿框包围的范围,包含有字母标题和对应的子项。

代码如下:

<scroll-view class="scroll">
    <view class="dl">
      <view class="dt">这里是字母标题。</view>
      <view class="dd">
        <span>这里当然是展示的内容啦。</span>
      </view>
    </view>
  </scroll-view>
复制代码

【侧边字母导航栏区域】

为了节省一下文章的篇幅,这里就不贴图了,很简单,就是并排下来就好了。

<view class="sub_nav">
    <view class="option">这里是输出字母。</view>
</view>
复制代码
接下来是wxss的样式了。

考虑到wxss的样式较多,我就直接贴代码链接吧,有兴趣的童鞋可以瞧瞧。

完成之后,是时候贴个效果图了。(不许吐槽丑,宝宝会不开心的!)

结构样式弄完了,也贴一下自定组件的基础文件
// index.json
{
  "component": true
}
复制代码
// index.js
Component({
  properties: {},// 组件的对外属性
  data: {},// 组件的内部数据
  lifetimes: {},// 生命周期
  methods: {}     // 事件
});
复制代码
现在开始实现功能了!!! 按照第一个字的首字母排序

说实话,实现这块功能呢,我是没啥头绪的,所以这个时候就要求助伟大的“度娘/Google”了。
经过楼主“遍寻网络”,查找到如下页面的源码参考:

因楼主问题,遗忘了该网址,如有知道的童鞋,贴个链接告诉下楼主,楼主立马麻溜的加上。

源码的原理大概描述下:

收录20902个汉字和375个多音字的Unicode编码,然后用JS切割首字母并转换成Unicode进行对比,最后返回对应首字母的拼音。

// 汉字对应的Unicode编码文件
// oMultiDiff = 多音字 | firstLetterMap = 汉字
import firstStore from './firstChineseLetter'; 

// 获取首字母拼音
function getFirstLetter (val) {
  const firstVal = val.charat(0);
  if (/.*[\u4e00-\u9fa5]+.*/.test(firstVal)) {
    // 处理中文字符
    // 转换成Unicode编码,与firstStore里面的数据进行对比,然后返回对应的参数
    const code = firstVal.charCodeAt(0); // 转换成Unicode编码
    return code in firstStore.oMultiDiff ? firstStore.oMultiDiff[code] : firstStore.firstLetterMap.charat(code - 19968);
  } else {
    // 这里处理非中文
    // 检测是否字母,如果是就直接返回大写的字母
    // 不是的话,返回“#”
    return /^[a-zA-Z]+$/.test(firstVal) ? firstVal.toupperCase() : '#';
  }
}

getFirstLetter('东城区');
// 输出结果:D

复制代码

firstChineseLetter.js地址

获取首字母的方法有了之后,就该对数据进行处理了。

首先定义一下组件所需要的参数。

Component({
  // 组件的对外属性
  properties: {
    data: { type: Array,value: [],},// 组件外传递进来的数据
    attr: { type: String,value: 'label' },// 需要进行首字母处理的属性,默认是"label"
  },...
})
复制代码

然后,针对组件外传递进来的数据,做一次转换。

// 静态数据的存储
const Static = {
  list: []
}

Component({
  ...
  methods: {
    // 初始/重置数据
    init () {
      const { data,attr } = this.properties;

      let changeData = [],// 转换后的数据
          inChangeData = {}; // 存储转换后的数据对应字母的索引值
          
      data.map(v => {
        // 获取首字母拼音
        let firstLetter = this.getFirstLetter(v[attr]); 
        
        // 循环对比检测
        firstLetter.split('').map(str => {
          if (str in inChangeData) {
            // 有首字母相同的项,
            // 则添加入已有的项里面
            changeData[inChangeData[str]].list.push(v);
          } else {
            // 没有首字母相同的项,
            // 则在尾部追加一条新的数据,
            // 储存对应的字母值(firstLetter),
            // 同时存储该字母对应的索引
            changeData.push({ firstLetter: str,list: [v] });
            inChangeData[str] = changeData.length - 1;
          }
        });
      });
      
      // 此时转换后的数组属于乱序,
      // 需要对乱序的数组进行排序
      changeData.sort((pre,next) => pre.firstLetter < next.firstLetter ? -1 : 1);
      
      // 若存在“#”项,将位置位移至底部
      if (changeData[0].firstLetter === '#') {
        const firstArr = changeData.splice(0,1);
        changeData = [...changeData,...firstArr];
      }

      // 存储转换后的数据,
      // this.data.list的数据对应页面的展示数据,因为有搜索功能,数据可能会变更,
      // 在静态的数据里面,也存储1份数据,方便后续的搜索等功能。
      this.setData({ list: changeData });
      Static.list = changeData;
    },}
  ...
});
复制代码

初始化函数有了之后呢,当然是调用它啦。

Component({
  lifetimes: {
    // 在组件实例进入页面节点树时执行初始化数据
    attached () {
      this.init();
    }
  },observers: {
    // 考虑到组件传递的数据存在变更的可能,
    // 在数据变更的时候,也要做一次初始化
    'data,attr,icon' (data,attr) {
      this.init();
    }
  },})
复制代码
接下来是搜索功能啦~

先给页面搜索框加个监听事件(input)

<view class="main">
  ...
  <view class="header">
    <view class="label">
      <icon></icon>
      <input type="text" placeholder="搜索" value="{{ search }}" bindinput="searchData" />
    </view>
  </view>
  ...
</view>
复制代码

接着是JS的事件

const Static = {
  list: []
}

Component({
  ...
  methods: {
    searchData (e) {
      const { value } = e.detail; // 用户输入的值
      const { list } = Static; // init存储的静态数据,用来做数据对比
      const { attr } = this.properties; // 要对比的属性值
      let result = [],tem = {};
      
      // 没有搜索内容,返回全部内容
      if (value.length === 0) { this.setData({ list: Static.list }); return; }

      // 检索搜索内容
      list.map(v => {
        // 获取所有跟value匹配上的数据
        const searchList = v.list.filter(v => v[attr].indexOf(value) !== -1);
        
        if (searchList.length > 0) {
          // 此处原理类似楼上init的对比,此处不细说,
          // 反正我懒我有理(0.0)
          if (v.firstLetter in tem) {
            const _list = result[tem[v.firstLetter]].lish;
            result[tem[v.firstLetter]].lish = [..._list,...searchList];
          } else {
            result.push({ firstLetter: v.firstLetter,list: [...searchList] });
            tem[v.firstLetter] = result.length - 1;
          }
        }
      });
      
      // 存储数据
      this.setData({ list: result,search: value });
    }
  },...
});
复制代码
侧边栏字母导航

(突然觉得,写文好累啊!!!)

写这块的时候呢,楼主发现了iPhone通讯录侧边导航栏有个问题,手指在字母导航栏上滑动的时候,有时候很难确认自己滑到了哪个区域?!

然鹅这个问题呢,楼主发现了微信的通讯录,针对这块添加了手指滑动的时候,添加了个结构来帮助用户确认目前所处的区域。

楼主本着学习的精神,借(chao)鉴(xi)了这个效果,来个效果图。

贴一下新的wxml结构

<!-- 侧边导航 -->
  <view class="sub_nav" id="subNav" catchtouchstart="subTouchStart" catchtouchmove="subTouchMove" catchtouchend="subTouchEnd">
    <view class="option" wx:for="{{ list }}" data-firstLetter="{{ item.firstLetter }}" wx:key="firstLetter">
      {{ item.firstLetter }}
      <!-- 以下这块就是新增的结构啦 S -->
      <view 
        class="max {{ item.firstLetter ===  scrollIntoView && subNavHint ? 'show' : '' }}" 
        data-desc="{{ item.firstLetter }}"
      ></view>
      <!-- 以上这块就是新增的结构啦 E -->
    </view>
  </view>
复制代码
const Static = {
  list: [],timer: null
}

Component({
  ...
  data: {
    scrollIntoView: '',// 标记当前处于哪个字母
    subNavHint: false,// 控制借(chao)鉴(xi)微信效果的元素
  },methods: {
    subTouchStart () {
      this.setData({ subNavHint: true,scrollIntoView: '' });
    },subTouchEnd () {
      this.setData({ subNavHint: false });
    },subTouchMove (e) {
      // 获取字母导航栏元素对应的值
      const query = this.createSelectorQuery();
      query.select('#subNav').boundingClientRect();
      query.selectViewport().scrollOffset();
      query.exec(res => {
        const { clientY } = e.touches[0]; // Y轴的位置
        const DomTop = res[0].top; // 导航元素距离顶部的位置
        const { list } = this.data;
        
        // 计算索引,
        // 或许看到这里有人会疑问,为什么是除以20?
        // 因为样式里面,我写的高度是20px,所以每个字母的区域是20px。
        let index = Math.round((clientY - DomTop) / 20); 
        index = index >= list.length ? list.length - 1 : index; // 限制索引大于0
        index = index < 0 ? 0 : index; // 限制索引小于0
        // 限制结果重复赋值
        if (list[index].firstLetter !== this.data.scrollIntoView) {
          this.setData({ scrollIntoView: list[index].firstLetter });
          // 加个抖动效果
          wx.vibrateShort(); 
        }
      });
      }
    },}
  ...
});
复制代码
结语

文章写到这呢,基本上核心的功能都已经实现啦~(终于写完了...)
通过自己封装组件,楼主还是有挺大收获的!

当然,这个组件还有很多可以继续完善的地方,有兴趣的童鞋呢,可以提出你的优化建议,楼主有时(xing)间(qu)的话,会继续完善下去。

最后,还是推一下这个组件啦,希望它能帮到有需要的童鞋。

github地址

手写不易,欢迎提issues,欢迎star,内附有使用方法哦。

Android仿iphone自定义滚动选择器

Android仿iphone自定义滚动选择器

本文实例为大家分享了Android仿iphone自定义滚动选择器的具体代码,供大家参考,具体内容如下

一、多的不说,效果图,先走起

二、实例源码

(1)自定义控件

package com.pickerscrollview.views; 
 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Timer; 
import java.util.TimerTask; 
 
import android.annotation.SuppressLint; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Paint; 
import android.graphics.Paint.Align; 
import android.graphics.Paint.FontMetricsInt; 
import android.graphics.Paint.Style; 
import android.os.Handler; 
import android.os.Message; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 
import android.view.View; 
 
import com.pickerscrollview.bean.Pickers; 
 
/** 
 * 自定义滚动选择器 
 * 
 * @author zengtao 2015年5月20日 下午7:36:03 
 * 
 */ 
@SuppressLint({ "HandlerLeak","ClickableViewAccessibility" }) 
public class PickerScrollView extends View { 
 
  public static final String TAG = "PickerView"; 
  /** 
   * text之间间距和minTextSize之比 
   */ 
  public static final float MARGIN_ALPHA = 2.8f; 
  /** 
   * 自动回滚到中间的速度 
   */ 
  public static final float SPEED = 2; 
 
  private List<Pickers> mDataList; 
  /** 
   * 选中的位置,这个位置是mDataList的中心位置,一直不变 
   */ 
  private int mCurrentSelected; 
  private Paint mPaint; 
 
  private float mMaxTextSize = 20; 
  private float mMinTextSize = 10; 
 
  private float mMaxTextAlpha = 255; 
  private float mMinTextAlpha = 120; 
 
  private int mColorText = 0x333333; 
 
  private int mViewHeight; 
  private int mViewWidth; 
 
  private float mLastDownY; 
  /** 
   * 滑动的距离 
   */ 
  private float mMoveLen = 0; 
  private boolean isInit = false; 
  private onSelectListener mSelectListener; 
  private Timer timer; 
  private MyTimerTask mTask; 
 
  Handler updateHandler = new Handler() { 
 
    @Override 
    public void handleMessage(Message msg) { 
      if (Math.abs(mMoveLen) < SPEED) { 
        mMoveLen = 0; 
        if (mTask != null) { 
          mTask.cancel(); 
          mTask = null; 
          performSelect(); 
        } 
      } else 
        // 这里mMoveLen / Math.abs(mMoveLen)是为了保有mMoveLen的正负号,以实现上滚或下滚 
        mMoveLen = mMoveLen - mMoveLen / Math.abs(mMoveLen) * SPEED; 
      invalidate(); 
    } 
 
  }; 
 
  public PickerScrollView(Context context) { 
    super(context); 
    init(); 
  } 
 
  public PickerScrollView(Context context,AttributeSet attrs) { 
    super(context,attrs); 
    init(); 
  } 
 
  public void setonSelectListener(onSelectListener listener) { 
    mSelectListener = listener; 
  } 
 
  private void performSelect() { 
    if (mSelectListener != null) 
      mSelectListener.onSelect(mDataList.get(mCurrentSelected)); 
  } 
 
  public void setData(List<Pickers> datas) { 
    mDataList = datas; 
    mCurrentSelected = datas.size() / 2; 
    invalidate(); 
  } 
 
  /** 
   * 选择选中的item的index 
   * 
   * @param selected 
   */ 
  public void setSelected(int selected) { 
    mCurrentSelected = selected; 
    int distance = mDataList.size() / 2 - mCurrentSelected; 
    if (distance < 0) 
      for (int i = 0; i < -distance; i++) { 
        moveHeadToTail(); 
        mCurrentSelected--; 
      } 
    else if (distance > 0) 
      for (int i = 0; i < distance; i++) { 
        moveTailToHead(); 
        mCurrentSelected++; 
      } 
    invalidate(); 
  } 
 
  /** 
   * 选择选中的内容 
   * 
   * @param mSelectItem 
   */ 
  public void setSelected(String mSelectItem) { 
    for (int i = 0; i < mDataList.size(); i++) 
      if (mDataList.get(i).equals(mSelectItem)) { 
        setSelected(i); 
        break; 
      } 
  } 
 
  private void moveHeadToTail() { 
    Pickers head = mDataList.get(0); 
    mDataList.remove(0); 
    mDataList.add(head); 
  } 
 
  private void moveTailToHead() { 
    Pickers tail = mDataList.get(mDataList.size() - 1); 
    mDataList.remove(mDataList.size() - 1); 
    mDataList.add(0,tail); 
  } 
 
  @Override 
  protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec) { 
    super.onMeasure(widthMeasureSpec,heightMeasureSpec); 
    mViewHeight = getMeasuredHeight(); 
    mViewWidth = getMeasuredWidth(); 
    // 按照View的高度计算字体大小 
    mMaxTextSize = mViewHeight / 8.0f; 
    mMinTextSize = mMaxTextSize / 2f; 
    isInit = true; 
    invalidate(); 
  } 
 
  private void init() { 
    timer = new Timer(); 
    mDataList = new ArrayList<Pickers>(); 
    mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 
    mPaint.setStyle(Style.FILL); 
    mPaint.setTextAlign(Align.CENTER); 
    mPaint.setColor(mColorText); 
  } 
 
  @Override 
  protected void onDraw(Canvas canvas) { 
    super.onDraw(canvas); 
    // 根据index绘制view 
    if (isInit) 
      drawData(canvas); 
  } 
 
  private void drawData(Canvas canvas) { 
    // 先绘制选中的text再往上往下绘制其余的text 
    float scale = parabola(mViewHeight / 4.0f,mMoveLen); 
    float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize; 
    mPaint.setTextSize(size); 
    mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); 
    // text居中绘制,注意baseline的计算才能达到居中,y值是text中心坐标 
    float x = (float) (mViewWidth / 2.0); 
    float y = (float) (mViewHeight / 2.0 + mMoveLen); 
    FontMetricsInt fmi = mPaint.getFontMetricsInt(); 
    float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0)); 
 
    int indexs = mCurrentSelected; 
    String textData = mDataList.get(indexs).getShowConetnt(); 
    canvas.drawText(textData,x,baseline,mPaint); 
 
    // 绘制上方data 
    for (int i = 1; (mCurrentSelected - i) >= 0; i++) { 
      drawOtherText(canvas,i,-1); 
    } 
    // 绘制下方data 
    for (int i = 1; (mCurrentSelected + i) < mDataList.size(); i++) { 
      drawOtherText(canvas,1); 
    } 
  } 
 
  /** 
   * @param canvas 
   * @param position 
   *      距离mCurrentSelected的差值 
   * @param type 
   *      1表示向下绘制,-1表示向上绘制 
   */ 
  private void drawOtherText(Canvas canvas,int position,int type) { 
    float d = (float) (MARGIN_ALPHA * mMinTextSize * position + type 
        * mMoveLen); 
    float scale = parabola(mViewHeight / 4.0f,d); 
    float size = (mMaxTextSize - mMinTextSize) * scale + mMinTextSize; 
    mPaint.setTextSize(size); 
    mPaint.setAlpha((int) ((mMaxTextAlpha - mMinTextAlpha) * scale + mMinTextAlpha)); 
    float y = (float) (mViewHeight / 2.0 + type * d); 
    FontMetricsInt fmi = mPaint.getFontMetricsInt(); 
    float baseline = (float) (y - (fmi.bottom / 2.0 + fmi.top / 2.0)); 
 
    int indexs = mCurrentSelected + type * position; 
    String textData = mDataList.get(indexs).getShowConetnt(); 
    canvas.drawText(textData,(float) (mViewWidth / 2.0),mPaint); 
  } 
 
  /** 
   * 抛物线 
   * 
   * @param zero 
   *      零点坐标 
   * @param x 
   *      偏移量 
   * @return scale 
   */ 
  private float parabola(float zero,float x) { 
    float f = (float) (1 - Math.pow(x / zero,2)); 
    return f < 0 ? 0 : f; 
  } 
 
  @Override 
  public boolean onTouchEvent(MotionEvent event) { 
    switch (event.getActionMasked()) { 
    case MotionEvent.ACTION_DOWN: 
      dodown(event); 
      break; 
    case MotionEvent.ACTION_MOVE: 
      doMove(event); 
      break; 
    case MotionEvent.ACTION_UP: 
      doUp(event); 
      break; 
    } 
    return true; 
  } 
 
  private void dodown(MotionEvent event) { 
    if (mTask != null) { 
      mTask.cancel(); 
      mTask = null; 
    } 
    mLastDownY = event.getY(); 
  } 
 
  private void doMove(MotionEvent event) { 
 
    mMoveLen += (event.getY() - mLastDownY); 
 
    if (mMoveLen > MARGIN_ALPHA * mMinTextSize / 2) { 
      // 往下滑超过离开距离 
      moveTailToHead(); 
      mMoveLen = mMoveLen - MARGIN_ALPHA * mMinTextSize; 
    } else if (mMoveLen < -MARGIN_ALPHA * mMinTextSize / 2) { 
      // 往上滑超过离开距离 
      moveHeadToTail(); 
      mMoveLen = mMoveLen + MARGIN_ALPHA * mMinTextSize; 
    } 
 
    mLastDownY = event.getY(); 
    invalidate(); 
  } 
 
  private void doUp(MotionEvent event) { 
    // 抬起手后mCurrentSelected的位置由当前位置move到中间选中位置 
    if (Math.abs(mMoveLen) < 0.0001) { 
      mMoveLen = 0; 
      return; 
    } 
    if (mTask != null) { 
      mTask.cancel(); 
      mTask = null; 
    } 
    mTask = new MyTimerTask(updateHandler); 
    timer.schedule(mTask,10); 
  } 
 
  class MyTimerTask extends TimerTask { 
    Handler handler; 
 
    public MyTimerTask(Handler handler) { 
      this.handler = handler; 
    } 
 
    @Override 
    public void run() { 
      handler.sendMessage(handler.obtainMessage()); 
    } 
 
  } 
 
  public interface onSelectListener { 
    void onSelect(Pickers pickers); 
  } 
} 

(2)实体类

package com.pickerscrollview.bean; 
 
import java.io.Serializable; 
 
/** 
 * 
 * @author zengtao 2015年5月20日下午7:18:14 
 * 
 */ 
public class Pickers implements Serializable { 
 
  private static final long serialVersionUID = 1L; 
 
  private String showConetnt; 
  private String showId; 
 
  public String getShowConetnt() { 
    return showConetnt; 
  } 
 
  public String getShowId() { 
    return showId; 
  } 
 
  public Pickers(String showConetnt,String showId) { 
    super(); 
    this.showConetnt = showConetnt; 
    this.showId = showId; 
  } 
 
  public Pickers() { 
    super(); 
  } 
 
} 

(3)主界面

package com.pickerscrollview.ui; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import android.app.Activity; 
import android.os.Bundle; 
import android.view.View; 
import android.view.View.OnClickListener; 
import android.widget.Button; 
import android.widget.RelativeLayout; 
 
import com.pickerscrollview.bean.Pickers; 
import com.pickerscrollview.views.PickerScrollView; 
import com.pickerscrollview.views.PickerScrollView.onSelectListener; 
 
/** 
 * 主界面 
 * 
 * @author zengtao 2015年5月20日 下午7:36:03 
 * 
 */ 
public class MainActivity extends Activity { 
 
  private Button bt_scrollchoose; // 滚动选择器按钮 
  private PickerScrollView pickerscrlllview; // 滚动选择器 
  private List<Pickers> list; // 滚动选择器数据 
  private String[] id; 
  private String[] name; 
 
  private Button bt_yes; // 确定按钮 
  private RelativeLayout picker_rel; // 选择器布局 
 
  @Override 
  protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
 
    initView(); 
    initLinstener(); 
    initData(); 
  } 
 
  /** 
   * 初始化 
   */ 
  private void initView() { 
    bt_scrollchoose = (Button) findViewById(R.id.bt_scrollchoose); 
    picker_rel = (RelativeLayout) findViewById(R.id.picker_rel); 
    pickerscrlllview = (PickerScrollView) findViewById(R.id.pickerscrlllview); 
    bt_yes = (Button) findViewById(R.id.picker_yes); 
  } 
 
  /** 
   * 设置监听事件 
   */ 
  private void initLinstener() { 
    bt_scrollchoose.setonClickListener(onClickListener); 
    pickerscrlllview.setonSelectListener(pickerListener); 
    bt_yes.setonClickListener(onClickListener); 
  } 
 
  /** 
   * 初始化数据 
   */ 
  private void initData() { 
    list = new ArrayList<Pickers>(); 
    id = new String[] { "1","2","3","4","5","6" }; 
    name = new String[] { "中国银行","农业银行","招商银行","工商银行","建设银行","民生银行" }; 
    for (int i = 0; i < name.length; i++) { 
      list.add(new Pickers(name[i],id[i])); 
    } 
    // 设置数据,默认选择第一条 
    pickerscrlllview.setData(list); 
    pickerscrlllview.setSelected(0); 
  } 
 
  // 滚动选择器选中事件 
  onSelectListener pickerListener = new onSelectListener() { 
 
    @Override 
    public void onSelect(Pickers pickers) { 
      System.out.println("选择:" + pickers.getShowId() + "--银行:" 
          + pickers.getShowConetnt()); 
    } 
  }; 
 
  // 点击监听事件 
  OnClickListener onClickListener = new OnClickListener() { 
 
    @Override 
    public void onClick(View v) { 
      if (v == bt_scrollchoose) { 
        picker_rel.setVisibility(View.VISIBLE); 
      } else if (v == bt_yes) { 
        picker_rel.setVisibility(View.GONE); 
      } 
    } 
  }; 
} 

三、总结

先做一下解析,在滑动手指的时候,有一个突出的点,就是有点像圆弧那个弧度一样的感觉,所以我们要用parabola这个方法去计算出来,画多大的字也是需要计算控件的高度,和宽度来绘制,首先我们先绘制中间的文体,在绘制上下两边的字,当然,我们也要设置一个手势监听,用于监听用户按下,滑动,抬起的时候,的一个操作,我们会根据手指往上移动和向下移动距离的多少来判断显示那个文字,选中了那个。

源码下载:Android自定义滚动选择器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

iphone – 将自定义选择器添加到UIBarButtonItem

iphone – 将自定义选择器添加到UIBarButtonItem

我是一个iOS新手我有一个导航栏按钮,当点击应该执行我自己的功能.最好的方法是什么?

UIBarButtonItem *doneBarButtonItem=[[UIBarButtonItem alloc] init];
doneBarButtonItem.title=@"Done";
self.navigationItem.rightBarButtonItem = doneBarButtonItem;
[doneBarButtonItem release];

解决方法

一种方法是初始化目标和操作:

UIBarButtonItem *buttonHello = [[UIBarButtonItem alloc] initWithTitle:@"Say Hello"     
    style:UIBarButtonItemStyleBordered target:self action:@selector(sayHello:)];

另一种方法是在创建目标和动作后设置它

[buttonHello setTarget:self];
[buttonHello setAction:@selector(sayHello:)];

目标是将被调用的对象的实例.在self的情况下,该方法将在该对象的实例上.

Action是被调用的方法.通常,您可以使用IBAction来装饰它,以向设计师提示它是一个动作.它编译失效.

- (IBAction)sayHello:(id)sender
{
    // code here
}

iPhone如何导出通讯录(怎样导出iPhone通讯录)

iPhone如何导出通讯录(怎样导出iPhone通讯录)

iPhone如何导出通讯录(怎样导出iPhone通讯录)

备份对于大多数人来说可能没有这个习惯,但是在丢失通讯录里的联系人时,才急急忙忙来咨询“怎么找回通讯录里的联系人呀?”虽然有软件可以找回丢失的通讯录联系人,但是做好备份是个好习惯,那么,备份通讯录有哪些方法?iPhone如何导出通讯录?



第一种:通过iCloud合并通讯录备份


不管您的iPhone手机是坏了还是需要换新手机,还是只是单纯想要做个通讯录备份,都可以通过iCloud合并通讯录,iCloud虽然只有5G的免费存储空间,但是由于通讯录的占用空间不会很大,所以建议长期使用iCloud备份通讯录的数据,一起看看如何合并通讯录吧!


步骤一:打开手机上的设置,进入【Apple ID】,在Apple ID中点击【iCloud】。



第二步:在iCloud中找到【通讯录】,并关闭或打开通讯录,如果您的通讯录本身就是开启状态,那么需要选择【保留在我的iPhone上】这个选项,然后将通讯录再次打开,点击【合并】;如果您的通讯录本身就是关闭状态,那么就需要打开,然后点击【合并】即可。



第二种:通过SIM卡导入通讯录


这种方法适用于安卓手机更换为iPhone手机的情况,由于两种手机是不同的系统,所以要通过SIM卡的形式导入通讯录进行备份。


首先将安卓手机上的SIM卡插入到iPhone手机上,然后打开iPhone手机的设置,下滑手机屏幕,找到【通讯录】并点击进去,最后点击【导入SIM卡通讯录】即可完成安卓手机到iPhone手机的通讯录备份。



第三种:通过专业的数据恢复软件恢复通讯录


如果您的通讯录的联系人已经是真的丢失了,通过以上两种方法都找不回来的情况下,那么,您可以通过专业的数据恢复软件恢复通讯录,而小编今天要给大家推荐一款非常好用的数据恢复软件,名字叫数据蛙苹果恢复专家,专门针对苹果手机而推出的数据恢复软件,并且能够全面扫描苹果设备,包括iPhone和iPad,具备免费扫描版本,能够扫描出手机上的多种设备,包括微信、QQ、WhatsApp、照片、视频、通讯录、备忘录等数据,到底如何找回呢?操作步骤如下:


步骤一:在常用电脑上安装这款软件,并且保证电脑空间充足。


步骤二:安装完毕后,打开软件,使用数据线将手机连接到电脑上,如果软件无法显示连接,可以尝试重新插入数据线或者重新打开软件,显示【设备已连接】,点击【开始扫描】即可。



步骤三:整个扫描过程会因为不同的数据导致扫描的时长不一,可能需要较为漫长的等待,请耐心一点。

步骤四:等待扫描结束后,在软件的左侧应用栏可以找到【通讯录】并点击进去,找到丢失的联系人,勾选好,点击【还原到设备】或者【恢复】即可。



以上就是三种情形之下的通讯录备份以及找回通讯录,每种情形都针对不一样的需求,根据自己的需求进行操作即可成功备份或找回通讯录,如果您的手机一直都是iPhone手机的话就直接使用第一种方法进行备份即可。

iphone通讯录传给华为

iphone通讯录传给华为

直接方法:使用 airdrop(适用于较新的设备):打开 airdrop,选择要传输的联系人,点击“共享”和“airdrop”。使用华为的共享联系人功能:选择联系人,点击“共享”并选择“共享联系人”。间接方法:使用 icloud:启用 iphone 上的“通讯录”,并在华为云服务应用中启用“通讯录”。使用 google 账号:在 iphone 上启用“通讯录”,在华为手机上导入从 google 账号。使用第三方应用:下载并按照应用内的说明将联系人从 iphone 传输到华为手机。

iphone通讯录传给华为

如何将 iPhone 通讯录传输到华为手机

直接方法:

  • 使用 AirDrop(仅限于较新的华为和 Apple 设备):

    • 打开 iPhone 和华为手机上的 AirDrop 功能。
    • 选择要传输的联系人并点击“共享”。
    • 在华为手机上点击“AirDrop”。
  • 使用共享联系人功能(华为手机):

    • 打开华为手机的“联系人”应用。
    • 选择要传输的联系人,然后点击右上角的“共享”。
    • 选择“共享联系人”并选择传输方式(如蓝牙、电子邮件或 WhatsApp)。

间接方法:

  • 使用 iCloud(需要 Apple ID):

    • 在 iPhone 上,转到“设置”>“Apple ID”>“iCloud”。
    • 启用“通讯录”选项。
    • 在华为手机上,下载华为云服务应用并登录您的华为 ID。
    • 打开应用,前往“云同步”,然后启用“通讯录”选项。
  • 使用 Google 账号:

    • 在 iPhone 上,转到“设置”>“邮件、通讯录、日历”。
    • 添加您的 Google 账号。
    • 打开“通讯录”,然后启用“通讯录”选项。
    • 在华为手机上,打开“通讯录”应用。
    • 点击左上方的“添加”按钮,然后选择“导入/导出”。
    • 选择“从其他设备导入”并选择您的 Google 账号。
  • 使用第三方应用:

    • 从应用商店下载一个联系人传输应用,例如“SyncMate”、“Copy My Data”或“PhoneTrans”。
    • 按照应用内的说明将联系人从 iPhone 传输到华为手机。

以上就是iphone通讯录传给华为的详细内容,更多请关注php中文网其它相关文章!

关于仿iPhone通讯录制作小程序自定义选择组件仿iphone通讯录制作小程序自定义选择组件的介绍现已完结,谢谢您的耐心阅读,如果想了解更多关于Android仿iphone自定义滚动选择器、iphone – 将自定义选择器添加到UIBarButtonItem、iPhone如何导出通讯录(怎样导出iPhone通讯录)、iphone通讯录传给华为的相关知识,请在本站寻找。

本文标签: