Android 时间轴的实现

实现Android回放功能下的时间轴的绘制

1.思路  横向的滑动  那我们就会想到HorizontalScrollView这个控件来实现的横向的滑动 ,

那我们就需要先画出布局,但是HorizontalScrollView 是没有滑动监听事件的,那我们就需要

重写HorizontalScrollView获取他的滑动监听,应为技术菜,自己也不会 所以就网上找了一下(这是转载别人的,出处没有,因为那里都有)


import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.HorizontalScrollView;

public class ScrollListenerHorizontalScrollView extends HorizontalScrollView
{
    
    public ScrollListenerHorizontalScrollView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        // TODO Auto-generated constructor stub
    }
    
    public ScrollListenerHorizontalScrollView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
        // TODO Auto-generated constructor stub
    }
    
    public ScrollListenerHorizontalScrollView(Context context)
    {
        super(context);
        // TODO Auto-generated constructor stub
    }
    
    public interface ScrollViewListener
    {
        
        void onScrollChanged(ScrollType scrollType);
        
    }
    
    private Handler mHandler;
    
    private ScrollViewListener scrollViewListener;
    
    
    /**
     * 滚动状态 IDLE 滚动停止 TOUCH_SCROLL 手指拖动滚动 FLING滚动
     * @version XHorizontalScrollViewgallery
     * @author DZC
     * @Time 2014-12-7 上午11:06:52
     *
     *
     */
    public enum ScrollType
    {
        IDLE, TOUCH_SCROLL, FLING
    };
    
    /**
     * 记录当前滚动的距离
     */
    private int currentX = -9999999;
    
    /**
     * 当前滚动状态
     */
    private ScrollType scrollType = ScrollType.IDLE;
    
    /**
     * 滚动监听间隔
     */
    private int scrollDealy = 50;
    
    /**
     * 滚动监听runnable
     */
    private Runnable scrollRunnable = new Runnable()
    {
        
        @Override
        public void run()
        {
            // TODO Auto-generated method stub
            if (getScrollX() == currentX)
            {
                // 滚动停止 取消监听线程
                Log.d("", "停止滚动");
                scrollType = ScrollType.IDLE;
                if (scrollViewListener != null)
                {
                    scrollViewListener.onScrollChanged(scrollType);
                }
                mHandler.removeCallbacks(this);
                return;
            }
            else
            {
                // 手指离开屏幕 view还在滚动的时候
                Log.d("", "Fling。。。。。");
                scrollType = ScrollType.FLING;
                if (scrollViewListener != null)
                {
                    scrollViewListener.onScrollChanged(scrollType);
                }
            }
            currentX = getScrollX();
            mHandler.postDelayed(this, scrollDealy);
        }
    };
    
    @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        switch (ev.getAction())
        {
            case MotionEvent.ACTION_MOVE:
                this.scrollType = ScrollType.TOUCH_SCROLL;
                scrollViewListener.onScrollChanged(scrollType);
                // 手指在上面移动的时候 取消滚动监听线程
                mHandler.removeCallbacks(scrollRunnable);
                break;
            case MotionEvent.ACTION_UP:
                // 手指移动的时候
                mHandler.post(scrollRunnable);
                break;
        }
        return super.onTouchEvent(ev);
    }
    
    /**
     * 必须先调用这个方法设置Handler 不然会出错
     * 
     * @author DZC
     * @return void
     * @param handler
     * @TODO
     */
    public void setHandler(Handler handler)
    {
        this.mHandler = handler;
    }
    
    /**
     * 设置滚动监听
     * 
     * @author DZC
     * @return void
     * @param listener
     * @TODO
     */
    public void setOnScrollStateChangedListener(ScrollViewListener listener)
    {
        this.scrollViewListener = listener;
    }
    
}
然后是 首页的布局

<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" >

    <TextView
        android:id="@+id/now_time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:textColor="@android:color/white"
        android:textSize="20sp" />

    <com.example.test.ScrollListenerHorizontalScrollView
        android:id="@+id/view"
        android:layout_width="fill_parent"
        android:layout_height="80dp"
        android:layout_below="@+id/now_time"
        android:scrollbars="none" >

        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="match_parent"
            android:background="#ffffff" >

            <LinearLayout
                android:id="@+id/flipper1"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal" />
        </RelativeLayout>
    </com.example.test.ScrollListenerHorizontalScrollView>

    <View
        android:layout_width="1dp"
        android:layout_height="80dp"
        android:layout_below="@+id/now_time"
        android:layout_centerHorizontal="true"
        android:background="#DC143C" />

</RelativeLayout>
下面 我们就开始绘制图像了,然而我这边的处理是将一个片段一个片的链接成时间轴的,所以又需要item的布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <RelativeLayout
        android:id="@+id/gaodu"
        android:layout_width="120dp"
        android:layout_height="wrap_content" >

        <TextView
            android:id="@+id/ling"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="00"
            android:textColor="#DC143C"
            android:textSize="18sp" />

        <RelativeLayout
            android:id="@+id/line"
            android:layout_width="120dp"
            android:layout_height="1dp"
            android:layout_below="@+id/ling"
            android:layout_marginTop="10dp"
            android:background="@color/timeline_light_grey" />

        <TextView
            android:id="@+id/zheng"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:textColor="#DC143C"
            android:textSize="18sp" />

        <RelativeLayout
            android:id="@+id/shu"
            android:layout_width="1dp"
            android:layout_height="10dp"
            android:layout_alignParentRight="true"
            android:layout_below="@+id/zheng"
            android:background="@color/timeline_light_grey" />

        <RelativeLayout
            android:id="@+id/play_line"
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:layout_below="@+id/line"
            android:layout_marginTop="10dp"
            android:background="@color/timeline_light_grey" />
    </RelativeLayout>

</RelativeLayout>
最后就是功能的实现了

import com.example.test.ScrollListenerHorizontalScrollView.ScrollType;
import com.example.test.ScrollListenerHorizontalScrollView.ScrollViewListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;

@SuppressLint({"InflateParams", "ClickableViewAccessibility", "HandlerLeak"})
public class MainActivity extends Activity
{
    // 时间刻度的布局
    private LinearLayout flipper1;
    
    // 横向滑动的scroll
    private ScrollListenerHorizontalScrollView scrollView;
    
    // 整個時間軸的总长度
    private int maxlength = 0;
    
    // 可滑动最大距离
    private int scroll_max = 0;
    
    // 屏幕的宽度
    private int phone_wegith;
    
    // 用于HorizontalScrollView监听事件的handler
    private Handler handler = new Handler();
    
    // 每一个单位的秒数
    private int m;
    
    private DelayThread thread;
    
    private TextView now_time;
    
    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        flipper1 = (LinearLayout)findViewById(R.id.flipper1);
        now_time = (TextView)findViewById(R.id.now_time);
        scrollView = (ScrollListenerHorizontalScrollView)findViewById(R.id.view);
        scrollView.setHandler(handler);
        // 获取手机屏幕的宽度
        WindowManager wm = this.getWindowManager();
        phone_wegith = wm.getDefaultDisplay().getWidth();
        scrollView.setScrollContainer(false);
        for (int i = 0; i < 28; i++)
        {
            addView(i);
        }
        thread = new DelayThread();
        thread.start();
        scrollView.setOnScrollStateChangedListener(new ScrollViewListener()
        {
            @Override
            public void onScrollChanged(final ScrollType scrollType)
            {
                handler = new Handler()
                {
                    @Override
                    public void handleMessage(Message msg)
                    {
                        super.handleMessage(msg);
                        now_time.setText(DateUtil.date(m * scrollView.getScrollX()));
                        if (scrollType == ScrollType.IDLE)
                        {
                            //停止滑动的状态
                            m = 86400 / scroll_max;
                        }
                        if(scrollType==ScrollType.FLING)
                        {
                           //处于正在滑动的状态
                            
                        }
                        
                    }
                };
               
            }
        });
    }
    
    /**
     * 添加时间轴的布局
     */
    @SuppressLint("NewApi")
    private void addView(int i)
    {
        View view = LayoutInflater.from(this).inflate(R.layout.item, null);
        TextView text = (TextView)view.findViewById(R.id.zheng);
        text.setText((i - 1) + ":");
        TextView ling = (TextView)view.findViewById(R.id.ling);
        RelativeLayout play_line = (RelativeLayout)view.findViewById(R.id.play_line);
        RelativeLayout line = (RelativeLayout)view.findViewById(R.id.line);
        RelativeLayout shu = (RelativeLayout)view.findViewById(R.id.shu);
        
        // 获取view的宽高 此方法会加载onMeasure三次
        int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        int h = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
        view.measure(w, h);
        int width = view.getMeasuredWidth();
        maxlength = maxlength + width;
        if (i == 0)
        {
            ling.setVisibility(View.INVISIBLE);
            line.setVisibility(View.INVISIBLE);
            play_line.setVisibility(View.INVISIBLE);
            text.setVisibility(View.INVISIBLE);
            // phone_wegith / 2 - width 屏幕一半的宽度 减去view的宽度 得到的值给予第一个view 从而使得时间轴正好对着初始0的位置
            LayoutParams l = new LayoutParams(phone_wegith / 2 - width, RelativeLayout.LayoutParams.MATCH_PARENT);
            view.setLayoutParams(l);
            
        }
        else if (i == 1)
        {
            ling.setVisibility(View.INVISIBLE);
            line.setVisibility(View.INVISIBLE);
            play_line.setVisibility(View.INVISIBLE);
        }
        else if (i == 26)
        {
            text.setVisibility(View.INVISIBLE);
            line.setVisibility(View.INVISIBLE);
            shu.setVisibility(View.INVISIBLE);
            play_line.setVisibility(View.INVISIBLE);
        }
        
        else if (i == 27)
        {
            // phone_wegith / 2 - width 屏幕一半的宽度 减去view的宽度 得到的值给予第一个view 从而使得时间轴正好对着最后24的位置
            LayoutParams l = new LayoutParams(phone_wegith / 2 - width, RelativeLayout.LayoutParams.MATCH_PARENT);
            view.setLayoutParams(l);
            text.setVisibility(View.INVISIBLE);
            line.setVisibility(View.INVISIBLE);
            shu.setVisibility(View.INVISIBLE);
            play_line.setVisibility(View.INVISIBLE);
            ling.setVisibility(View.INVISIBLE);
        }
        else
        {
            play_line.setVisibility(View.VISIBLE);
            scroll_max = scroll_max + width;
        }
        flipper1.addView(view);
    }
    
    @Override
    protected void onStart()
    {
        super.onStart();
    }
    
    @Override
    protected void onResume()
    {
        super.onResume();
    }
    
    /**
     * 线程用于监控滑动状态 以及后去滑动后的值
     */
    class DelayThread extends Thread
    {
        public void run()
        {
            while (true)
            {
                try
                {
                    sleep(100);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
                handler.sendEmptyMessage(0);
            }
        }
    }
    
}

写的不好,勿怪,只是给你们一个参考,有什么不好的不要说 不要问,谢谢!

效果图




  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: 实现 Android 时间轴 ListView 的 UI 界面可以分为以下几个步骤: 1. 定义布局文件:定义一个 ListView,并在 ListView 的 item 中添加需要展示的内容,如时间轴的线、时间轴上的圆圈、时间、内容等。 2. 定义数据源:定义一个数据源,存储需要展示的数据,如时间、内容等。 3. 创建 Adapter:创建一个 Adapter,将数据源中的数据绑定到 ListView 的 item 上。 4. 设置 ListView:将 Adapter 设置给 ListView,完成 ListView 的初始化。 以下是一个简单的实现代码: 1. 布局文件 timeline_item.xml ``` <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:padding="20dp"> <!-- 时间轴的线 --> <View android:layout_width="1dp" android:layout_height="match_parent" android:layout_marginLeft="8dp" android:layout_marginRight="8dp" android:background="@color/colorAccent" /> <!-- 时间轴上的圆圈 --> <View android:id="@+id/circle" android:layout_width="20dp" android:layout_height="20dp" android:background="@drawable/circle" android:gravity="center" /> <!-- 时间和内容 --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="8dp" android:orientation="vertical"> <TextView android:id="@+id/time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="2019-01-01" /> <TextView android:id="@+id/content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="这是内容" /> </LinearLayout> </LinearLayout> ``` 2. 数据源 TimelineItem.java ``` public class TimelineItem { private String time; private String content; public TimelineItem(String time, String content) { this.time = time; this.content = content; } public String getTime() { return time; } public void setTime(String time) { this.time = time; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } } ``` 3. Adapter TimelineAdapter.java ``` public class TimelineAdapter extends BaseAdapter { private Context context; private List<TimelineItem> itemList; public TimelineAdapter(Context context, List<TimelineItem> itemList) { this.context = context; this.itemList = itemList; } @Override public int getCount() { return itemList.size(); } @Override public Object getItem(int position) { return itemList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder; if (convertView == null) { convertView = LayoutInflater.from(context).inflate(R.layout.timeline_item, null); viewHolder = new ViewHolder(); viewHolder.time = convertView.findViewById(R.id.time); viewHolder.content = convertView.findViewById(R.id.content); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } TimelineItem item = itemList.get(position); viewHolder.time.setText(item.getTime()); viewHolder.content.setText(item.getContent()); return convertView; } static class ViewHolder { TextView time; TextView content; } } ``` 4. Activity 实现 ``` public class MainActivity extends AppCompatActivity { private ListView listView; private TimelineAdapter adapter; private List<TimelineItem> itemList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { listView = findViewById(R.id.list_view); } private void initData() { itemList = new ArrayList<>(); itemList.add(new TimelineItem("2020-01-01", "这是内容1")); itemList.add(new TimelineItem("2020-02-01", "这是内容2")); itemList.add(new TimelineItem("2020-03-01", "这是内容3")); itemList.add(new TimelineItem("2020-04-01", "这是内容4")); itemList.add(new TimelineItem("2020-05-01", "这是内容5")); itemList.add(new TimelineItem("2020-06-01", "这是内容6")); itemList.add(new TimelineItem("2020-07-01", "这是内容7")); itemList.add(new TimelineItem("2020-08-01", "这是内容8")); itemList.add(new TimelineItem("2020-09-01", "这是内容9")); itemList.add(new TimelineItem("2020-10-01", "这是内容10")); adapter = new TimelineAdapter(this, itemList); listView.setAdapter(adapter); } } ``` 以上就是一个简单的 Android 时间轴 ListView 实现的过程。 ### 回答2: Android 时间轴 ListView 是一种使用 ListView 组件实现时间轴效果的 UI 界面。它通常用于显示某个时间段内的事件或活动,并按照时间顺序排列。 要实现 Android 时间轴 ListView 的 UI 界面,可以按照以下步骤进行: 1. 创建一个布局文件,可以使用 LinearLayout 或 RelativeLayout 作为根布局。根据需要设置好背景颜色和布局方向。 2. 在布局文件中添加一个 ListView 组件,用于显示时间轴的事件列表。设置好宽度、高度和布局位置。 3. 创建一个自定义的适配器类,继承自 ArrayAdapter 或 BaseAdapter,并重写其中的方法。适配器负责将数据绑定到 ListView 上,每个列表项都会有一个时间和事件的相关信息。可以使用自定义的布局文件作为列表项的外观。 4. 在自定义适配器的 getView() 方法中,将数据绑定到列表项的布局文件上。可以使用 TextView 或自定义的 View 组件显示时间和事件信息。 5. 在主活动中,实例化自定义适配器,并将其设置为 ListView 的适配器。通过获取事件数据,将其传递给适配器的构造函数。 6. 最后,在主活动中设置 ListView 的点击事件监听器,以便在用户点击某个列表项时可以执行相应的操作。 通过以上步骤,我们就可以实现一个基本的 Android 时间轴 ListView 的 UI 界面。根据实际需求,还可以对列表项进行更多的样式和交互效果的定制。 ### 回答3: Android时间轴ListView是一种特殊的ListView控件,可以按照时间顺序展示数据,并且能够实现类似时间轴的效果。实现时间轴ListView的UI界面,可以按照以下步骤操作: 1. 导入相关依赖库:在项目的build.gradle文件中添加依赖库,例如: ``` implementation 'com.github.vipulasri:timelineview:1.1.0' ``` 2. 在布局文件中定义ListView控件,例如: ```xml <ListView android:id="@+id/timelineListView" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` 3. 创建数据源:根据需求,创建一个数据源,每个数据项包含时间和内容等信息。 4. 自定义ListView的item布局:根据需求,设计并创建ListView的item布局文件,可以使用LinearLayout或RelativeLayout等容器布局,添加显示时间和内容的TextView控件。 5. 创建适配器:创建一个继承自ArrayAdapter或BaseAdapter的适配器类,重写getView()方法,将数据源中的数据绑定到ListView的item布局中。 6. 设置ListView的适配器:在Activity或Fragment中获取ListView对象,并将适配器与ListView关联,例如: ```java ListView listView = findViewById(R.id.timelineListView); listView.setAdapter(adapter); ``` 7. 实现时间轴效果:如果要实现时间轴效果,可以结合使用自定义控件TimelineView,通过设置其属性来控制item的样式,例如: ```java TimelineView timelineView = findViewById(R.id.timelineView); timelineView.setTimelineViewType(TimelineView.TYPE_START); ``` 通过以上步骤,我们可以实现一个简单的Android时间轴ListView的UI界面。根据具体需求,还可以进行样式定制以及添加其他功能,以满足项目的需求。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值