Qt for android模仿优酷菜单与android原生比较

1.效果如下图

说明:该例子是我最近学习android时的一个小例子,目前再看的android教程为尚硅谷的入门教程。链接:https://www.gulixueyuan.com/course/124/task/1893/show

从截图效果来看有一个有些卡顿,但是实际操作的时候并看不出来两者有任何区别,都比较流畅。下面只介绍Qt for android的流程。如果想要android 源码和图片资源可以联系我QQ:1024847801。

2.Qt QML 开发移动端界面关于宽高的定义

为了达到和android原生一样的效果,我一直再寻找如何让qml写出的界面和android的一样。搜了好多相关文章,试了好多,最后发现直接写宽高就行。不需要做任何转换。

android中xml的尺寸:

 <RelativeLayout
        android:id="@+id/layout_level3"
        android:layout_width="280dp"
        android:layout_height="140dp"
        android:layout_centerHorizontal="true"
        android:layout_alignParentBottom="true"
        android:background="@drawable/level3" >

Qt中,QML与之相对应的控件宽高

 Item {
        id: level3Item
        width: 280 ; //和android的值一样
        height: 140 ;//和android的值一样
        anchors.horizontalCenter: parent.horizontalCenter;
        anchors.bottom: parent.bottom;
        state: "NORMAL3"
}

这是最外层那个大半圆环的背景图片。宽和高与android保持一样即可。

3.qt 书写动画的代码与android比较

在android中,添加动画的代码为:

    public static void hideView(ViewGroup view , int startOffset) {
        //利用属性动画解决
        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
        ObjectAnimator animatorRotate =ObjectAnimator.ofFloat(view , "rotation" , 0 , 180);
        animatorRotate.setDuration(500);
        animatorRotate.setStartDelay(startOffset);
        animatorRotate.start();

    }

    public static void showView(ViewGroup view , int startOffset) {

        view.setPivotX(view.getWidth()/2);
        view.setPivotY(view.getHeight());
        ObjectAnimator animatorRotate =ObjectAnimator.ofFloat(view , "rotation" , 180 , 360);
        animatorRotate.setDuration(500);
        animatorRotate.setStartDelay(startOffset);
        animatorRotate.start();
    }

Qt中的代码为:

  states: [State {
                name: "NORMAL3"
                PropertyChanges { target: level3Item; rotation: 360; transformOrigin: Item.Bottom }
            },

            State {
                name: "ROTATED3";
                PropertyChanges { target: level3Item; rotation:180 ; transformOrigin: Item.Bottom }
            }
        ]

        transitions: Transition {
            SequentialAnimation {
                PauseAnimation { duration: isShowLevel2 ? 100 : (isShowLevel1 ? 80 : 200) }
                RotationAnimation { duration: 500; direction: RotationAnimation.Clockwise }
            }
        }


//状态切换响应:
  if( isShowLevel3 ) {
                            level3Item.state = "ROTATED3"
                            isShowLevel3 = false;
                        } else {
                            level3Item.state = "NORMAL3"
                            isShowLevel3 = true;
                        }

                    }

4. Qt 捕获android下的Back按键并传给Qt

android原生代码:

public boolean onKeyDown(int keyCode, KeyEvent event) {

        if( keyCode == KeyEvent.KEYCODE_BACK ) {
            //如果一级、二级、三级菜单显示,就隐藏
            if ( isShowLevel1 ) {
                isShowLevel1 = false;
                Tools.hideView(level1);

                if ( isShowLevel2 ) {
                    isShowLevel2 = false;
                    Tools.hideView(level2 , 200);
                }

                if ( isShowLevel3 ) {
                    isShowLevel3 = false;
                    Tools.hideView(level3 , 400);
                }

            } else {
                //如果一级二级隐藏就显示
                isShowLevel1 = true;
                Tools.showView(level1);

                if ( !isShowLevel2 ) {
                    isShowLevel2 = true;
                    Tools.showView(level2 , 200);
                }
            }

            return true;
        }

        return super.onKeyDown(keyCode, event);
    }

Qt捕获android下back按键的代码:通过jni注册回调来实现。

4.1 首先写一个java类

package com.lsy.youku_menu;



import org.qtproject.qt5.android.bindings.QtApplication;

//tommego
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.KeyEvent;
//屏幕像素密度
import android.util.DisplayMetrics;

//蓝牙 开关
import android.bluetooth.BluetoothAdapter;

public class Screen extends org.qtproject.qt5.android.bindings.QtActivity{
    private static Screen m_instance;//单例对象
    private static BluetoothAdapter m_bluetoothAdapter;//蓝牙控制对象
    public Screen(){
        m_instance = this;//实例化单例对象


        m_bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();


        if (!m_bluetoothAdapter.isEnabled()){
            //打开蓝牙
            m_bluetoothAdapter.enable();

        }
    }
    //获取屏幕像素密度
    public static double getDentisy(){
        DisplayMetrics metrics=new DisplayMetrics();
        m_instance.getWindowManager().getDefaultDisplay().getMetrics(metrics);
        return metrics.density;
//        return 3;
    }




//按键捕获只需要关注下面,上面是测试像素密度的。
    public  native void OnESCdown();


@Override
   public boolean onKeyDown(int keyCode, KeyEvent event)
   {
       int newKeyCode = keyCode;
       if ( (keyCode == KeyEvent.KEYCODE_BACK) )
       {
           OnESCdown();//通知<调用>C++层的 onEscDown函数
           newKeyCode = KeyEvent.KEYCODE_MEDIA_PREVIOUS;
       }

       if (QtApplication.m_delegateObject != null && QtApplication.onKeyDown != null) {
            Log.e("TAG" , "back.................newKeyCode"+newKeyCode);
           return (Boolean)QtApplication.invokeDelegateMethod(QtApplication.onKeyDown, newKeyCode,event);
       }
       else
           return super.onKeyDown(newKeyCode, event);
   }

}

4.2.写一个C++类,并注册函数OnESCdown。

void  DeviceScreen::RegJni()
{

    static const JNINativeMethod methods[] {
        { "OnESCdown", "()V", (void*)onEscDown }
    };



    qDebug()<<"RegisterNatives   0***********";
    qDebug()<<"RegisterNatives   1***********";

    const char* kClassName ="com/lsy/youku_menu/Screen";


    QtAndroid::runOnAndroidThreadSync([=](){

        QAndroidJniEnvironment qtEnv;
        jclass clazz;
        JNIEnv *EV = qtEnv.operator ->();

        clazz =EV->FindClass(kClassName);

        if (clazz == NULL)
        {
            qDebug()<<"erro   clazz";
            return ;
        }
        qDebug()<<"RegisterNatives   2***********";

        if (EV->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0])) != JNI_OK)
        {
            printf("register native method failed!\n");
            return;
        }else{
            qDebug()<<"RegisterNatives   搞定***********";
        }

    });

    //这里可以找到要注册的类,前提是这个类已经加载到java虚拟机中。 这里说明,动态库和有native方法的类之间,没有任何对应关系。

    //    QAndroidJniObject javaClass(kClassName);
    //        clazz = env->GetObjectClass(javaClass.object());
    //        qDebug() <<"find ExtendsQtNative"<< clazz;


    //EV->DeleteLocalRef(clazz);//删除引用避免内存泄漏
    qDebug()<<"RegisterNatives   OK***********";
}

void  DeviceScreen::onEscDown()
{
    qDebug()<<"C++ onEscDown";
    device->emitSignal();
}

然后在运行的时候按下back按键,就会调用onEscDown()函数,然后再通知到QML

 Connections{
        target: mydevice;

        function onOnBackKeyChanged() {
            //如果1、2、3都显示,则全部隐藏
            if ( isShowLevel1 ) {
                level1Item.state = "ROTATED"
                isShowLevel1 = false;

                if( isShowLevel2 ) {
                    level2Item.state = "ROTATED2"
                    isShowLevel2 = false;
                }

                if ( isShowLevel3 ) {
                    level3Item.state = "ROTATED3"
                    isShowLevel3 = false;
                }

            } else {
                level1Item.state = "NORMAL"
                isShowLevel1 = true;

                level2Item.state = "NORMAL2"
                isShowLevel2 = true;
            }
        }
    }

运行效果请看开头,打印如下:

由于时间原因写的比较仓促。

经过比较,Qt开发android还是需要懂一些android开发。最好系统的学习下android开发然后再学习JNI相关知识。Qt for android 路还是很长的。 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Liu-Eleven

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值