android - 在搜索栏中创建垂直线

标签 android android-canvas paint android-seekbar

我正在尝试创建类似这样的东西 this .问题是如何在搜索栏附近创建垂直线。我尝试了给定的代码 here , 但搜索栏线消失了。任何帮助,将不胜感激。这是我到目前为止所做的。

 public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            SeekBar sb = (SeekBar)findViewById(R.id.seekBar1);



            //Get the width of the main view.
            Display display = getWindowManager().getDefaultDisplay();
            Point displaysize = new Point();
            display.getSize(displaysize);
            int width = displaysize.x;




            //set the seekbar maximum (Must be a even number, having a remainder will cause undersirable results)
            //this variable will also determine the number of points on the scale.
            int seekbarmax = 10;




            int seekbarpoints = (width/seekbarmax); //this will determine how many points on the scale there should be on the seekbar


            //find the seekbar in the view, and set some behaviour properties
            SeekBar seekbar = (SeekBar)findViewById(R.id.seekBar1);


            //Set the seekbar to a max range of 10
            seekbar.setMax(seekbarmax);




            //Create a new bitmap that is the width of the screen
            Bitmap bitmap = Bitmap.createBitmap(width, 100, Bitmap.Config.ARGB_8888);
            //A new canvas to draw on.
            Canvas canvas = new Canvas(bitmap);


            //a new style of painting - colour and stoke thickness.
            Paint paint = new Paint();
            paint.setColor(Color.BLUE); //Set the colour to red
            paint.setStyle(Paint.Style.STROKE); //set the style
            paint.setStrokeWidth(1); //Stoke width


            Paint textpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            textpaint.setColor(Color.rgb(61, 61, 61));// text color RGB
            textpaint.setTextSize(28);// text size




            int point = 0; //initiate the point variable


            //Start a for loop that will loop seekbarpoints number of times.
            for (int i = 0; i < seekbarpoints; i++  ){




                if ((i%2)==0) {
                    //short line
                    point = point  + seekbarpoints;
                    canvas.drawLine(point, 30, point, 0, paint);
                    //drawLine(startx,startx,endy,endy)

            }


            //Create a new Drawable
            Drawable d = new BitmapDrawable(getResources(),bitmap);


            //Set the seekbar widgets background to the above drawable.
            seekbar.setProgressDrawable(d);





            }
        }

    }

最佳答案

我搜索了很长时间,只得到了绘制数字的答案。因此我决定自己做。我采用了只有步骤的解决方案,并通过添加间隔逻辑对其进行了扩展。

请看下图。

enter image description here

然后我成功地创建了一个带有间隔标签和垂直线的搜索栏。上图是我取得的成果。

但是,您可以在调整尺寸时对填充进行一些优化。

解决方案:

区间的 xml 文件:

seekbar_with_intervals_labels

<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textViewInterval"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerInParent="true"
    android:textColor="#707070"/>

XML 垂直分隔符:seekbar_vertical_lines

<?xml version="1.0" encoding="utf-8"?>

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/textViewVerticalLine"
    android:layout_width="1dp"
    android:layout_height="match_parent"
    android:background="@drawable/lines" />

然后是自定义的 Seekbar 类:

package com.example.abc.myapplication;

import java.util.List;
import java.util.concurrent.locks.ReadWriteLock;

import com.example.abc.myapplication.R;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class SeekbarWithIntervals extends LinearLayout {
    private RelativeLayout RelativeLayout = null;
    private SeekBar Seekbar = null;
    private RelativeLayout Divider = null;
    private View verticalLine = null;

    private int WidthMeasureSpec = 0;
    private int HeightMeasureSpec = 0;

    public SeekbarWithIntervals(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }

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

        getActivity().getLayoutInflater()
                .inflate(R.layout.seekbar_with_intervals, this);
    }

    private Activity getActivity() {
        return (Activity) getContext();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);

        verticalLine = new View(getActivity());
        verticalLine.setLayoutParams(new LayoutParams(2, LayoutParams.MATCH_PARENT));
        verticalLine.setBackgroundColor(Color.BLACK);

        if (changed) {
            alignIntervals();

            // We've changed the intervals layout, we need to refresh.
            RelativeLayout.measure(WidthMeasureSpec, HeightMeasureSpec);
            RelativeLayout.layout(RelativeLayout.getLeft(), RelativeLayout.getTop(), RelativeLayout.getRight(), RelativeLayout.getBottom());
        }
    }

    private void alignIntervals() {
        int widthOfSeekbarThumb = getSeekbarThumbWidth();
        int thumbOffset = widthOfSeekbarThumb / 2;

        int widthOfSeekbar = getSeekbar().getWidth();
        int firstIntervalWidth = getRelativeLayout().getChildAt(0).getWidth();
        int remainingPaddableWidth = widthOfSeekbar - firstIntervalWidth - widthOfSeekbarThumb;

        int numberOfIntervals = getSeekbar().getMax();
        int maximumWidthOfEachInterval = remainingPaddableWidth / numberOfIntervals;

        alignFirstInterval(thumbOffset);
        alignIntervalsInBetween(maximumWidthOfEachInterval);
        alignLastInterval(thumbOffset, maximumWidthOfEachInterval);
    }

    private int getSeekbarThumbWidth() {
        return getResources().getDimensionPixelOffset(R.dimen.seekbar_thumb_width);
    }

    private void alignFirstInterval(int offset) {
        TextView firstInterval = (TextView) getRelativeLayout().getChildAt(0);
        firstInterval.setPadding(offset - 10, 0, 0, 0);

        TextView firstLine = (TextView) getDivider().getChildAt(0);
        firstLine.setPadding(offset + 10, 0, 0, 0);
    }

    private void alignIntervalsInBetween(int maximumWidthOfEachInterval) {
        int widthOfPreviousIntervalsText = 0;
        int widthOfPreviousLine = 0;

        // Don't align the first or last interval.
        for (int index = 1; index < (getRelativeLayout().getChildCount() - 1); index++) {
            TextView textViewInterval = (TextView) getRelativeLayout().getChildAt(index);
            int widthOfText = textViewInterval.getWidth();

            // This works out how much left padding is needed to center the current interval.
            //int leftPadding = Math.round(maximumWidthOfEachInterval - (widthOfText / 2) - (widthOfPreviousIntervalsText / 2) - (widthOfText / 2));
            int leftPadding = Math.round(maximumWidthOfEachInterval - (widthOfText / 2) - (widthOfPreviousIntervalsText / 2) - (widthOfText / index ) + index + 5 * 5);

            textViewInterval.setPadding(leftPadding, 0, 0, 0);

            widthOfPreviousIntervalsText = widthOfText;

            TextView textViewLine = (TextView) getDivider().getChildAt(index);
            int widthOfLine = textViewLine.getWidth();

            // This works out how much left padding is needed to center the current interval.
            leftPadding = (maximumWidthOfEachInterval + (index + (maximumWidthOfEachInterval / 10)) - (index * 4)); //Math.round(maximumWidthOfEachInterval + (widthOfLine ) + (widthOfPreviousLine ));
            //leftPadding = Math.round((maximumWidthOfEachInterval - (widthOfPreviousLine / index) - (widthOfPreviousLine / index) - (widthOfPreviousLine / index)) + 10);
            textViewLine.setPadding(leftPadding , 0, 0, 0);

            widthOfPreviousLine = widthOfLine;
        }
    }

    private void alignLastInterval(int offset, int maximumWidthOfEachInterval) {
        int lastIndex = getRelativeLayout().getChildCount() - 1;

        TextView lastInterval = (TextView) getRelativeLayout().getChildAt(lastIndex);
        int widthOfText = lastInterval.getWidth();

        int leftPadding = Math.round(maximumWidthOfEachInterval - widthOfText - offset);
        lastInterval.setPadding(leftPadding + 20, 0, 0, 0);

        TextView lastLine = (TextView) getDivider().getChildAt(lastIndex);
        leftPadding = Math.round(maximumWidthOfEachInterval - (widthOfText / 5) - (widthOfText / 5) - (widthOfText / 5 ) + 3 * 10);
        lastLine.setPadding(leftPadding , 0, 0, 0);

    }

    protected synchronized void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        WidthMeasureSpec = widthMeasureSpec;
        HeightMeasureSpec = heightMeasureSpec;

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    public int getProgress() {
        return getSeekbar().getProgress();
    }

    public void setProgress(int progress) {
        getSeekbar().setProgress(progress);
    }

    public void setIntervals(List<String> intervals) {
        displayIntervals(intervals);
        getSeekbar().setMax(intervals.size() - 1);
    }

    private void displayIntervals(List<String> intervals) {
        int idOfPreviousInterval = 0;
        int idOfPreviousLine = 0;

        if (getRelativeLayout().getChildCount() == 0) {
            for (String interval : intervals) {
                TextView textViewInterval = createInterval(interval);
                alignTextViewToRightOfPreviousInterval(textViewInterval, idOfPreviousInterval);

                TextView textViewVerticaLine = createVerticalLine();
                alignTextViewToRightOfPreviousInterval(textViewVerticaLine, idOfPreviousLine);
                idOfPreviousLine = textViewVerticaLine.getId();

                idOfPreviousInterval = textViewInterval.getId();

                getRelativeLayout().addView(textViewInterval);
                getDivider().addView(textViewVerticaLine);

            }
        }
    }

    private TextView createInterval(String interval) {
        View textBoxView = (View) LayoutInflater.from(getContext())
                .inflate(R.layout.seekbar_with_intervals_labels, null);

        TextView textView = (TextView) textBoxView
                .findViewById(R.id.textViewInterval);

        textView.setId(View.generateViewId());
        textView.setText(interval);

        return textView;
    }

    private TextView createVerticalLine() {
        View textBoxView = (View) LayoutInflater.from(getContext())
                .inflate(R.layout.seekbar_vertical_lines, null);

        TextView textView = (TextView) textBoxView
                .findViewById(R.id.textViewVerticalLine);

        textView.setId(View.generateViewId());

        return textView;
    }


    private void alignTextViewToRightOfPreviousInterval(TextView textView, int idOfPreviousInterval) {
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);

        if (idOfPreviousInterval > 0) {
            params.addRule(RelativeLayout.RIGHT_OF, idOfPreviousInterval);
        }

        textView.setLayoutParams(params);
    }

    public void setOnSeekBarChangeListener(OnSeekBarChangeListener onSeekBarChangeListener) {
        getSeekbar().setOnSeekBarChangeListener(onSeekBarChangeListener);
    }

    private RelativeLayout getRelativeLayout() {
        if (RelativeLayout == null) {
            RelativeLayout = (RelativeLayout) findViewById(R.id.intervals);
        }

        return RelativeLayout;
    }

    private SeekBar getSeekbar() {
        if (Seekbar == null) {
            Seekbar = (SeekBar) findViewById(R.id.seekbar);
        }

        return Seekbar;
    }

    private RelativeLayout getDivider() {

        if (Divider == null) {
            Divider = (RelativeLayout) findViewById(R.id.fl_divider);
        }

        return Divider;
    }
}

然后是我们动态添加间隔的 MainActivity

public class MainActivity extends AppCompatActivity {

    private SeekbarWithIntervals SeekbarWithIntervals = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        List<String> seekbarIntervals = getIntervals();
        getSeekbarWithIntervals().setIntervals(seekbarIntervals);
    }

    private List<String> getIntervals() {
        return new ArrayList<String>() {{
            add("45");
            add("55");
            add("65");
            add("75");
            add("85");
            add("95");
        }};
    }

    private SeekbarWithIntervals getSeekbarWithIntervals() {
        if (SeekbarWithIntervals == null) {
            SeekbarWithIntervals = (SeekbarWithIntervals) findViewById(R.id.seekbarWithIntervals);
        }

        return SeekbarWithIntervals;
    }
}

您可以将填充物放在分隔线的底部,以便像您的图片那样将其向上推。

注意:您还可以使用一个布局来定义分隔线和数字布局。

关于android - 在搜索栏中创建垂直线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34327745/

相关文章:

android - 如何在 RectShape 或 OvalShape 中显示 Android Canvas ShapeDrawable 中的文本?

android - Android位图中的文本剪切

bitmap - 以编程方式截取屏幕截图时,Cardview 会失去其半径

java - 重写 JButton 中的 Paint() 方法

javascript - HTML5 Canvas 软笔刷

android - 有没有办法找到drawable的资源ID

android - 创建图标按钮 - Android

android - 在 AOSP 构建目录中找不到模拟器

android - Recycler View 正在加载错误的数据或从错误的位置加载数据

java - 如何在android中更改gif图片大小