Android自定义屏幕侧边字母排序控件

看图片右侧字母排序的控件,触摸上面的字母,可迅速跳至指定字母分类,配合上一篇汉字转拼音,可以实现此功能。

侧栏字母排序图

如下代码,新建类,可copy直接使用。

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;

/**
 * 根据字母形成的索引栏 测试
 *
 * Created by yangxiix on 2015/11/16.
 */
public class LetterIndexBar extends View {

    private String[] mIndexer = {"A", "B", "C", "D", "E", "F", "G", "H",
            "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U",
            "V", "W", "X", "Y", "Z", "#"};
    private int height;
    private int curChoose = -1; //当前选中

    private OnTouchingLetterChangedListener onTouchingLetterChangedListener;

    private Paint mPaint;

    public LetterIndexBar(Context context) {
        this(context, null);
    }

    public LetterIndexBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public LetterIndexBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        initData(canvas);
    }

    private void initData(Canvas canvas) {
        DisplayMetrics dm = getResources().getDisplayMetrics();
        float density = dm.density; //像素密度
        int width = getWidth();
        height = getHeight();
        int perHeight = height / mIndexer.length;

        canvas.drawColor(Color.parseColor("#FFC0CB"));  //设置背景栏
        mPaint = new Paint();

        for (int i = 0; i < mIndexer.length; i++) {
            if (curChoose != -1 && i == curChoose) {
                mPaint.setTextSize(12 * density);
                mPaint.setColor(Color.parseColor("#FFFFFF"));   //设置选中后的颜色
                mPaint.setAntiAlias(true);  //是否反锯齿
                canvas.drawText(mIndexer[i], width / 2f - mPaint.measureText(mIndexer[i]) / 2f, perHeight + perHeight * i, mPaint);
            } else {
                mPaint.setTextSize(12 * density);
                mPaint.setColor(Color.parseColor("#FF0000"));   //正常的颜色
                mPaint.setAntiAlias(true);  //是否反锯齿
                canvas.drawText(mIndexer[i], width / 2f - mPaint.measureText(mIndexer[i]) / 2f, perHeight + perHeight * i, mPaint); //文字居中显示,宽度的一半 + 文体的一半
            }
            mPaint.reset();
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        float posY = event.getY();
        final int oldChoose = curChoose;
        int curLetterPos = (int) (posY / height * mIndexer.length);
        final OnTouchingLetterChangedListener listener = onTouchingLetterChangedListener;

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (oldChoose != curLetterPos && listener != null) {
                    if (curLetterPos < mIndexer.length && curLetterPos >= 0) {
                        listener.onTouchingLetterChanged(mIndexer[curLetterPos]);
                        curChoose = curLetterPos;
                        invalidate();
                    }
                }
                break;

            case MotionEvent.ACTION_MOVE:
                if (oldChoose != curLetterPos && listener != null) {
                    if (curLetterPos < mIndexer.length && curLetterPos >= 0) {
                        listener.onTouchingLetterChanged(mIndexer[curLetterPos]);
                        curChoose = curLetterPos;
                        invalidate();
                    }
                }
                break;

            case MotionEvent.ACTION_UP:
                curChoose = -1;
                invalidate();
                break;
        }
        return true;
    }

    public void setOnTouchingLetterChangedListener(
            OnTouchingLetterChangedListener onTouchingLetterChangedListener) {
        this.onTouchingLetterChangedListener = onTouchingLetterChangedListener;
    }

    public interface OnTouchingLetterChangedListener {
        public void onTouchingLetterChanged(String s);
    }
}

我这边运行之后的效果是这样子的(颜色,字体都可以根据注释去改动):

运行之后效果

如果你想做成颜色,字体大小由布局去实现你可以做如下小小的改进即可
效果

定义一个attr.xml
里面定义代码:

<declare-styleable name="IndexerBar">
        <attr name="show_common_icon" format="boolean" />
</declare-styleable>

然后在自定义的控件里面初始化时获取相关参数:

TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.IndexerBar);
boolean show_common_icon = ta.getBoolean(R.styleable.IndexerBar_show_common_icon, true);

然后就可以用相关定义的参数啦,动动脑,定义字体大小颜色可以用此类似方法。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: WPF是一种用于创建Windows桌面应用程序的框架,它提供了许多控件和功能来创建交互式界面。如果我们需要在WPF应用程序中自定义侧边导航,可以按照以下步骤进行操作: 1. 创建侧边导航的布局:可以使用WPF中的Grid或StackPanel控件来创建一个垂直的侧边导航栏,其中包含导航项的按钮或列表。 2. 设置导航项的样式:可以自定义按钮的外观,例如背景颜色、字体颜色和大小,以及按钮的左侧图标。使用WPF的Style和Trigger来设置按钮的不同状态下的外观效果,例如鼠标悬停或点击时的效果。 3. 绑定导航项到页面:在创建导航项的按钮或列表时,可以使用WPF的Command属性将导航命令与按钮或列表项的点击事件关联起来。这样,在用户点击导航项时,将触发相应的命令并导航到对应的页面。 4. 创建页面内容:根据导航项的点击事件,我们可以在主窗口的内容区域加载不同的页面内容。可以使用WPF中的Frame控件来承载页面内容,并使用不同的页面来填充Frame控件,以实现导航功能。 5. 设计页面导航逻辑:可以在应用程序中设计导航逻辑,例如在导航到不同页面时进行权限验证、显示页面切换动画等。使用WPF的Page和Frame控件配合使用,可以实现页面之间的无缝切换和导航。 通过以上步骤,我们可以在WPF应用程序中自定义一个侧边导航,使用户能够方便地切换不同的页面内容。这样的自定义侧边导航可以提升用户体验,并增加应用程序的交互性。 ### 回答2: WPF是一种用于创建Windows桌面应用程序的技术,它允许开发者使用XAML语言和C#或VB.NET代码来构建用户界面。在WPF中,可以自定义侧边导航以提供更好的用户体验。 要创建自定义侧边导航,首先需要在WPF窗口中添加一个导航栏容器,可以使用StackPanel或WrapPanel等控件。然后,可以在导航栏容器中添加按钮或菜单项,用于作为导航的选项。 接下来,为每个导航选项创建一个页面。页面可以通过使用WPF的Page或UserControl来创建。可以为页面添加标识符或属性来表示其对应的导航选项。 然后,在侧边导航的按钮或菜单项的点击事件中,使用导航框架(如Frame或NavigationWindow)加载对应的页面。导航框架将负责显示和管理页面的导航。 为了提供更好的用户体验,可以为选中的导航选项添加高亮效果,以便用户知道当前所在的导航选项。可以使用样式或触发器来实现这一效果。 此外,还可以根据需要添加额外的功能,如在导航选项上添加图标或说明文本,或者使用动画效果来改善导航的过渡效果。 总结起来,自定义WPF侧边导航需要在WPF窗口中添加导航栏容器,创建导航选项和相应的页面,使用导航框架进行页面的导航,为选中的导航选项添加高亮效果,并根据需要添加其他功能来提升用户体验。通过这些步骤,可以实现一个自定义侧边导航,为应用程序提供直观和简洁的导航界面。 ### 回答3: WPF是Windows Presentation Foundation的缩写,是一种用于创建Windows桌面应用程序的.NET框架。WPF提供了丰富的可视化元素和灵活的布局系统,使开发者能够构建功能强大、交互性强的应用程序。 自定义侧边导航是WPF中常见的需求之一,可以通过以下步骤实现: 首先,创建一个主窗口容器,可以使用Grid或其他适当的布局容器。在主窗口的侧边位置放置一个StackPanel作为导航栏容器。 然后,通过创建自定义的UserControl来表示每个导航条目。在这个UserControl中,可以添加一个Button来表示条目的按钮,并将其样式设置为适当的样式。还可以添加一个TextBlock或其他适当的元素来显示条目的标题。 在主窗口容器的侧边导航栏StackPanel中,使用多个自定义的导航条目UserControl来表示不同的导航选项。可以通过设置每个导航条目UserControl的属性来设置其显示的标题和按钮样式。 在导航条目的按钮的Click事件中,可以在主窗口中的内容区域切换不同的页面。可以使用Frame或其他适当的控件作为内容区域容器,并将其导航源设置为所需的页面。 最后,根据需要可以添加一些动画效果或交互功能来增强侧边导航的用户体验。例如,可以在导航条目被选中时,修改按钮样式或显示选中状态的指示。 总之,通过创建自定义的UserControl来表示每个导航条目,并在主窗口中的内容区域动态切换页面,可以实现WPF中的自定义侧边导航。这样用户就可以通过点击导航栏中的按钮来方便地浏览和切换不同的页面内容。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值