android常用控件应用之文本框(TextView)特效

来源:互联网 发布:如何评价蒋方舟 知乎 编辑:程序博客网 时间:2024/04/30 13:40
常用控件应用之文本框(TextView)特效

1.TextView之跑马灯效果

     android:ellipsize属性使用之跑马灯效果        android:ellipsize        设置当文字过长时,该控件该如何显示。有如下值设置:        "start"—–省略号显示在开头        "end"——省略号显示在结尾        "middle"—-省略号显示在中间        "marquee" ——以跑马灯的方式显示(动画横向向左移动)                布局文件中给TextView加入如下属性即可:        android:ellipsize="marquee"         android:marqueeRepeatLimit="marquee_forever"        android:focusable="true"         android:focusableInTouchMode="true"
复制代码
<!--        布局文件中设置如下(完整代码稍后给出)-->  <TextView        android:id="@+id/marquee_effect"        android:layout_width="100dip"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        android:ellipsize="marquee"        android:focusable="true"        android:focusableInTouchMode="true"        android:marqueeRepeatLimit="marquee_forever"        android:singleLine="true"        android:text="@string/marquee_effect" />
复制代码

      如果一个页面想实现多个TextView同时跑马灯效果解决方案:给要跑动的textview加上如下代码就行了

textview.setSelected(true);

2.TextView之阴影效果(可在布局文件里加入如下属性进行设置也可通过程序设置)
        android:shadowDx——设置阴影横向坐标开始位置(相对于文本内容)
        android:shadowDy——设置阴影纵向坐标开始位置(相对于文本内容)
        android:shadowRadius——设置阴影的半径
        android:shadowColor——指定文本阴影的颜色

//关键代码(完整代码稍后给出)textview.setShadowLayer(2.5f, 15, -10, 0xff00ff00);

3.html标签设置样式效果

  补充:

  textView.setAutoLinkMask(Linkify.WEB_URLS);// 当文本内容中包含超链接格式的文本时,自动转换成超链接样式,点击会自动跳转到指定的网页
  textView.setAutoLinkMask(Linkify.PHONE_NUMBERS);//自动转手机号码点击它可进入系统拨号界面
  textView.setAutoLinkMask(Linkify.EMAIL_ADDRESSES);//自动转邮件地址点击它可发送邮件(要提前设置好自己的电子邮件)
  textView.setAutoLinkMask(Linkify.MAP_ADDRESSES);//自动转街道地址点击它可查看位置(前提已安装了google地图)
  textView.setAutoLinkMask(Linkify.ALL);//包括上面4种情况

  关键代码(完整代码稍后给出):

复制代码
     TextView tv = (TextView) findViewById(R.id.fromhtml_effect);        StringBuffer sb = new StringBuffer();        sb.append("<h1><font color='#ff0000'>Html标签方式:</font></h1>");        sb.append("<h6><b><i><font color='#00ff00'><a href='http://www.cnblogs.com/bravestarrhu/'>");        sb.append(getString(R.string.fromhtml_effect));        sb.append("</a></font></i></b></h6>");        tv.setText(Html.fromHtml(sb.toString()));        tv.setMovementMethod(LinkMovementMethod.getInstance());// 这句很重要,使超链接<a href>起作用
复制代码

4.TextView之动画效果(rotate旋转、alpha透明度、scale缩放、translate移动)

实现动画需要在res/anim目录下新建对应的xml文件(稍后给出)

  关键代码(完整代码稍后给出):

复制代码
     TextView tv = null;     // TextView旋转 动画效果        tv = (TextView) findViewById(R.id.rotate);                Animation mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.rotate);        tv.setAnimation(mAnimationRight);                // TextView透明度动画效果        tv = (TextView) findViewById(R.id.alpha);        mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.alpha);        tv.setAnimation(mAnimationRight);                // TextView缩放动画效果        tv = (TextView) findViewById(R.id.scale);        mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.scale);        tv.setAnimation(mAnimationRight);                // TextView移动动画效果        tv = (TextView) findViewById(R.id.translate);                mAnimationRight = AnimationUtils.loadAnimation(                        TextViewEffectActivity.this, R.anim.translate);        tv.setAnimation(mAnimationRight);
复制代码

5.TextView之霓虹灯效果

采用timer+TimerTask+Handler实现

主要用到SpannableStringBuilder对象

关键代码(完整代码稍后给出):

复制代码
// 霓虹灯效果(此段代码会使"光"变红色)String wholeContent = "欢迎光临";SpannableStringBuilder spannable = new SpannableStringBuilder(                wholeContent);spannable.setSpan(new ForegroundColorSpan(Color.RED), 2,                    3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); // 设置指定位置文字的颜色(索引0开始)
复制代码

6.TextView之包含图片的效果

实现步骤(1.构建ImageGetter;2.直接使用append进行追加)
        关键代码(完整代码稍后给出):

复制代码
     TextView tv = (TextView) findViewById(R.id.image_effect);        tv.setText(R.string.image_effect);        // 通过HTML标记获得res目录下指定的图片        ImageGetter imageGetter = new ImageGetter() {            @Override            public Drawable getDrawable(String source) {                int id = Integer.parseInt(source);                // 根据id从资源文件中获取图片对象                Drawable d = getResources().getDrawable(id);                d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());                return d;            }        };        tv.append(Html.fromHtml("<img src='" + R.drawable.log + "'/>",                imageGetter, null));
复制代码

上图:

                                      

    目录结构如下:

                                                        

完整代码:

1>清单文件AndroidManifest.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.bravestarr.app.textvieweffect"    android:versionCode="1"    android:versionName="1.0" >    <uses-sdk android:minSdkVersion="7" />    <application        android:icon="@drawable/ic_launcher"        android:label="@string/app_name" >        <activity            android:name=".TextViewEffectActivity"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>
复制代码

2>main.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <!--         android:ellipsize属性使用之跑马灯效果        android:ellipsize        设置当文字过长时,该控件该如何显示。有如下值设置:        "start"—–省略号显示在开头        "end"——省略号显示在结尾        "middle"—-省略号显示在中间        "marquee" ——以跑马灯的方式显示(动画横向向左移动)                关键代码:        android:ellipsize="marquee"         android:marqueeRepeatLimit="marquee_forever"        android:focusable="true"         android:focusableInTouchMode="true"                                如果一个页面想实现多个TextView同时跑马灯效果解决方案:代码中给要跑动的textview加上textview.setSelected(true);就行了    -->    <TextView        android:id="@+id/marquee_effect"        android:layout_width="100dip"        android:layout_height="wrap_content"        android:layout_gravity="center_horizontal"        android:ellipsize="marquee"        android:focusable="true"        android:focusableInTouchMode="true"        android:marqueeRepeatLimit="marquee_forever"        android:singleLine="true"        android:text="@string/marquee_effect" />    <!--         TextView之阴影效果        android:shadowDx——设置阴影横向坐标开始位置(相对于文本内容)        android:shadowDy——设置阴影纵向坐标开始位置(相对于文本内容)        android:shadowRadius——设置阴影的半径        android:shadowColor——指定文本阴影的颜色    -->    <TextView        android:id="@+id/shadow_effect"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:singleLine="true" />    <!-- html设置样式效果 -->    <TextView        android:id="@+id/fromhtml_effect"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:singleLine="true" />    <!-- 动画效果 -->    <TextView        android:id="@+id/alpha"        android:layout_width="wrap_content"        android:layout_height="wrap_content"         android:text="@string/alpha_animation_effect"        />    <TextView        android:id="@+id/rotate"        android:layout_width="wrap_content"        android:layout_height="wrap_content"         android:text="@string/rotate_animation_effect"/>    <TextView        android:id="@+id/scale"        android:layout_width="wrap_content"        android:layout_height="wrap_content"         android:text="@string/scale_animation_effect"/>    <TextView        android:id="@+id/translate"        android:layout_width="wrap_content"        android:layout_height="wrap_content"         android:text="@string/translate_animation_effect"/>    <!-- 霓虹灯效果 -->    <TextView        android:id="@+id/neonlights_effect"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <!-- 包含图片的效果 -->    <TextView        android:id="@+id/image_effect"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>
复制代码

3>strings.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><resources>    <string name="app_name">TextView效果集锦</string>    <string name="marquee_effect">跑马灯效果</string>    <string name="shadow_effect">阴影效果</string>    <string name="fromhtml_effect">fromhtml设置效果</string>    <string name="alpha_animation_effect">文本透明度动画效果</string>    <string name="rotate_animation_effect">文本旋转动画效果</string>    <string name="scale_animation_effect">文本缩放动画效果</string>    <string name="translate_animation_effect">文本移动动画效果</string>    <string name="neonlights_effect">霓虹灯效果</string>    <string name="image_effect">包含图片的TextView效果</string></resources>
复制代码

4>alpha.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" >    <alpha        android:duration="500"        android:fromAlpha="1.0"        android:toAlpha="0.0"         android:repeatCount="10"/></set><!--    fromAlpha:开始时透明度       toAlpha: 结束时透明度       duration:动画持续时间        应用:    例1:淡出效果    android:fromAlpha="1.0"    android:toAlpha="0.0"    例2:淡入效果    android:fromAlpha="0.0"    android:toAlpha="1.0"-->
复制代码

5>rotate.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><set>    <rotate        xmlns:android="http://schemas.android.com/apk/res/android"        android:duration="500"        android:fromDegrees="0"        android:interpolator="@android:anim/linear_interpolator"        android:pivotX="50%"        android:pivotY="50%"        android:repeatCount="10"        android:toDegrees="-90" /></set><!--      fromDegrees   动画开始时的角度     toDegrees     动画结束时物件的旋转角度,正代表顺时针       pivotX    属性为动画相对于物件的X坐标的开始位置    pivotY    属性为动画相对于物件的Y坐标的开始位置      duration:动画持续时间  -->
复制代码

6>scale.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android">     <scale       android:interpolator= "@android:anim/decelerate_interpolator"         android:fromXScale="0.0"         android:toXScale="1.5"         android:fromYScale="0.0"         android:toYScale="1.5"         android:pivotX="50%"         android:pivotY="50%"         android:startOffset="0"         android:duration="5000"     android:repeatCount="3"       android:repeatMode="reverse"     /> </set><!-- interpolator指定动画插入器,常见的有加速减速插入器accelerate_decelerate_interpolator,加速插入器accelerate_interpolator,减速插入器decelerate_interpolator。fromXScale,fromYScale,动画开始前X,Y的缩放,0.0为不显示,1.0为正常大小toXScale,toYScale,动画最终缩放的倍数,1.0为正常大小,大于1.0放大pivotX,pivotY动画起始位置,相对于屏幕的百分比,两个都为50%表示动画从屏幕中间开始startOffset,动画多次执行的间隔时间,如果只执行一次,执行前会暂停这段时间,单位毫秒duration,一次动画效果消耗的时间,单位毫秒,值越小动画速度越快repeatCount,动画重复的计数,动画将会执行该值+1次repeatMode,动画重复的模式,reverse为反向,当第偶次执行时,动画方向会相反。restart为重新执行,方向不变 -->
复制代码

7>translate.xml

复制代码
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"><translateandroid:fromXDelta="320"android:toXDelta="0"android:fromYDelta="480"android:toYDelta="0"android:duration="5000" android:repeatCount="10" /></set><!-- fromXDelta,fromYDelta起始时X,Y座标,屏幕右下角的座标是X:320,Y:480toXDelta,toYDelta动画结束时X,Y的座标 -->
复制代码

8>TextViewEffectActivity.java

复制代码
package com.bravestarr.app.textvieweffect;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.Timer;import java.util.TimerTask;import android.app.Activity;import android.graphics.Color;import android.graphics.drawable.Drawable;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.text.Html;import android.text.Html.ImageGetter;import android.text.method.LinkMovementMethod;import android.view.animation.Animation;import android.view.animation.AnimationUtils;import android.widget.TextView;import com.bravestarr.app.utils.SpannableStringBuilderUtils;/** * @Author BraveStarr * @QQ 1733259520 * @Blog http://www.cnblogs.com/bravestarrhu/,http://blog.sina.com.cn/ *       wanghubravestarr *  */public class TextViewEffectActivity extends Activity {    private static final int[] colors = new int[] { Color.RED, Color.GRAY,            Color.GREEN, Color.LTGRAY, Color.BLUE };    private int currColor = 0;// 当前第一个文字的颜色    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        TextView tv = null;        // 跑马灯效果文本框        tv = (TextView) findViewById(R.id.marquee_effect);        tv.setTextSize(28);        tv.setTextColor(0xffd0eeee);        tv.setSelected(true);// 要实现界面上有多个跑马灯时需要加入这句        // 阴影效果        tv = (TextView) findViewById(R.id.shadow_effect);        tv.setTextSize(28);        tv.setTextColor(0xffd0eeee);        tv.setText(R.string.shadow_effect);        tv.setShadowLayer(2.5f, 15, -10, 0xff00ff00);        // HTML标签实现效果         tv = (TextView) findViewById(R.id.fromhtml_effect);        // 当文本内容中包含超链接格式的文本时,自动转换成超链接样式,点击会自动跳转到指定的网页,文本框还能实现自动转手机号码/邮件/地图        // Linkify.PHONE_NUMBERS为自动转手机号码点击它可进入系统拨号界面        // Linkify.EMAIL_ADDRESSES为自动转邮件地址点击它可发送邮件(要提前设置好自己的电子邮件)        // Linkify.MAP_ADDRESSES为自动转街道地址点击它可查看位置(前提已安装了google地图)        // Linkify.ALL包括WEB_URLS、EMAIL_ADDRESSES、PHONE_NUMBERS和MAP_ADDRESSES        // tv.setAutoLinkMask(Linkify.WEB_URLS);        StringBuffer sb = new StringBuffer();        sb.append("<h1><font color='#ff0000'>Html标签方式:</font></h1>");        sb.append("<h6><b><i><font color='#00ff00'><a href='http://www.cnblogs.com/bravestarrhu/'>");        sb.append(getString(R.string.fromhtml_effect));        sb.append("</a></font></i></b></h6>");        tv.setText(Html.fromHtml(sb.toString()));        tv.setMovementMethod(LinkMovementMethod.getInstance());// 这句很重要,使超链接<a href>起作用             // TextView旋转 动画效果        tv = (TextView) findViewById(R.id.rotate);                Animation mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.rotate);        tv.setAnimation(mAnimationRight);                // TextView透明度动画效果        tv = (TextView) findViewById(R.id.alpha);        mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.alpha);        tv.setAnimation(mAnimationRight);                // TextView缩放动画效果        tv = (TextView) findViewById(R.id.scale);        mAnimationRight = AnimationUtils.loadAnimation(                TextViewEffectActivity.this, R.anim.scale);        tv.setAnimation(mAnimationRight);                // TextView移动动画效果        tv = (TextView) findViewById(R.id.translate);                mAnimationRight = AnimationUtils.loadAnimation(                        TextViewEffectActivity.this, R.anim.translate);        tv.setAnimation(mAnimationRight);                        // 霓虹灯效果,延时1秒转第一次,从此以后每隔1秒又开始执行执行        timer.schedule(task_neon, 1000, 1000);        // 包含图片的效果(1.构建ImageGetter;2.直接使用append进行追加)        tv = (TextView) findViewById(R.id.image_effect);        tv.setText(R.string.image_effect);        // 通过HTML标记获得res目录下指定的图片        ImageGetter imageGetter = new ImageGetter() {            @Override            public Drawable getDrawable(String source) {                int id = Integer.parseInt(source);                // 根据id从资源文件中获取图片对象                Drawable d = getResources().getDrawable(id);                d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());                return d;            }        };        tv.append(Html.fromHtml("<img src='" + R.drawable.log + "'/>",                imageGetter, null));    }    Timer timer = new Timer();    TimerTask task_neon = new TimerTask() {        public void run() {            Message message = new Message();            message.what = 1;            handler.sendMessage(message);        }    };    final Handler handler = new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case 1:                // 霓虹灯效果                TextView tv = (TextView) findViewById(R.id.neonlights_effect);                String neontext = getString(R.string.neonlights_effect);                int len = neontext.length();                int colorsize = colors.length;                List<Map<String, Object>> data = new ArrayList<Map<String, Object>>();                for (int i = 0; i < len; i++) {                    int index = currColor + i;// 颜色索引                    if (index >= colorsize)                        index = index % colorsize;                    Map<String, Object> target = new HashMap<String, Object>();                    target.put("content", neontext.substring(i, i + 1));                    target.put("color", colors[index]);                    data.add(target);                }                currColor++;                if (currColor == colorsize)                    currColor = 0;                tv.setText(SpannableStringBuilderUtils                        .highlight(neontext, data));                break;            }            super.handleMessage(msg);        }    };    protected void onDestroy() {        if (timer != null) {            timer.cancel();            timer = null;        }        super.onDestroy();    }}
复制代码

9>SpannableStringBuilderUtils.java

复制代码
package com.bravestarr.app.utils;import java.util.List;import java.util.Map;import java.util.regex.Matcher;import java.util.regex.Pattern;import android.text.Spannable;import android.text.SpannableStringBuilder;import android.text.style.ForegroundColorSpan;/** * @Author    BraveStarr * @QQ        1733259520 * @Blog    http://www.cnblogs.com/bravestarrhu/,http://blog.sina.com.cn/wanghubravestarr *     * SpannableStringBuilder助手类 */public class SpannableStringBuilderUtils {        /**     * 指定内容高亮显示(此方法缺点:变色目标文字有多处匹配时效果不好)     * @param wholeContent    文本内容     * @param data    Map<String, Object>数组包含"content"和"color"字段     * @return     *      * 如何使用     *      * String content = "文本框局部改变颜色"     * List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();                                Map<String, Object> target = null;                target = new HashMap<String, Object>();                target.put("content", "改变");//指定要改变颜色的内容                target.put("color", Color.RED);//指定颜色                data.add(target);                                textview.setText(highlight(content, data));     */    public static SpannableStringBuilder highlight(String wholeContent,            List<Map<String, Object>> data) {        SpannableStringBuilder spannable = new SpannableStringBuilder(                wholeContent);        for (Map<String, Object> targetdata : data) {            Pattern p = Pattern.compile(targetdata.get("content").toString());            Matcher m = p.matcher(wholeContent);            while (m.find()) {                spannable.setSpan(                        new ForegroundColorSpan(Integer.valueOf(targetdata.get("color").toString())),                        m.start(), m.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);            }        }        return spannable;    }        /**     *      * @param wholeContent 文本内容     * @param data Map<String, Object>数组包含"start"、"end"和"color"字段     * @return     * 如何使用     *      * String content = "文本框局部改变颜色"     * List<Map<String, Object>> data = new ArrayList<Map<String,Object>>();                                Map<String, Object> target = new HashMap<String, Object>();                target.put("start", "5");//指定要改变颜色的起始位置                target.put("end", "7");//指定要改变颜色的结束位置                target.put("color", Color.RED);//指定颜色                data.add(target);                                textview.setText(subHighlight(content, data));     */    public static SpannableStringBuilder subHighlight(String wholeContent,            List<Map<String, Object>> data) {        SpannableStringBuilder spannable = new SpannableStringBuilder(                wholeContent);        for (Map<String, Object> targetdata : data) {            int color = Integer.valueOf(targetdata.get("color").toString());            int start = Integer.valueOf(targetdata.get("start").toString());            int end = Integer.valueOf(targetdata.get("end").toString());            spannable.setSpan(new ForegroundColorSpan(color), start,                    end, Spannable.SPAN_EXCLUSIVE_INCLUSIVE); // 设置指定位置文字的颜色(索引0开始)        }        return spannable;    }}
复制代码

附件下载:

apk安装包下载

源码打包下载

补充:连续动画实现,比如一个文本框在屏幕最底部,然后向上冒出,停留一会后,再向下移出屏幕

关键代码如下:

1.给指定的文本框设置内容(含图片)

tip = (TextView)findViewById(R.id.tip);
   tip.setText("按下");
   ImageGetter imageGetter = new ImageGetter() {
       @Override
       public Drawable getDrawable(String source) {
           int id = Integer.parseInt(source);
           // 根据id从资源文件中获取图片对象
           Drawable d = getResources().getDrawable(id);
           d.setBounds(0,0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
           return d;
       }
   };
    
   tip.append(Html.fromHtml("<img src='" + R.drawable.back_image + "'/>",
           imageGetter,null));
   tip.append("可取消测速并返回选区界面");

 2.

复制代码
  private TextView tip;    private int currStatus;//当前状态,UP,STAY ,或DOWN    private static final int UP = 1;//向上移动状态    private static final int STAY =2;//停留状态    private static final int DOWN = 3;//向下移动状态    private static final int UP_TIME = 2*1000;//向上移动用时    private static final int STAY_TIME = 3*1000;//到达目标后停留用时    private static final int DOWN_TIME = 2*1000;//向下移动用时        private int time;//(某)动画的运行时间  /**     * 更新移动的当前状态     */    private void updateCurrStatus(){        if(currStatus<3){            currStatus++;        }else{            currStatus = 1;        }    }        /**     * 移动动画处理     * @param StartX     * @param StartY     * @param EndX     * @param EndY     */    private void moveTip(int StartX,int StartY,int EndX,int EndY){                TranslateAnimation translateAnimation = new TranslateAnimation(StartX,EndX,StartY,EndY);        translateAnimation.setAnimationListener(new AnimationListener() {                        @Override            public void onAnimationStart(Animation animation) {            }                       @Override            public void onAnimationRepeat(Animation animation) {            }                       @Override            public void onAnimationEnd(Animation animation) {                updateCurrStatus();                //在动画结束时,重新启动动画                switch(currStatus){                case UP:                    time=STAY_TIME;          //此处的68为tip文本框的背景图的高                    moveTip(0, -68, 0, -68);                    break;                case STAY:                    time = DOWN_TIME;                    moveTip(0, -68, 0, 0);                    break;                case DOWN:                    break;                }                            }    });        translateAnimation.setDuration(time);        tip.startAnimation(translateAnimation);    }
复制代码

3.(onCreate()方法中)启动动画时调用如下代码

time = UP_TIME;
moveTip(0,0,0,-68);<span style="color: #000000;"><span style="color: #008000;">//此处的68为tip文本框的背景图的高</span></span>
原创粉丝点击